blvm-consensus 0.1.12

Bitcoin Commons BLVM: Direct mathematical implementation of Bitcoin consensus rules from the Orange Paper
Documentation
//! blvm-secp256k1 backend implementation.

use crate::error::{ConsensusError, Result};
use crate::types::Hash;
use blvm_secp256k1::ecdsa::{ecdsa_sig_parse_compact, ecdsa_sig_verify, ge_from_compressed};
use blvm_secp256k1::scalar::Scalar;
use blvm_secp256k1::schnorr::{schnorr_verify, schnorr_verify_batch};
use blvm_secp256k1::taproot::taproot_output_key as blvm_taproot_output_key;

pub fn verify_ecdsa(
    msg_hash: &[u8; 32],
    sig_compact: &[u8; 64],
    pubkey_compressed: &[u8; 33],
) -> Result<bool> {
    let (sigr, sigs) = match ecdsa_sig_parse_compact(sig_compact) {
        Some(s) => s,
        None => return Ok(false),
    };
    let pk = match ge_from_compressed(pubkey_compressed) {
        Some(p) => p,
        None => return Ok(false),
    };
    let mut msg = Scalar::zero();
    msg.set_b32(msg_hash);
    Ok(ecdsa_sig_verify(&sigr, &sigs, &pk, &msg))
}

pub fn verify_schnorr(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> Result<bool> {
    Ok(schnorr_verify(sig, msg, pubkey))
}

pub fn verify_schnorr_batch(
    sigs: &[[u8; 64]],
    msgs: &[&[u8]],
    pubkeys: &[[u8; 32]],
) -> Result<Vec<bool>> {
    let n = sigs.len().min(msgs.len()).min(pubkeys.len());
    if n == 0 {
        return Ok(Vec::new());
    }
    let ok = schnorr_verify_batch(sigs, msgs, pubkeys);
    if ok {
        Ok(vec![true; n])
    } else {
        let mut results = Vec::with_capacity(n);
        for i in 0..n {
            results.push(schnorr_verify(&sigs[i], msgs[i], &pubkeys[i]));
        }
        Ok(results)
    }
}

pub fn taproot_output_key(internal_pubkey: &[u8; 32], merkle_root: &Hash) -> Result<[u8; 32]> {
    blvm_taproot_output_key(internal_pubkey, merkle_root)
        .ok_or_else(|| ConsensusError::InvalidSignature("Invalid internal public key".into()))
}