use std::collections::HashMap;
use std::str::FromStr;
use bitcoin::blockdata::witness::Witness;
use bitcoin::{secp256k1, PackedLockTime, Sequence};
fn main() {
let mut tx = spending_transaction();
let pks = list_of_three_arbitrary_public_keys();
let sig = random_signature_from_the_blockchain();
let s = format!("wsh(multi(2,{},{},{}))", pks[0], pks[1], pks[2],);
let descriptor = miniscript::Descriptor::<bitcoin::PublicKey>::from_str(&s).unwrap();
assert_eq!(descriptor.max_satisfaction_weight().unwrap(), 258);
assert_eq!(
format!("{:x}", descriptor.script_pubkey()),
"00200ed49b334a12c37f3df8a2974ad91ff95029215a2b53f78155be737907f06163"
);
assert_eq!(
format!(
"{:x}",
descriptor
.explicit_script()
.expect("wsh descriptors have unique inner script")
),
"52\
21020202020202020202020202020202020202020202020202020202020202020202\
21020102030405060708010203040506070801020304050607080000000000000000\
21030102030405060708010203040506070801020304050607080000000000000000\
53ae"
);
let original_txin = tx.input[0].clone();
let mut sigs = HashMap::<bitcoin::PublicKey, miniscript::bitcoin::EcdsaSig>::new();
assert!(descriptor.satisfy(&mut tx.input[0], &sigs).is_err());
assert_eq!(tx.input[0], original_txin);
sigs.insert(pks[1], sig);
assert!(descriptor.satisfy(&mut tx.input[0], &sigs).is_err());
assert_eq!(tx.input[0], original_txin);
sigs.insert(pks[2], sig);
assert!(descriptor.satisfy(&mut tx.input[0], &sigs).is_ok());
assert_ne!(tx.input[0], original_txin);
assert_eq!(tx.input[0].witness.len(), 4);
sigs.insert(pks[0], sig);
assert!(descriptor.satisfy(&mut tx.input[0], &sigs).is_ok());
assert_ne!(tx.input[0], original_txin);
assert_eq!(tx.input[0].witness.len(), 4); }
fn spending_transaction() -> bitcoin::Transaction {
bitcoin::Transaction {
version: 2,
lock_time: PackedLockTime::ZERO,
input: vec![bitcoin::TxIn {
previous_output: Default::default(),
script_sig: bitcoin::Script::new(),
sequence: Sequence::MAX,
witness: Witness::default(),
}],
output: vec![bitcoin::TxOut {
script_pubkey: bitcoin::Script::new(),
value: 100_000_000,
}],
}
}
fn list_of_three_arbitrary_public_keys() -> Vec<bitcoin::PublicKey> {
#[cfg_attr(feature="cargo-fmt", rustfmt_skip)]
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"),
]
}
fn random_signature_from_the_blockchain() -> bitcoin::EcdsaSig {
bitcoin::EcdsaSig {
sig: secp256k1::ecdsa::Signature::from_str(
"3045\
0221\
00f7c3648c390d87578cd79c8016940aa8e3511c4104cb78daa8fb8e429375efc1\
0220\
531d75c136272f127a5dc14acc0722301cbddc222262934151f140da345af177",
)
.unwrap(),
hash_ty: bitcoin::EcdsaSighashType::All,
}
}