Tuesday, November 5, 2024

taproot – “non-mandatory-script-verify-flag (Invalid Schnorr signature)” error regardless of profitable Schnorr signature verification?

I’m engaged on verifying a Schnorr signature for a Bitcoin transaction, and regardless of the signature verification succeeding, I am encountering the next error when broadcasting the transaction:

Standing Err("RPC error: Object {"code": Quantity(-26), "message": String("non-mandatory-script-verify-flag (Invalid Schnorr signature)")}")

Listed here are the main points of my transaction:

Unsigned Transaction Hex:

0200000000010274e1be2d0692b65bd22f61ab77af5840446529bb43c21f99d86461250126563e0000000000ffffffffc68b4cfa8bda7eb1f473b0c42c51bde3d62df313416b090bebc9b8f36b1c48250000000000ffffffff0417270000000000002251200ea2746ae09dfcd1bfbf0f1bc819f7d1192c8fefd65d4ce3a0f510737a18d61a10270000000000002251207c019aba4fe8376b2ca2e4afa89c6a995d973ae55039a505badf55cb3b8fd21b6ad0029500000000225120b8df80071cd758e45bb1345559936864c6ba38bb78663eb13e96b56a459ef3520000000000000000096a5d06008b01016301000247304402204317d0cbaa1f264f536ba1bca4fa66d8c5a54228b8935065f7bee4dc3f7ce32f02205ef2ae85228797824f3ad1e94ec6662992a3a83dcb485a638e7ba5843a8f24b4012102787804fc6954ad0777e2e0717ed775e5344bb9da6307c1d3f3b4df642782622b00000000

Signed Transaction Hex:

0200000000010274e1be2d0692b65bd22f61ab77af5840446529bb43c21f99d86461250126563e0000000000ffffffffc68b4cfa8bda7eb1f473b0c42c51bde3d62df313416b090bebc9b8f36b1c48250000000000ffffffff0417270000000000002251200ea2746ae09dfcd1bfbf0f1bc819f7d1192c8fefd65d4ce3a0f510737a18d61a10270000000000002251207c019aba4fe8376b2ca2e4afa89c6a995d973ae55039a505badf55cb3b8fd21b6ad0029500000000225120b8df80071cd758e45bb1345559936864c6ba38bb78663eb13e96b56a459ef3520000000000000000096a5d06008b0101630101407032ca6ad2a3e473f03dd594d9b071ff22bb12e2da4648d33e89a898e4fbd0c423f14a4ddf13f083413877487bc868ae8affb9f9a672bf54197c5b17391409a40247304402204317d0cbaa1f264f536ba1bca4fa66d8c5a54228b8935065f7bee4dc3f7ce32f02205ef2ae85228797824f3ad1e94ec6662992a3a83dcb485a638e7ba5843a8f24b4012102787804fc6954ad0777e2e0717ed775e5344bb9da6307c1d3f3b4df642782622b00000000

I’ve verified the Schnorr signature utilizing the suitable sighash, and all the pieces checks out. But, when I attempt to broadcast the transaction, I obtain the above RPC error.

What could possibly be inflicting this error, and the way can I resolve it?

Further Context:

  • I am working with SegWit v1 Taproot outputs.
  • The signature verification course of makes use of the right sighash.
  • The nLockTime and nSequence fields are correctly set.

Any insights or ideas could be tremendously appreciated!

Code to generate signature and confirm


pub fn sign_transaction(
    tx: &mut Transaction,
    priv_key: &PrivateKey,
    mpc_group_pub_key: String,
    funding_script: String,
) -> Consequence<Transaction, String> {

    let secp = Secp256k1::new();

    // Create sighasher utilizing a mutable reference to tx as a substitute of cloning it.
    let mut sighasher = SighashCache::new(tx.clone());
    //Vault Pub Key
    println!("MPC key :{:?}",mpc_group_pub_key);
    let prev_out_1 = ScriptBuf::from_hex(&format!("5120{}", mpc_group_pub_key)).unwrap();

    let prev_out_2 = ScriptBuf::from_hex(&funding_script).unwrap();

    // Outline earlier UTXOs
    let prev_utxo_0 = TxOut {
        worth: 10007,
        script_pubkey: prev_out_1,
    };

    let prev_utxo_1 = TxOut {
        //   worth: tx.output.get(1).unwrap().worth,
        worth: 2500000000,
        script_pubkey: prev_out_2,
    };

    let prev_utxo = vec![prev_utxo_0, prev_utxo_1];
    let prevouts: bdk::bitcoin::psbt::Prevouts<_> = Prevouts::All(&prev_utxo);

    let sighash: bdk::bitcoin::sighash::TapSighash = sighasher
        .taproot_key_spend_signature_hash(
            0,
            &prevouts,
            bdk::bitcoin::sighash::TapSighashType::Default,
        )
        .map_err(|e| e.to_string())?;

    let msg = Message::from(sighash);


    // Signal the sighash utilizing the secp256k1 library (exported by rust-bitcoin).
    let key_pair = KeyPair::from_secret_key(&secp, &priv_key.inside);


    let signature = secp.sign_schnorr_no_aux_rand(&msg, &key_pair);


    // Replace the witness stack.
    let signature = Signature {
        sig: signature,
        hash_ty: bdk::bitcoin::sighash::TapSighashType::Default,
    };
    println!("Signature :{:?}", hex::encode(signature.to_vec()));

    let witness = sighasher.witness_mut(0).ok_or("Did not get witness")?;
    witness.push(&signature.to_vec());
   
    Okay(sighasher.into_transaction().clone())
}
let sk = SecretKey::from_str("8756415bbbbf1ce134ca7b97e2ca584cb52150783cb37f78cc41ccc7aacc10f1").unwrap();

let secp = Secp256k1::new();
let hex_msg = "0b5d2c9103c794eec24dd3dbbbfc8c8efc377d3fd613b958bdfc9d649166dc5f";
let msg = bdk::bitcoin::secp256k1::Message::from_slice(&hex::decode(hex_msg).unwrap()).unwrap();
let sig = bdk::bitcoin::secp256k1::schnorr::Signature::from_slice(&hex::decode("b9ca544040e9dee3b547b5c781ae13d15a5b20369e522b684c240a9e353b9b4bde1bca69642963801b33dd8ecc50c8714cfa4bb386390a867baabafde59dfd30").unwrap()).unwrap();

let pubkey = bdk::bitcoin::key::PublicKey::from_str("020ea2746ae09dfcd1bfbf0f1bc819f7d1192c8fefd65d4ce3a0f510737a18d61a").unwrap();

println!("Standing {}", secp.verify_schnorr(&sig, &msg, &pubkey.to_x_only_pubkey()).is_ok());

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles