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
andnSequence
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());