// // https://github.com/apoelstra/rust-miniscript/blob/master/examples/sign_multisig.rs // // Miniscript // // Written in 2019 by // // Andrew Poelstra // // // // To the extent possible under law, the author(s) have dedicated all // // copyright and related and neighboring rights to this software to // // the public domain worldwide. This software is distributed without // // any warranty. // // // // You should have received a copy of the CC0 Public Domain Dedication // // along with this software. // // If not, see . // // // // //! Example: Signing a 2-of-3 multisignature // // use bdk::bitcoin; // use bdk::bitcoin::secp256k1; // secp256k1 re-exported from rust-bitcoin // use miniscript; // use miniscript::DescriptorTrait; // use std::collections::HashMap; // use std::str::FromStr; // // #[test] // fn main() { // // Avoid repeatedly typing a pretty-common descriptor type // type BitcoinDescriptor = miniscript::Descriptor; // // // Transaction which spends some output // let mut tx = bitcoin::Transaction { // version: 2, // lock_time: 0, // input: vec![bitcoin::TxIn { // previous_output: Default::default(), // script_sig: bitcoin::Script::new(), // sequence: 0xffffffff, // witness: vec![], // }], // output: vec![bitcoin::TxOut { // script_pubkey: bitcoin::Script::new(), // value: 100_000_000, // }], // }; // // #[cfg_attr(feature="cargo-fmt", rustfmt_skip)] // let public_keys = vec![ // bitcoin::PublicKey::from_slice(&[2; 33]).expect("key 1"), // bitcoin::PublicKey::from_slice(&[ // 0x02, // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ]).expect("key 2"), // bitcoin::PublicKey::from_slice(&[ // 0x03, // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ]).expect("key 3"), // ]; // let bitcoin_sig = ( // // copied at random off the blockchain; this is not actually a valid // // signature for this transaction; Miniscript does not verify // secp256k1::Signature::from_str( // "3045\ // 0221\ // 00f7c3648c390d87578cd79c8016940aa8e3511c4104cb78daa8fb8e429375efc1\ // 0220\ // 531d75c136272f127a5dc14acc0722301cbddc222262934151f140da345af177", // ) // .unwrap(), // bitcoin::SigHashType::All, // ); // // let descriptor_str = format!( // "wsh(multi(2,{},{},{}))", // public_keys[0], public_keys[1], public_keys[2], // ); // // // Descriptor for the output being spent // let my_descriptor = // BitcoinDescriptor::from_str(&descriptor_str[..]).expect("parse descriptor string"); // // // Check weight for witness satisfaction cost ahead of time. // // 4(scriptSig length of 0) + 1(witness stack size) + 106(serialized witnessScript) // // + 73*2(signature length + signatures + sighash bytes) + 1(dummy byte) = 258 // assert_eq!(my_descriptor.max_satisfaction_weight().unwrap(), 258); // // // Sometimes it is necessary to have additional information to get the bitcoin::PublicKey // // from the MiniscriptKey which can supplied by `to_pk_ctx` parameter. For example, // // when calculating the script pubkey of a descriptor with xpubs, the secp context and // // child information maybe required. // // // Observe the script properties, just for fun // assert_eq!( // format!("{:x}", my_descriptor.script_pubkey()), // "00200ed49b334a12c37f3df8a2974ad91ff95029215a2b53f78155be737907f06163" // ); // // assert_eq!( // format!("{:x}", my_descriptor.explicit_script()), // "52\ // 21020202020202020202020202020202020202020202020202020202020202020202\ // 21020102030405060708010203040506070801020304050607080000000000000000\ // 21030102030405060708010203040506070801020304050607080000000000000000\ // 53ae" // ); // // // Attempt to satisfy at age 0, height 0 // let original_txin = tx.input[0].clone(); // // let mut sigs = HashMap::::new(); // // // Doesn't work with no signatures // assert!(my_descriptor.satisfy(&mut tx.input[0], &sigs).is_err()); // assert_eq!(tx.input[0], original_txin); // // // ...or one signature... // sigs.insert(public_keys[1], bitcoin_sig); // assert!(my_descriptor.satisfy(&mut tx.input[0], &sigs).is_err()); // assert_eq!(tx.input[0], original_txin); // // // ...but two signatures is ok // sigs.insert(public_keys[2], bitcoin_sig); // assert!(my_descriptor.satisfy(&mut tx.input[0], &sigs).is_ok()); // assert_ne!(tx.input[0], original_txin); // assert_eq!(tx.input[0].witness.len(), 4); // 0, sig, sig, witness script // // // ...and even if we give it a third signature, only two are used // sigs.insert(public_keys[0], bitcoin_sig); // assert!(my_descriptor.satisfy(&mut tx.input[0], &sigs).is_ok()); // assert_ne!(tx.input[0], original_txin); // assert_eq!(tx.input[0].witness.len(), 4); // 0, sig, sig, witness script // }