Struct Interpreter

Source
pub struct Interpreter<'txin> { /* private fields */ }
Expand description

An iterable Miniscript-structured representation of the spending of a coin

Implementations§

Source§

impl<'txin> Interpreter<'txin>

Source

pub fn from_txdata( spk: &Script, script_sig: &'txin Script, witness: &'txin Witness, age: u32, height: u32, txtemplate: Hash, ) -> Result<Self, Error>

Constructs an interpreter from the data of a spending transaction

Accepts a signature-validating function. If you are willing to trust that ECSDA signatures are valid, this can be set to the constant true function; otherwise, it should be a closure containing a sighash and secp context, which can actually verify a given signature.

Examples found in repository?
examples/verify_tx.rs (lines 89-97)
27fn main() {
28    // tx `f27eba163c38ad3f34971198687a3f1882b7ec818599ffe469a8440d82261c98`
29    #[cfg_attr(feature="cargo-fmt", rustfmt_skip)]
30    let tx_bytes = vec![
31        0x01, 0x00, 0x00, 0x00, 0x02, 0xc5, 0x11, 0x1d, 0xb7, 0x93, 0x50, 0xc1,
32        0x70, 0x28, 0x41, 0x39, 0xe8, 0xe3, 0x4e, 0xb0, 0xed, 0xba, 0x64, 0x7b,
33        0x6c, 0x88, 0x7e, 0x9f, 0x92, 0x8f, 0xfd, 0x9b, 0x5c, 0x4a, 0x4b, 0x52,
34        0xd0, 0x01, 0x00, 0x00, 0x00, 0xda, 0x00, 0x47, 0x30, 0x44, 0x02, 0x20,
35        0x1c, 0xcc, 0x1b, 0xe9, 0xaf, 0x73, 0x4a, 0x10, 0x9f, 0x66, 0xfb, 0xed,
36        0xeb, 0x77, 0xb7, 0xa1, 0xf4, 0xb3, 0xc5, 0xff, 0x3d, 0x7f, 0x46, 0xf6,
37        0xde, 0x50, 0x69, 0xbb, 0x52, 0x7f, 0x26, 0x9d, 0x02, 0x20, 0x75, 0x37,
38        0x2f, 0x6b, 0xd7, 0x0c, 0xf6, 0x45, 0x7a, 0xc7, 0x0e, 0x82, 0x6f, 0xc6,
39        0xa7, 0x5b, 0xf7, 0xcf, 0x10, 0x8c, 0x92, 0xea, 0xcf, 0xfc, 0xb5, 0xd9,
40        0xfd, 0x77, 0x66, 0xa3, 0x58, 0xa9, 0x01, 0x48, 0x30, 0x45, 0x02, 0x21,
41        0x00, 0xfe, 0x82, 0x5b, 0xe1, 0xd5, 0xfd, 0x71, 0x67, 0x83, 0xf4, 0x55,
42        0xef, 0xe6, 0x6d, 0x61, 0x58, 0xff, 0xf8, 0xc3, 0x2b, 0x93, 0x1c, 0x5f,
43        0x3f, 0xf9, 0x8e, 0x06, 0x65, 0xa9, 0xfd, 0x8e, 0x64, 0x02, 0x20, 0x22,
44        0x01, 0x0f, 0xdb, 0x53, 0x8d, 0x0f, 0xa6, 0x8b, 0xd7, 0xf5, 0x20, 0x5d,
45        0xc1, 0xdf, 0xa6, 0xc4, 0x28, 0x1b, 0x7b, 0xb7, 0x6f, 0xc2, 0x53, 0xf7,
46        0x51, 0x4d, 0x83, 0x48, 0x52, 0x5f, 0x0d, 0x01, 0x47, 0x52, 0x21, 0x03,
47        0xd0, 0xbf, 0x26, 0x7c, 0x93, 0x78, 0xb3, 0x18, 0xb5, 0x80, 0xc2, 0x10,
48        0xa6, 0x78, 0xc4, 0xbb, 0x60, 0xd8, 0x44, 0x8b, 0x52, 0x0d, 0x21, 0x25,
49        0xa1, 0xbd, 0x37, 0x2b, 0x23, 0xae, 0xa6, 0x49, 0x21, 0x02, 0x11, 0xa8,
50        0x2a, 0xa6, 0x94, 0x63, 0x99, 0x0a, 0x6c, 0xdd, 0x48, 0x36, 0x76, 0x36,
51        0x6a, 0x44, 0xac, 0x3c, 0x98, 0xe7, 0x68, 0x54, 0x69, 0x84, 0x0b, 0xf2,
52        0x7a, 0x72, 0x4e, 0x40, 0x5a, 0x7e, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff,
53        0xea, 0x51, 0x1f, 0x33, 0x7a, 0xf5, 0x72, 0xbb, 0xad, 0xcd, 0x2e, 0x03,
54        0x07, 0x71, 0x62, 0x3a, 0x60, 0xcc, 0x71, 0x82, 0xad, 0x74, 0x53, 0x3e,
55        0xa3, 0x2f, 0xc8, 0xaa, 0x47, 0xd2, 0x0e, 0x71, 0x01, 0x00, 0x00, 0x00,
56        0xda, 0x00, 0x48, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfa, 0x2b, 0xfb, 0x4d,
57        0x49, 0xb7, 0x6d, 0x9f, 0xb4, 0xc6, 0x9c, 0xc7, 0x8c, 0x36, 0xd2, 0x66,
58        0x92, 0x40, 0xe4, 0x57, 0x14, 0xc7, 0x19, 0x06, 0x85, 0xf7, 0xe5, 0x13,
59        0x94, 0xac, 0x4e, 0x37, 0x02, 0x20, 0x04, 0x95, 0x2c, 0xf7, 0x75, 0x1c,
60        0x45, 0x9d, 0x8a, 0x8b, 0x64, 0x76, 0x76, 0xce, 0x86, 0xf3, 0xbd, 0x69,
61        0xff, 0x39, 0x17, 0xcb, 0x99, 0x85, 0x14, 0xbd, 0x73, 0xb7, 0xfc, 0x04,
62        0xf6, 0x4c, 0x01, 0x47, 0x30, 0x44, 0x02, 0x20, 0x31, 0xae, 0x81, 0x1e,
63        0x35, 0x7e, 0x80, 0x00, 0x01, 0xc7, 0x57, 0x27, 0x7a, 0x22, 0x44, 0xa7,
64        0x2b, 0xd5, 0x9d, 0x0a, 0x00, 0xbe, 0xde, 0x49, 0x0a, 0x96, 0x12, 0x3e,
65        0x54, 0xce, 0x03, 0x4c, 0x02, 0x20, 0x05, 0xa2, 0x9f, 0x14, 0x30, 0x1e,
66        0x5e, 0x2f, 0xdc, 0x7c, 0xee, 0x49, 0x43, 0xec, 0x78, 0x78, 0xdf, 0x73,
67        0xde, 0x96, 0x27, 0x00, 0xa4, 0xd9, 0x43, 0x6b, 0xce, 0x24, 0xd6, 0xc3,
68        0xa3, 0x57, 0x01, 0x47, 0x52, 0x21, 0x03, 0x4e, 0x74, 0xde, 0x0b, 0x84,
69        0x3f, 0xaa, 0x60, 0x44, 0x3d, 0xf4, 0x76, 0xf1, 0xf6, 0x14, 0x4a, 0x5b,
70        0x0e, 0x76, 0x49, 0x9e, 0x8a, 0x26, 0x71, 0x07, 0x36, 0x5b, 0x32, 0xfa,
71        0xd5, 0xd0, 0xfd, 0x21, 0x03, 0xb4, 0xa6, 0x82, 0xc8, 0x6a, 0xd9, 0x06,
72        0x38, 0x8f, 0x99, 0x52, 0x76, 0xf0, 0x84, 0x92, 0x72, 0x3a, 0x8c, 0x5f,
73        0x32, 0x3c, 0x6a, 0xf6, 0x92, 0x97, 0x17, 0x40, 0x5d, 0x2e, 0x1b, 0x2f,
74        0x70, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff, 0x02, 0xa7, 0x32, 0x75, 0x01,
75        0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xfb, 0xf7, 0x76, 0xff,
76        0xeb, 0x3b, 0xb8, 0x89, 0xb2, 0x01, 0xa5, 0x3f, 0x5f, 0xb0, 0x55, 0x4f,
77        0x6e, 0x6f, 0xa2, 0x56, 0x88, 0xac, 0x19, 0x88, 0x56, 0x01, 0x00, 0x00,
78        0x00, 0x00, 0x17, 0xa9, 0x14, 0xd3, 0xb6, 0x1d, 0x34, 0xf6, 0x33, 0x7c,
79        0xd7, 0xc0, 0x28, 0xb7, 0x90, 0xb0, 0xcf, 0x43, 0xe0, 0x27, 0xd9, 0x1d,
80        0xe7, 0x87, 0x09, 0x5d, 0x07, 0x00,
81    ];
82    let transaction =
83        bitcoin::Transaction::consensus_decode(&mut &tx_bytes[..]).expect("decode transaction");
84
85    let spk_input_1 = bitcoin::Script::from(vec![
86        0xa9, 0x14, 0x92, 0x09, 0xa8, 0xf9, 0x0c, 0x58, 0x4b, 0xb5, 0x97, 0x4d, 0x58, 0x68, 0x72,
87        0x49, 0xe5, 0x32, 0xde, 0x59, 0xf4, 0xbc, 0x87,
88    ]);
89    let interpreter = miniscript::Interpreter::from_txdata(
90        &spk_input_1,
91        &transaction.input[0].script_sig,
92        &transaction.input[0].witness,
93        0,
94        0,
95        // TODO: Replace with actual hash
96        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
97    )
98    .unwrap();
99
100    let desc_string = interpreter.inferred_descriptor_string();
101    println!("Descriptor: {}", desc_string);
102    miniscript::Descriptor::<bitcoin::PublicKey>::from_str(&desc_string)
103        .expect("this descriptor can be reparsed with sanity checks passing");
104    interpreter
105        .inferred_descriptor()
106        .expect("we can use this method to do the above from_str for us");
107
108    // 1. Example one: learn which keys were used, not bothering
109    //    to verify the signatures (trusting that if they're on
110    //    the blockchain, standardness would've required they be
111    //    either valid or 0-length.
112    println!("\nExample one");
113    for elem in interpreter.iter_assume_sigs() {
114        // Don't bother checking signatures
115        match elem.expect("no evaluation error") {
116            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
117                // Check that the signature is ecdsa sig
118                let (key, sig) = key_sig
119                    .as_ecdsa()
120                    .expect("Expected Ecdsa sig, found schnorr sig");
121                println!("Signed with {}: {}", key, sig);
122            }
123            _ => {}
124        }
125    }
126
127    // 2. Example two: verify the signatures to ensure that invalid
128    //    signatures are not treated as having participated in the script
129    let secp = secp256k1::Secp256k1::new();
130    // Sometimes it is necessary to have additional information to get the bitcoin::PublicKey
131    // from the MiniscriptKey which can supplied by `to_pk_ctx` parameter. For example,
132    // when calculating the script pubkey of a descriptor with xpubs, the secp context and
133    // child information maybe required.
134    let interpreter = miniscript::Interpreter::from_txdata(
135        &spk_input_1,
136        &transaction.input[0].script_sig,
137        &transaction.input[0].witness,
138        0,
139        0,
140        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
141    )
142    .unwrap();
143
144    // We can set prevouts to be empty list because this is a legacy transaction
145    // and this information is not required for sighash computation.
146    let prevouts = sighash::Prevouts::All::<TxOut>(&[]);
147
148    println!("\nExample two");
149    for elem in interpreter.iter(&secp, &transaction, 0, &prevouts) {
150        match elem.expect("no evaluation error") {
151            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
152                let (key, sig) = key_sig.as_ecdsa().unwrap();
153                println!("Signed with {}: {}", key, sig);
154            }
155            _ => {}
156        }
157    }
158
159    // 3. Example three: same, but with the wrong signature hash, to demonstrate
160    //    what happens given an apparently invalid script
161    let secp = secp256k1::Secp256k1::new();
162    let message = secp256k1::Message::from_slice(&[0x01; 32][..]).expect("32-byte hash");
163    let interpreter = miniscript::Interpreter::from_txdata(
164        &spk_input_1,
165        &transaction.input[0].script_sig,
166        &transaction.input[0].witness,
167        0,
168        0,
169        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
170    )
171    .unwrap();
172
173    let iter = interpreter.iter_custom(Box::new(|key_sig: &KeySigPair| {
174        let (pk, ecdsa_sig) = key_sig.as_ecdsa().expect("Ecdsa Sig");
175        ecdsa_sig.hash_ty == bitcoin::EcdsaSighashType::All
176            && secp
177                .verify_ecdsa(&message, &ecdsa_sig.sig, &pk.inner)
178                .is_ok()
179    }));
180    println!("\nExample three");
181    for elem in iter {
182        let error = elem.expect_err("evaluation error");
183        println!("Evaluation error: {}", error);
184    }
185}
Source

pub fn iter_custom<'iter>( &'iter self, verify_sig: Box<dyn FnMut(&KeySigPair) -> bool + 'iter>, ) -> Iter<'txin, 'iter>

Same as Interpreter::iter, but allows for a custom verification function. See Self::iter_assume_sigs for a simpler API without information about Prevouts but skips the signature verification

Examples found in repository?
examples/verify_tx.rs (lines 173-179)
27fn main() {
28    // tx `f27eba163c38ad3f34971198687a3f1882b7ec818599ffe469a8440d82261c98`
29    #[cfg_attr(feature="cargo-fmt", rustfmt_skip)]
30    let tx_bytes = vec![
31        0x01, 0x00, 0x00, 0x00, 0x02, 0xc5, 0x11, 0x1d, 0xb7, 0x93, 0x50, 0xc1,
32        0x70, 0x28, 0x41, 0x39, 0xe8, 0xe3, 0x4e, 0xb0, 0xed, 0xba, 0x64, 0x7b,
33        0x6c, 0x88, 0x7e, 0x9f, 0x92, 0x8f, 0xfd, 0x9b, 0x5c, 0x4a, 0x4b, 0x52,
34        0xd0, 0x01, 0x00, 0x00, 0x00, 0xda, 0x00, 0x47, 0x30, 0x44, 0x02, 0x20,
35        0x1c, 0xcc, 0x1b, 0xe9, 0xaf, 0x73, 0x4a, 0x10, 0x9f, 0x66, 0xfb, 0xed,
36        0xeb, 0x77, 0xb7, 0xa1, 0xf4, 0xb3, 0xc5, 0xff, 0x3d, 0x7f, 0x46, 0xf6,
37        0xde, 0x50, 0x69, 0xbb, 0x52, 0x7f, 0x26, 0x9d, 0x02, 0x20, 0x75, 0x37,
38        0x2f, 0x6b, 0xd7, 0x0c, 0xf6, 0x45, 0x7a, 0xc7, 0x0e, 0x82, 0x6f, 0xc6,
39        0xa7, 0x5b, 0xf7, 0xcf, 0x10, 0x8c, 0x92, 0xea, 0xcf, 0xfc, 0xb5, 0xd9,
40        0xfd, 0x77, 0x66, 0xa3, 0x58, 0xa9, 0x01, 0x48, 0x30, 0x45, 0x02, 0x21,
41        0x00, 0xfe, 0x82, 0x5b, 0xe1, 0xd5, 0xfd, 0x71, 0x67, 0x83, 0xf4, 0x55,
42        0xef, 0xe6, 0x6d, 0x61, 0x58, 0xff, 0xf8, 0xc3, 0x2b, 0x93, 0x1c, 0x5f,
43        0x3f, 0xf9, 0x8e, 0x06, 0x65, 0xa9, 0xfd, 0x8e, 0x64, 0x02, 0x20, 0x22,
44        0x01, 0x0f, 0xdb, 0x53, 0x8d, 0x0f, 0xa6, 0x8b, 0xd7, 0xf5, 0x20, 0x5d,
45        0xc1, 0xdf, 0xa6, 0xc4, 0x28, 0x1b, 0x7b, 0xb7, 0x6f, 0xc2, 0x53, 0xf7,
46        0x51, 0x4d, 0x83, 0x48, 0x52, 0x5f, 0x0d, 0x01, 0x47, 0x52, 0x21, 0x03,
47        0xd0, 0xbf, 0x26, 0x7c, 0x93, 0x78, 0xb3, 0x18, 0xb5, 0x80, 0xc2, 0x10,
48        0xa6, 0x78, 0xc4, 0xbb, 0x60, 0xd8, 0x44, 0x8b, 0x52, 0x0d, 0x21, 0x25,
49        0xa1, 0xbd, 0x37, 0x2b, 0x23, 0xae, 0xa6, 0x49, 0x21, 0x02, 0x11, 0xa8,
50        0x2a, 0xa6, 0x94, 0x63, 0x99, 0x0a, 0x6c, 0xdd, 0x48, 0x36, 0x76, 0x36,
51        0x6a, 0x44, 0xac, 0x3c, 0x98, 0xe7, 0x68, 0x54, 0x69, 0x84, 0x0b, 0xf2,
52        0x7a, 0x72, 0x4e, 0x40, 0x5a, 0x7e, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff,
53        0xea, 0x51, 0x1f, 0x33, 0x7a, 0xf5, 0x72, 0xbb, 0xad, 0xcd, 0x2e, 0x03,
54        0x07, 0x71, 0x62, 0x3a, 0x60, 0xcc, 0x71, 0x82, 0xad, 0x74, 0x53, 0x3e,
55        0xa3, 0x2f, 0xc8, 0xaa, 0x47, 0xd2, 0x0e, 0x71, 0x01, 0x00, 0x00, 0x00,
56        0xda, 0x00, 0x48, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfa, 0x2b, 0xfb, 0x4d,
57        0x49, 0xb7, 0x6d, 0x9f, 0xb4, 0xc6, 0x9c, 0xc7, 0x8c, 0x36, 0xd2, 0x66,
58        0x92, 0x40, 0xe4, 0x57, 0x14, 0xc7, 0x19, 0x06, 0x85, 0xf7, 0xe5, 0x13,
59        0x94, 0xac, 0x4e, 0x37, 0x02, 0x20, 0x04, 0x95, 0x2c, 0xf7, 0x75, 0x1c,
60        0x45, 0x9d, 0x8a, 0x8b, 0x64, 0x76, 0x76, 0xce, 0x86, 0xf3, 0xbd, 0x69,
61        0xff, 0x39, 0x17, 0xcb, 0x99, 0x85, 0x14, 0xbd, 0x73, 0xb7, 0xfc, 0x04,
62        0xf6, 0x4c, 0x01, 0x47, 0x30, 0x44, 0x02, 0x20, 0x31, 0xae, 0x81, 0x1e,
63        0x35, 0x7e, 0x80, 0x00, 0x01, 0xc7, 0x57, 0x27, 0x7a, 0x22, 0x44, 0xa7,
64        0x2b, 0xd5, 0x9d, 0x0a, 0x00, 0xbe, 0xde, 0x49, 0x0a, 0x96, 0x12, 0x3e,
65        0x54, 0xce, 0x03, 0x4c, 0x02, 0x20, 0x05, 0xa2, 0x9f, 0x14, 0x30, 0x1e,
66        0x5e, 0x2f, 0xdc, 0x7c, 0xee, 0x49, 0x43, 0xec, 0x78, 0x78, 0xdf, 0x73,
67        0xde, 0x96, 0x27, 0x00, 0xa4, 0xd9, 0x43, 0x6b, 0xce, 0x24, 0xd6, 0xc3,
68        0xa3, 0x57, 0x01, 0x47, 0x52, 0x21, 0x03, 0x4e, 0x74, 0xde, 0x0b, 0x84,
69        0x3f, 0xaa, 0x60, 0x44, 0x3d, 0xf4, 0x76, 0xf1, 0xf6, 0x14, 0x4a, 0x5b,
70        0x0e, 0x76, 0x49, 0x9e, 0x8a, 0x26, 0x71, 0x07, 0x36, 0x5b, 0x32, 0xfa,
71        0xd5, 0xd0, 0xfd, 0x21, 0x03, 0xb4, 0xa6, 0x82, 0xc8, 0x6a, 0xd9, 0x06,
72        0x38, 0x8f, 0x99, 0x52, 0x76, 0xf0, 0x84, 0x92, 0x72, 0x3a, 0x8c, 0x5f,
73        0x32, 0x3c, 0x6a, 0xf6, 0x92, 0x97, 0x17, 0x40, 0x5d, 0x2e, 0x1b, 0x2f,
74        0x70, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff, 0x02, 0xa7, 0x32, 0x75, 0x01,
75        0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xfb, 0xf7, 0x76, 0xff,
76        0xeb, 0x3b, 0xb8, 0x89, 0xb2, 0x01, 0xa5, 0x3f, 0x5f, 0xb0, 0x55, 0x4f,
77        0x6e, 0x6f, 0xa2, 0x56, 0x88, 0xac, 0x19, 0x88, 0x56, 0x01, 0x00, 0x00,
78        0x00, 0x00, 0x17, 0xa9, 0x14, 0xd3, 0xb6, 0x1d, 0x34, 0xf6, 0x33, 0x7c,
79        0xd7, 0xc0, 0x28, 0xb7, 0x90, 0xb0, 0xcf, 0x43, 0xe0, 0x27, 0xd9, 0x1d,
80        0xe7, 0x87, 0x09, 0x5d, 0x07, 0x00,
81    ];
82    let transaction =
83        bitcoin::Transaction::consensus_decode(&mut &tx_bytes[..]).expect("decode transaction");
84
85    let spk_input_1 = bitcoin::Script::from(vec![
86        0xa9, 0x14, 0x92, 0x09, 0xa8, 0xf9, 0x0c, 0x58, 0x4b, 0xb5, 0x97, 0x4d, 0x58, 0x68, 0x72,
87        0x49, 0xe5, 0x32, 0xde, 0x59, 0xf4, 0xbc, 0x87,
88    ]);
89    let interpreter = miniscript::Interpreter::from_txdata(
90        &spk_input_1,
91        &transaction.input[0].script_sig,
92        &transaction.input[0].witness,
93        0,
94        0,
95        // TODO: Replace with actual hash
96        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
97    )
98    .unwrap();
99
100    let desc_string = interpreter.inferred_descriptor_string();
101    println!("Descriptor: {}", desc_string);
102    miniscript::Descriptor::<bitcoin::PublicKey>::from_str(&desc_string)
103        .expect("this descriptor can be reparsed with sanity checks passing");
104    interpreter
105        .inferred_descriptor()
106        .expect("we can use this method to do the above from_str for us");
107
108    // 1. Example one: learn which keys were used, not bothering
109    //    to verify the signatures (trusting that if they're on
110    //    the blockchain, standardness would've required they be
111    //    either valid or 0-length.
112    println!("\nExample one");
113    for elem in interpreter.iter_assume_sigs() {
114        // Don't bother checking signatures
115        match elem.expect("no evaluation error") {
116            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
117                // Check that the signature is ecdsa sig
118                let (key, sig) = key_sig
119                    .as_ecdsa()
120                    .expect("Expected Ecdsa sig, found schnorr sig");
121                println!("Signed with {}: {}", key, sig);
122            }
123            _ => {}
124        }
125    }
126
127    // 2. Example two: verify the signatures to ensure that invalid
128    //    signatures are not treated as having participated in the script
129    let secp = secp256k1::Secp256k1::new();
130    // Sometimes it is necessary to have additional information to get the bitcoin::PublicKey
131    // from the MiniscriptKey which can supplied by `to_pk_ctx` parameter. For example,
132    // when calculating the script pubkey of a descriptor with xpubs, the secp context and
133    // child information maybe required.
134    let interpreter = miniscript::Interpreter::from_txdata(
135        &spk_input_1,
136        &transaction.input[0].script_sig,
137        &transaction.input[0].witness,
138        0,
139        0,
140        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
141    )
142    .unwrap();
143
144    // We can set prevouts to be empty list because this is a legacy transaction
145    // and this information is not required for sighash computation.
146    let prevouts = sighash::Prevouts::All::<TxOut>(&[]);
147
148    println!("\nExample two");
149    for elem in interpreter.iter(&secp, &transaction, 0, &prevouts) {
150        match elem.expect("no evaluation error") {
151            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
152                let (key, sig) = key_sig.as_ecdsa().unwrap();
153                println!("Signed with {}: {}", key, sig);
154            }
155            _ => {}
156        }
157    }
158
159    // 3. Example three: same, but with the wrong signature hash, to demonstrate
160    //    what happens given an apparently invalid script
161    let secp = secp256k1::Secp256k1::new();
162    let message = secp256k1::Message::from_slice(&[0x01; 32][..]).expect("32-byte hash");
163    let interpreter = miniscript::Interpreter::from_txdata(
164        &spk_input_1,
165        &transaction.input[0].script_sig,
166        &transaction.input[0].witness,
167        0,
168        0,
169        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
170    )
171    .unwrap();
172
173    let iter = interpreter.iter_custom(Box::new(|key_sig: &KeySigPair| {
174        let (pk, ecdsa_sig) = key_sig.as_ecdsa().expect("Ecdsa Sig");
175        ecdsa_sig.hash_ty == bitcoin::EcdsaSighashType::All
176            && secp
177                .verify_ecdsa(&message, &ecdsa_sig.sig, &pk.inner)
178                .is_ok()
179    }));
180    println!("\nExample three");
181    for elem in iter {
182        let error = elem.expect_err("evaluation error");
183        println!("Evaluation error: {}", error);
184    }
185}
Source

pub fn verify_sig<C: Verification, T: Borrow<TxOut>>( &self, secp: &Secp256k1<C>, tx: &Transaction, input_idx: usize, prevouts: &Prevouts<'_, T>, sig: &KeySigPair, ) -> bool

Verify a signature for a given transaction and prevout information This is a low level API, Interpreter::iter or [Interpreter::iter_assume_sig] should satisfy most use-cases. Returns false if

  • the signature verification fails
  • the input index is out of range
  • Insufficient sighash information is present
  • sighash single without corresponding output
Source

pub fn iter<'iter, C: Verification, T: Borrow<TxOut>>( &'iter self, secp: &'iter Secp256k1<C>, tx: &'txin Transaction, input_idx: usize, prevouts: &'iter Prevouts<'_, T>, ) -> Iter<'txin, 'iter>

Creates an iterator over the satisfied spending conditions

Returns all satisfied constraints, even if they were redundant (i.e. did not contribute to the script being satisfied). For example, if a signature were provided for an and_b(Pk,false) fragment, that signature will be returned, even though the entire and_b must have failed and must not have been used.

In case the script is actually dissatisfied, this may return several values before ultimately returning an error.

Not all fields are used by legacy/segwitv0 descriptors; if you are sure this is a legacy spend (you can check with the is_legacy\is_segwitv0 method) you can provide dummy data for the amount/prevouts.

  • For legacy outputs, no information about prevouts is required
  • For segwitv0 outputs, prevout at corresponding index with correct amount must be provided
  • For taproot outputs, information about all prevouts must be supplied
Examples found in repository?
examples/verify_tx.rs (line 149)
27fn main() {
28    // tx `f27eba163c38ad3f34971198687a3f1882b7ec818599ffe469a8440d82261c98`
29    #[cfg_attr(feature="cargo-fmt", rustfmt_skip)]
30    let tx_bytes = vec![
31        0x01, 0x00, 0x00, 0x00, 0x02, 0xc5, 0x11, 0x1d, 0xb7, 0x93, 0x50, 0xc1,
32        0x70, 0x28, 0x41, 0x39, 0xe8, 0xe3, 0x4e, 0xb0, 0xed, 0xba, 0x64, 0x7b,
33        0x6c, 0x88, 0x7e, 0x9f, 0x92, 0x8f, 0xfd, 0x9b, 0x5c, 0x4a, 0x4b, 0x52,
34        0xd0, 0x01, 0x00, 0x00, 0x00, 0xda, 0x00, 0x47, 0x30, 0x44, 0x02, 0x20,
35        0x1c, 0xcc, 0x1b, 0xe9, 0xaf, 0x73, 0x4a, 0x10, 0x9f, 0x66, 0xfb, 0xed,
36        0xeb, 0x77, 0xb7, 0xa1, 0xf4, 0xb3, 0xc5, 0xff, 0x3d, 0x7f, 0x46, 0xf6,
37        0xde, 0x50, 0x69, 0xbb, 0x52, 0x7f, 0x26, 0x9d, 0x02, 0x20, 0x75, 0x37,
38        0x2f, 0x6b, 0xd7, 0x0c, 0xf6, 0x45, 0x7a, 0xc7, 0x0e, 0x82, 0x6f, 0xc6,
39        0xa7, 0x5b, 0xf7, 0xcf, 0x10, 0x8c, 0x92, 0xea, 0xcf, 0xfc, 0xb5, 0xd9,
40        0xfd, 0x77, 0x66, 0xa3, 0x58, 0xa9, 0x01, 0x48, 0x30, 0x45, 0x02, 0x21,
41        0x00, 0xfe, 0x82, 0x5b, 0xe1, 0xd5, 0xfd, 0x71, 0x67, 0x83, 0xf4, 0x55,
42        0xef, 0xe6, 0x6d, 0x61, 0x58, 0xff, 0xf8, 0xc3, 0x2b, 0x93, 0x1c, 0x5f,
43        0x3f, 0xf9, 0x8e, 0x06, 0x65, 0xa9, 0xfd, 0x8e, 0x64, 0x02, 0x20, 0x22,
44        0x01, 0x0f, 0xdb, 0x53, 0x8d, 0x0f, 0xa6, 0x8b, 0xd7, 0xf5, 0x20, 0x5d,
45        0xc1, 0xdf, 0xa6, 0xc4, 0x28, 0x1b, 0x7b, 0xb7, 0x6f, 0xc2, 0x53, 0xf7,
46        0x51, 0x4d, 0x83, 0x48, 0x52, 0x5f, 0x0d, 0x01, 0x47, 0x52, 0x21, 0x03,
47        0xd0, 0xbf, 0x26, 0x7c, 0x93, 0x78, 0xb3, 0x18, 0xb5, 0x80, 0xc2, 0x10,
48        0xa6, 0x78, 0xc4, 0xbb, 0x60, 0xd8, 0x44, 0x8b, 0x52, 0x0d, 0x21, 0x25,
49        0xa1, 0xbd, 0x37, 0x2b, 0x23, 0xae, 0xa6, 0x49, 0x21, 0x02, 0x11, 0xa8,
50        0x2a, 0xa6, 0x94, 0x63, 0x99, 0x0a, 0x6c, 0xdd, 0x48, 0x36, 0x76, 0x36,
51        0x6a, 0x44, 0xac, 0x3c, 0x98, 0xe7, 0x68, 0x54, 0x69, 0x84, 0x0b, 0xf2,
52        0x7a, 0x72, 0x4e, 0x40, 0x5a, 0x7e, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff,
53        0xea, 0x51, 0x1f, 0x33, 0x7a, 0xf5, 0x72, 0xbb, 0xad, 0xcd, 0x2e, 0x03,
54        0x07, 0x71, 0x62, 0x3a, 0x60, 0xcc, 0x71, 0x82, 0xad, 0x74, 0x53, 0x3e,
55        0xa3, 0x2f, 0xc8, 0xaa, 0x47, 0xd2, 0x0e, 0x71, 0x01, 0x00, 0x00, 0x00,
56        0xda, 0x00, 0x48, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfa, 0x2b, 0xfb, 0x4d,
57        0x49, 0xb7, 0x6d, 0x9f, 0xb4, 0xc6, 0x9c, 0xc7, 0x8c, 0x36, 0xd2, 0x66,
58        0x92, 0x40, 0xe4, 0x57, 0x14, 0xc7, 0x19, 0x06, 0x85, 0xf7, 0xe5, 0x13,
59        0x94, 0xac, 0x4e, 0x37, 0x02, 0x20, 0x04, 0x95, 0x2c, 0xf7, 0x75, 0x1c,
60        0x45, 0x9d, 0x8a, 0x8b, 0x64, 0x76, 0x76, 0xce, 0x86, 0xf3, 0xbd, 0x69,
61        0xff, 0x39, 0x17, 0xcb, 0x99, 0x85, 0x14, 0xbd, 0x73, 0xb7, 0xfc, 0x04,
62        0xf6, 0x4c, 0x01, 0x47, 0x30, 0x44, 0x02, 0x20, 0x31, 0xae, 0x81, 0x1e,
63        0x35, 0x7e, 0x80, 0x00, 0x01, 0xc7, 0x57, 0x27, 0x7a, 0x22, 0x44, 0xa7,
64        0x2b, 0xd5, 0x9d, 0x0a, 0x00, 0xbe, 0xde, 0x49, 0x0a, 0x96, 0x12, 0x3e,
65        0x54, 0xce, 0x03, 0x4c, 0x02, 0x20, 0x05, 0xa2, 0x9f, 0x14, 0x30, 0x1e,
66        0x5e, 0x2f, 0xdc, 0x7c, 0xee, 0x49, 0x43, 0xec, 0x78, 0x78, 0xdf, 0x73,
67        0xde, 0x96, 0x27, 0x00, 0xa4, 0xd9, 0x43, 0x6b, 0xce, 0x24, 0xd6, 0xc3,
68        0xa3, 0x57, 0x01, 0x47, 0x52, 0x21, 0x03, 0x4e, 0x74, 0xde, 0x0b, 0x84,
69        0x3f, 0xaa, 0x60, 0x44, 0x3d, 0xf4, 0x76, 0xf1, 0xf6, 0x14, 0x4a, 0x5b,
70        0x0e, 0x76, 0x49, 0x9e, 0x8a, 0x26, 0x71, 0x07, 0x36, 0x5b, 0x32, 0xfa,
71        0xd5, 0xd0, 0xfd, 0x21, 0x03, 0xb4, 0xa6, 0x82, 0xc8, 0x6a, 0xd9, 0x06,
72        0x38, 0x8f, 0x99, 0x52, 0x76, 0xf0, 0x84, 0x92, 0x72, 0x3a, 0x8c, 0x5f,
73        0x32, 0x3c, 0x6a, 0xf6, 0x92, 0x97, 0x17, 0x40, 0x5d, 0x2e, 0x1b, 0x2f,
74        0x70, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff, 0x02, 0xa7, 0x32, 0x75, 0x01,
75        0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xfb, 0xf7, 0x76, 0xff,
76        0xeb, 0x3b, 0xb8, 0x89, 0xb2, 0x01, 0xa5, 0x3f, 0x5f, 0xb0, 0x55, 0x4f,
77        0x6e, 0x6f, 0xa2, 0x56, 0x88, 0xac, 0x19, 0x88, 0x56, 0x01, 0x00, 0x00,
78        0x00, 0x00, 0x17, 0xa9, 0x14, 0xd3, 0xb6, 0x1d, 0x34, 0xf6, 0x33, 0x7c,
79        0xd7, 0xc0, 0x28, 0xb7, 0x90, 0xb0, 0xcf, 0x43, 0xe0, 0x27, 0xd9, 0x1d,
80        0xe7, 0x87, 0x09, 0x5d, 0x07, 0x00,
81    ];
82    let transaction =
83        bitcoin::Transaction::consensus_decode(&mut &tx_bytes[..]).expect("decode transaction");
84
85    let spk_input_1 = bitcoin::Script::from(vec![
86        0xa9, 0x14, 0x92, 0x09, 0xa8, 0xf9, 0x0c, 0x58, 0x4b, 0xb5, 0x97, 0x4d, 0x58, 0x68, 0x72,
87        0x49, 0xe5, 0x32, 0xde, 0x59, 0xf4, 0xbc, 0x87,
88    ]);
89    let interpreter = miniscript::Interpreter::from_txdata(
90        &spk_input_1,
91        &transaction.input[0].script_sig,
92        &transaction.input[0].witness,
93        0,
94        0,
95        // TODO: Replace with actual hash
96        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
97    )
98    .unwrap();
99
100    let desc_string = interpreter.inferred_descriptor_string();
101    println!("Descriptor: {}", desc_string);
102    miniscript::Descriptor::<bitcoin::PublicKey>::from_str(&desc_string)
103        .expect("this descriptor can be reparsed with sanity checks passing");
104    interpreter
105        .inferred_descriptor()
106        .expect("we can use this method to do the above from_str for us");
107
108    // 1. Example one: learn which keys were used, not bothering
109    //    to verify the signatures (trusting that if they're on
110    //    the blockchain, standardness would've required they be
111    //    either valid or 0-length.
112    println!("\nExample one");
113    for elem in interpreter.iter_assume_sigs() {
114        // Don't bother checking signatures
115        match elem.expect("no evaluation error") {
116            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
117                // Check that the signature is ecdsa sig
118                let (key, sig) = key_sig
119                    .as_ecdsa()
120                    .expect("Expected Ecdsa sig, found schnorr sig");
121                println!("Signed with {}: {}", key, sig);
122            }
123            _ => {}
124        }
125    }
126
127    // 2. Example two: verify the signatures to ensure that invalid
128    //    signatures are not treated as having participated in the script
129    let secp = secp256k1::Secp256k1::new();
130    // Sometimes it is necessary to have additional information to get the bitcoin::PublicKey
131    // from the MiniscriptKey which can supplied by `to_pk_ctx` parameter. For example,
132    // when calculating the script pubkey of a descriptor with xpubs, the secp context and
133    // child information maybe required.
134    let interpreter = miniscript::Interpreter::from_txdata(
135        &spk_input_1,
136        &transaction.input[0].script_sig,
137        &transaction.input[0].witness,
138        0,
139        0,
140        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
141    )
142    .unwrap();
143
144    // We can set prevouts to be empty list because this is a legacy transaction
145    // and this information is not required for sighash computation.
146    let prevouts = sighash::Prevouts::All::<TxOut>(&[]);
147
148    println!("\nExample two");
149    for elem in interpreter.iter(&secp, &transaction, 0, &prevouts) {
150        match elem.expect("no evaluation error") {
151            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
152                let (key, sig) = key_sig.as_ecdsa().unwrap();
153                println!("Signed with {}: {}", key, sig);
154            }
155            _ => {}
156        }
157    }
158
159    // 3. Example three: same, but with the wrong signature hash, to demonstrate
160    //    what happens given an apparently invalid script
161    let secp = secp256k1::Secp256k1::new();
162    let message = secp256k1::Message::from_slice(&[0x01; 32][..]).expect("32-byte hash");
163    let interpreter = miniscript::Interpreter::from_txdata(
164        &spk_input_1,
165        &transaction.input[0].script_sig,
166        &transaction.input[0].witness,
167        0,
168        0,
169        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
170    )
171    .unwrap();
172
173    let iter = interpreter.iter_custom(Box::new(|key_sig: &KeySigPair| {
174        let (pk, ecdsa_sig) = key_sig.as_ecdsa().expect("Ecdsa Sig");
175        ecdsa_sig.hash_ty == bitcoin::EcdsaSighashType::All
176            && secp
177                .verify_ecdsa(&message, &ecdsa_sig.sig, &pk.inner)
178                .is_ok()
179    }));
180    println!("\nExample three");
181    for elem in iter {
182        let error = elem.expect_err("evaluation error");
183        println!("Evaluation error: {}", error);
184    }
185}
Source

pub fn iter_assume_sigs<'iter>(&'iter self) -> Iter<'txin, 'iter>

Creates an iterator over the satisfied spending conditions without checking signatures

Examples found in repository?
examples/verify_tx.rs (line 113)
27fn main() {
28    // tx `f27eba163c38ad3f34971198687a3f1882b7ec818599ffe469a8440d82261c98`
29    #[cfg_attr(feature="cargo-fmt", rustfmt_skip)]
30    let tx_bytes = vec![
31        0x01, 0x00, 0x00, 0x00, 0x02, 0xc5, 0x11, 0x1d, 0xb7, 0x93, 0x50, 0xc1,
32        0x70, 0x28, 0x41, 0x39, 0xe8, 0xe3, 0x4e, 0xb0, 0xed, 0xba, 0x64, 0x7b,
33        0x6c, 0x88, 0x7e, 0x9f, 0x92, 0x8f, 0xfd, 0x9b, 0x5c, 0x4a, 0x4b, 0x52,
34        0xd0, 0x01, 0x00, 0x00, 0x00, 0xda, 0x00, 0x47, 0x30, 0x44, 0x02, 0x20,
35        0x1c, 0xcc, 0x1b, 0xe9, 0xaf, 0x73, 0x4a, 0x10, 0x9f, 0x66, 0xfb, 0xed,
36        0xeb, 0x77, 0xb7, 0xa1, 0xf4, 0xb3, 0xc5, 0xff, 0x3d, 0x7f, 0x46, 0xf6,
37        0xde, 0x50, 0x69, 0xbb, 0x52, 0x7f, 0x26, 0x9d, 0x02, 0x20, 0x75, 0x37,
38        0x2f, 0x6b, 0xd7, 0x0c, 0xf6, 0x45, 0x7a, 0xc7, 0x0e, 0x82, 0x6f, 0xc6,
39        0xa7, 0x5b, 0xf7, 0xcf, 0x10, 0x8c, 0x92, 0xea, 0xcf, 0xfc, 0xb5, 0xd9,
40        0xfd, 0x77, 0x66, 0xa3, 0x58, 0xa9, 0x01, 0x48, 0x30, 0x45, 0x02, 0x21,
41        0x00, 0xfe, 0x82, 0x5b, 0xe1, 0xd5, 0xfd, 0x71, 0x67, 0x83, 0xf4, 0x55,
42        0xef, 0xe6, 0x6d, 0x61, 0x58, 0xff, 0xf8, 0xc3, 0x2b, 0x93, 0x1c, 0x5f,
43        0x3f, 0xf9, 0x8e, 0x06, 0x65, 0xa9, 0xfd, 0x8e, 0x64, 0x02, 0x20, 0x22,
44        0x01, 0x0f, 0xdb, 0x53, 0x8d, 0x0f, 0xa6, 0x8b, 0xd7, 0xf5, 0x20, 0x5d,
45        0xc1, 0xdf, 0xa6, 0xc4, 0x28, 0x1b, 0x7b, 0xb7, 0x6f, 0xc2, 0x53, 0xf7,
46        0x51, 0x4d, 0x83, 0x48, 0x52, 0x5f, 0x0d, 0x01, 0x47, 0x52, 0x21, 0x03,
47        0xd0, 0xbf, 0x26, 0x7c, 0x93, 0x78, 0xb3, 0x18, 0xb5, 0x80, 0xc2, 0x10,
48        0xa6, 0x78, 0xc4, 0xbb, 0x60, 0xd8, 0x44, 0x8b, 0x52, 0x0d, 0x21, 0x25,
49        0xa1, 0xbd, 0x37, 0x2b, 0x23, 0xae, 0xa6, 0x49, 0x21, 0x02, 0x11, 0xa8,
50        0x2a, 0xa6, 0x94, 0x63, 0x99, 0x0a, 0x6c, 0xdd, 0x48, 0x36, 0x76, 0x36,
51        0x6a, 0x44, 0xac, 0x3c, 0x98, 0xe7, 0x68, 0x54, 0x69, 0x84, 0x0b, 0xf2,
52        0x7a, 0x72, 0x4e, 0x40, 0x5a, 0x7e, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff,
53        0xea, 0x51, 0x1f, 0x33, 0x7a, 0xf5, 0x72, 0xbb, 0xad, 0xcd, 0x2e, 0x03,
54        0x07, 0x71, 0x62, 0x3a, 0x60, 0xcc, 0x71, 0x82, 0xad, 0x74, 0x53, 0x3e,
55        0xa3, 0x2f, 0xc8, 0xaa, 0x47, 0xd2, 0x0e, 0x71, 0x01, 0x00, 0x00, 0x00,
56        0xda, 0x00, 0x48, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfa, 0x2b, 0xfb, 0x4d,
57        0x49, 0xb7, 0x6d, 0x9f, 0xb4, 0xc6, 0x9c, 0xc7, 0x8c, 0x36, 0xd2, 0x66,
58        0x92, 0x40, 0xe4, 0x57, 0x14, 0xc7, 0x19, 0x06, 0x85, 0xf7, 0xe5, 0x13,
59        0x94, 0xac, 0x4e, 0x37, 0x02, 0x20, 0x04, 0x95, 0x2c, 0xf7, 0x75, 0x1c,
60        0x45, 0x9d, 0x8a, 0x8b, 0x64, 0x76, 0x76, 0xce, 0x86, 0xf3, 0xbd, 0x69,
61        0xff, 0x39, 0x17, 0xcb, 0x99, 0x85, 0x14, 0xbd, 0x73, 0xb7, 0xfc, 0x04,
62        0xf6, 0x4c, 0x01, 0x47, 0x30, 0x44, 0x02, 0x20, 0x31, 0xae, 0x81, 0x1e,
63        0x35, 0x7e, 0x80, 0x00, 0x01, 0xc7, 0x57, 0x27, 0x7a, 0x22, 0x44, 0xa7,
64        0x2b, 0xd5, 0x9d, 0x0a, 0x00, 0xbe, 0xde, 0x49, 0x0a, 0x96, 0x12, 0x3e,
65        0x54, 0xce, 0x03, 0x4c, 0x02, 0x20, 0x05, 0xa2, 0x9f, 0x14, 0x30, 0x1e,
66        0x5e, 0x2f, 0xdc, 0x7c, 0xee, 0x49, 0x43, 0xec, 0x78, 0x78, 0xdf, 0x73,
67        0xde, 0x96, 0x27, 0x00, 0xa4, 0xd9, 0x43, 0x6b, 0xce, 0x24, 0xd6, 0xc3,
68        0xa3, 0x57, 0x01, 0x47, 0x52, 0x21, 0x03, 0x4e, 0x74, 0xde, 0x0b, 0x84,
69        0x3f, 0xaa, 0x60, 0x44, 0x3d, 0xf4, 0x76, 0xf1, 0xf6, 0x14, 0x4a, 0x5b,
70        0x0e, 0x76, 0x49, 0x9e, 0x8a, 0x26, 0x71, 0x07, 0x36, 0x5b, 0x32, 0xfa,
71        0xd5, 0xd0, 0xfd, 0x21, 0x03, 0xb4, 0xa6, 0x82, 0xc8, 0x6a, 0xd9, 0x06,
72        0x38, 0x8f, 0x99, 0x52, 0x76, 0xf0, 0x84, 0x92, 0x72, 0x3a, 0x8c, 0x5f,
73        0x32, 0x3c, 0x6a, 0xf6, 0x92, 0x97, 0x17, 0x40, 0x5d, 0x2e, 0x1b, 0x2f,
74        0x70, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff, 0x02, 0xa7, 0x32, 0x75, 0x01,
75        0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xfb, 0xf7, 0x76, 0xff,
76        0xeb, 0x3b, 0xb8, 0x89, 0xb2, 0x01, 0xa5, 0x3f, 0x5f, 0xb0, 0x55, 0x4f,
77        0x6e, 0x6f, 0xa2, 0x56, 0x88, 0xac, 0x19, 0x88, 0x56, 0x01, 0x00, 0x00,
78        0x00, 0x00, 0x17, 0xa9, 0x14, 0xd3, 0xb6, 0x1d, 0x34, 0xf6, 0x33, 0x7c,
79        0xd7, 0xc0, 0x28, 0xb7, 0x90, 0xb0, 0xcf, 0x43, 0xe0, 0x27, 0xd9, 0x1d,
80        0xe7, 0x87, 0x09, 0x5d, 0x07, 0x00,
81    ];
82    let transaction =
83        bitcoin::Transaction::consensus_decode(&mut &tx_bytes[..]).expect("decode transaction");
84
85    let spk_input_1 = bitcoin::Script::from(vec![
86        0xa9, 0x14, 0x92, 0x09, 0xa8, 0xf9, 0x0c, 0x58, 0x4b, 0xb5, 0x97, 0x4d, 0x58, 0x68, 0x72,
87        0x49, 0xe5, 0x32, 0xde, 0x59, 0xf4, 0xbc, 0x87,
88    ]);
89    let interpreter = miniscript::Interpreter::from_txdata(
90        &spk_input_1,
91        &transaction.input[0].script_sig,
92        &transaction.input[0].witness,
93        0,
94        0,
95        // TODO: Replace with actual hash
96        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
97    )
98    .unwrap();
99
100    let desc_string = interpreter.inferred_descriptor_string();
101    println!("Descriptor: {}", desc_string);
102    miniscript::Descriptor::<bitcoin::PublicKey>::from_str(&desc_string)
103        .expect("this descriptor can be reparsed with sanity checks passing");
104    interpreter
105        .inferred_descriptor()
106        .expect("we can use this method to do the above from_str for us");
107
108    // 1. Example one: learn which keys were used, not bothering
109    //    to verify the signatures (trusting that if they're on
110    //    the blockchain, standardness would've required they be
111    //    either valid or 0-length.
112    println!("\nExample one");
113    for elem in interpreter.iter_assume_sigs() {
114        // Don't bother checking signatures
115        match elem.expect("no evaluation error") {
116            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
117                // Check that the signature is ecdsa sig
118                let (key, sig) = key_sig
119                    .as_ecdsa()
120                    .expect("Expected Ecdsa sig, found schnorr sig");
121                println!("Signed with {}: {}", key, sig);
122            }
123            _ => {}
124        }
125    }
126
127    // 2. Example two: verify the signatures to ensure that invalid
128    //    signatures are not treated as having participated in the script
129    let secp = secp256k1::Secp256k1::new();
130    // Sometimes it is necessary to have additional information to get the bitcoin::PublicKey
131    // from the MiniscriptKey which can supplied by `to_pk_ctx` parameter. For example,
132    // when calculating the script pubkey of a descriptor with xpubs, the secp context and
133    // child information maybe required.
134    let interpreter = miniscript::Interpreter::from_txdata(
135        &spk_input_1,
136        &transaction.input[0].script_sig,
137        &transaction.input[0].witness,
138        0,
139        0,
140        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
141    )
142    .unwrap();
143
144    // We can set prevouts to be empty list because this is a legacy transaction
145    // and this information is not required for sighash computation.
146    let prevouts = sighash::Prevouts::All::<TxOut>(&[]);
147
148    println!("\nExample two");
149    for elem in interpreter.iter(&secp, &transaction, 0, &prevouts) {
150        match elem.expect("no evaluation error") {
151            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
152                let (key, sig) = key_sig.as_ecdsa().unwrap();
153                println!("Signed with {}: {}", key, sig);
154            }
155            _ => {}
156        }
157    }
158
159    // 3. Example three: same, but with the wrong signature hash, to demonstrate
160    //    what happens given an apparently invalid script
161    let secp = secp256k1::Secp256k1::new();
162    let message = secp256k1::Message::from_slice(&[0x01; 32][..]).expect("32-byte hash");
163    let interpreter = miniscript::Interpreter::from_txdata(
164        &spk_input_1,
165        &transaction.input[0].script_sig,
166        &transaction.input[0].witness,
167        0,
168        0,
169        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
170    )
171    .unwrap();
172
173    let iter = interpreter.iter_custom(Box::new(|key_sig: &KeySigPair| {
174        let (pk, ecdsa_sig) = key_sig.as_ecdsa().expect("Ecdsa Sig");
175        ecdsa_sig.hash_ty == bitcoin::EcdsaSighashType::All
176            && secp
177                .verify_ecdsa(&message, &ecdsa_sig.sig, &pk.inner)
178                .is_ok()
179    }));
180    println!("\nExample three");
181    for elem in iter {
182        let error = elem.expect_err("evaluation error");
183        println!("Evaluation error: {}", error);
184    }
185}
Source

pub fn inferred_descriptor_string(&self) -> String

Outputs a “descriptor” string which reproduces the spent coins

This may not represent the original descriptor used to produce the transaction, since it cannot distinguish between sorted and unsorted multisigs (and anyway it can only see the final keys, keyorigin info is lost in serializing to Bitcoin).

If you are using the interpreter as a sanity check on a transaction, it is worthwhile to try to parse this as a descriptor using from_str which will check standardness and consensus limits, which the interpreter does not do on its own. Or use the inferred_descriptor method which does this for you.

Examples found in repository?
examples/verify_tx.rs (line 100)
27fn main() {
28    // tx `f27eba163c38ad3f34971198687a3f1882b7ec818599ffe469a8440d82261c98`
29    #[cfg_attr(feature="cargo-fmt", rustfmt_skip)]
30    let tx_bytes = vec![
31        0x01, 0x00, 0x00, 0x00, 0x02, 0xc5, 0x11, 0x1d, 0xb7, 0x93, 0x50, 0xc1,
32        0x70, 0x28, 0x41, 0x39, 0xe8, 0xe3, 0x4e, 0xb0, 0xed, 0xba, 0x64, 0x7b,
33        0x6c, 0x88, 0x7e, 0x9f, 0x92, 0x8f, 0xfd, 0x9b, 0x5c, 0x4a, 0x4b, 0x52,
34        0xd0, 0x01, 0x00, 0x00, 0x00, 0xda, 0x00, 0x47, 0x30, 0x44, 0x02, 0x20,
35        0x1c, 0xcc, 0x1b, 0xe9, 0xaf, 0x73, 0x4a, 0x10, 0x9f, 0x66, 0xfb, 0xed,
36        0xeb, 0x77, 0xb7, 0xa1, 0xf4, 0xb3, 0xc5, 0xff, 0x3d, 0x7f, 0x46, 0xf6,
37        0xde, 0x50, 0x69, 0xbb, 0x52, 0x7f, 0x26, 0x9d, 0x02, 0x20, 0x75, 0x37,
38        0x2f, 0x6b, 0xd7, 0x0c, 0xf6, 0x45, 0x7a, 0xc7, 0x0e, 0x82, 0x6f, 0xc6,
39        0xa7, 0x5b, 0xf7, 0xcf, 0x10, 0x8c, 0x92, 0xea, 0xcf, 0xfc, 0xb5, 0xd9,
40        0xfd, 0x77, 0x66, 0xa3, 0x58, 0xa9, 0x01, 0x48, 0x30, 0x45, 0x02, 0x21,
41        0x00, 0xfe, 0x82, 0x5b, 0xe1, 0xd5, 0xfd, 0x71, 0x67, 0x83, 0xf4, 0x55,
42        0xef, 0xe6, 0x6d, 0x61, 0x58, 0xff, 0xf8, 0xc3, 0x2b, 0x93, 0x1c, 0x5f,
43        0x3f, 0xf9, 0x8e, 0x06, 0x65, 0xa9, 0xfd, 0x8e, 0x64, 0x02, 0x20, 0x22,
44        0x01, 0x0f, 0xdb, 0x53, 0x8d, 0x0f, 0xa6, 0x8b, 0xd7, 0xf5, 0x20, 0x5d,
45        0xc1, 0xdf, 0xa6, 0xc4, 0x28, 0x1b, 0x7b, 0xb7, 0x6f, 0xc2, 0x53, 0xf7,
46        0x51, 0x4d, 0x83, 0x48, 0x52, 0x5f, 0x0d, 0x01, 0x47, 0x52, 0x21, 0x03,
47        0xd0, 0xbf, 0x26, 0x7c, 0x93, 0x78, 0xb3, 0x18, 0xb5, 0x80, 0xc2, 0x10,
48        0xa6, 0x78, 0xc4, 0xbb, 0x60, 0xd8, 0x44, 0x8b, 0x52, 0x0d, 0x21, 0x25,
49        0xa1, 0xbd, 0x37, 0x2b, 0x23, 0xae, 0xa6, 0x49, 0x21, 0x02, 0x11, 0xa8,
50        0x2a, 0xa6, 0x94, 0x63, 0x99, 0x0a, 0x6c, 0xdd, 0x48, 0x36, 0x76, 0x36,
51        0x6a, 0x44, 0xac, 0x3c, 0x98, 0xe7, 0x68, 0x54, 0x69, 0x84, 0x0b, 0xf2,
52        0x7a, 0x72, 0x4e, 0x40, 0x5a, 0x7e, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff,
53        0xea, 0x51, 0x1f, 0x33, 0x7a, 0xf5, 0x72, 0xbb, 0xad, 0xcd, 0x2e, 0x03,
54        0x07, 0x71, 0x62, 0x3a, 0x60, 0xcc, 0x71, 0x82, 0xad, 0x74, 0x53, 0x3e,
55        0xa3, 0x2f, 0xc8, 0xaa, 0x47, 0xd2, 0x0e, 0x71, 0x01, 0x00, 0x00, 0x00,
56        0xda, 0x00, 0x48, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfa, 0x2b, 0xfb, 0x4d,
57        0x49, 0xb7, 0x6d, 0x9f, 0xb4, 0xc6, 0x9c, 0xc7, 0x8c, 0x36, 0xd2, 0x66,
58        0x92, 0x40, 0xe4, 0x57, 0x14, 0xc7, 0x19, 0x06, 0x85, 0xf7, 0xe5, 0x13,
59        0x94, 0xac, 0x4e, 0x37, 0x02, 0x20, 0x04, 0x95, 0x2c, 0xf7, 0x75, 0x1c,
60        0x45, 0x9d, 0x8a, 0x8b, 0x64, 0x76, 0x76, 0xce, 0x86, 0xf3, 0xbd, 0x69,
61        0xff, 0x39, 0x17, 0xcb, 0x99, 0x85, 0x14, 0xbd, 0x73, 0xb7, 0xfc, 0x04,
62        0xf6, 0x4c, 0x01, 0x47, 0x30, 0x44, 0x02, 0x20, 0x31, 0xae, 0x81, 0x1e,
63        0x35, 0x7e, 0x80, 0x00, 0x01, 0xc7, 0x57, 0x27, 0x7a, 0x22, 0x44, 0xa7,
64        0x2b, 0xd5, 0x9d, 0x0a, 0x00, 0xbe, 0xde, 0x49, 0x0a, 0x96, 0x12, 0x3e,
65        0x54, 0xce, 0x03, 0x4c, 0x02, 0x20, 0x05, 0xa2, 0x9f, 0x14, 0x30, 0x1e,
66        0x5e, 0x2f, 0xdc, 0x7c, 0xee, 0x49, 0x43, 0xec, 0x78, 0x78, 0xdf, 0x73,
67        0xde, 0x96, 0x27, 0x00, 0xa4, 0xd9, 0x43, 0x6b, 0xce, 0x24, 0xd6, 0xc3,
68        0xa3, 0x57, 0x01, 0x47, 0x52, 0x21, 0x03, 0x4e, 0x74, 0xde, 0x0b, 0x84,
69        0x3f, 0xaa, 0x60, 0x44, 0x3d, 0xf4, 0x76, 0xf1, 0xf6, 0x14, 0x4a, 0x5b,
70        0x0e, 0x76, 0x49, 0x9e, 0x8a, 0x26, 0x71, 0x07, 0x36, 0x5b, 0x32, 0xfa,
71        0xd5, 0xd0, 0xfd, 0x21, 0x03, 0xb4, 0xa6, 0x82, 0xc8, 0x6a, 0xd9, 0x06,
72        0x38, 0x8f, 0x99, 0x52, 0x76, 0xf0, 0x84, 0x92, 0x72, 0x3a, 0x8c, 0x5f,
73        0x32, 0x3c, 0x6a, 0xf6, 0x92, 0x97, 0x17, 0x40, 0x5d, 0x2e, 0x1b, 0x2f,
74        0x70, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff, 0x02, 0xa7, 0x32, 0x75, 0x01,
75        0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xfb, 0xf7, 0x76, 0xff,
76        0xeb, 0x3b, 0xb8, 0x89, 0xb2, 0x01, 0xa5, 0x3f, 0x5f, 0xb0, 0x55, 0x4f,
77        0x6e, 0x6f, 0xa2, 0x56, 0x88, 0xac, 0x19, 0x88, 0x56, 0x01, 0x00, 0x00,
78        0x00, 0x00, 0x17, 0xa9, 0x14, 0xd3, 0xb6, 0x1d, 0x34, 0xf6, 0x33, 0x7c,
79        0xd7, 0xc0, 0x28, 0xb7, 0x90, 0xb0, 0xcf, 0x43, 0xe0, 0x27, 0xd9, 0x1d,
80        0xe7, 0x87, 0x09, 0x5d, 0x07, 0x00,
81    ];
82    let transaction =
83        bitcoin::Transaction::consensus_decode(&mut &tx_bytes[..]).expect("decode transaction");
84
85    let spk_input_1 = bitcoin::Script::from(vec![
86        0xa9, 0x14, 0x92, 0x09, 0xa8, 0xf9, 0x0c, 0x58, 0x4b, 0xb5, 0x97, 0x4d, 0x58, 0x68, 0x72,
87        0x49, 0xe5, 0x32, 0xde, 0x59, 0xf4, 0xbc, 0x87,
88    ]);
89    let interpreter = miniscript::Interpreter::from_txdata(
90        &spk_input_1,
91        &transaction.input[0].script_sig,
92        &transaction.input[0].witness,
93        0,
94        0,
95        // TODO: Replace with actual hash
96        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
97    )
98    .unwrap();
99
100    let desc_string = interpreter.inferred_descriptor_string();
101    println!("Descriptor: {}", desc_string);
102    miniscript::Descriptor::<bitcoin::PublicKey>::from_str(&desc_string)
103        .expect("this descriptor can be reparsed with sanity checks passing");
104    interpreter
105        .inferred_descriptor()
106        .expect("we can use this method to do the above from_str for us");
107
108    // 1. Example one: learn which keys were used, not bothering
109    //    to verify the signatures (trusting that if they're on
110    //    the blockchain, standardness would've required they be
111    //    either valid or 0-length.
112    println!("\nExample one");
113    for elem in interpreter.iter_assume_sigs() {
114        // Don't bother checking signatures
115        match elem.expect("no evaluation error") {
116            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
117                // Check that the signature is ecdsa sig
118                let (key, sig) = key_sig
119                    .as_ecdsa()
120                    .expect("Expected Ecdsa sig, found schnorr sig");
121                println!("Signed with {}: {}", key, sig);
122            }
123            _ => {}
124        }
125    }
126
127    // 2. Example two: verify the signatures to ensure that invalid
128    //    signatures are not treated as having participated in the script
129    let secp = secp256k1::Secp256k1::new();
130    // Sometimes it is necessary to have additional information to get the bitcoin::PublicKey
131    // from the MiniscriptKey which can supplied by `to_pk_ctx` parameter. For example,
132    // when calculating the script pubkey of a descriptor with xpubs, the secp context and
133    // child information maybe required.
134    let interpreter = miniscript::Interpreter::from_txdata(
135        &spk_input_1,
136        &transaction.input[0].script_sig,
137        &transaction.input[0].witness,
138        0,
139        0,
140        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
141    )
142    .unwrap();
143
144    // We can set prevouts to be empty list because this is a legacy transaction
145    // and this information is not required for sighash computation.
146    let prevouts = sighash::Prevouts::All::<TxOut>(&[]);
147
148    println!("\nExample two");
149    for elem in interpreter.iter(&secp, &transaction, 0, &prevouts) {
150        match elem.expect("no evaluation error") {
151            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
152                let (key, sig) = key_sig.as_ecdsa().unwrap();
153                println!("Signed with {}: {}", key, sig);
154            }
155            _ => {}
156        }
157    }
158
159    // 3. Example three: same, but with the wrong signature hash, to demonstrate
160    //    what happens given an apparently invalid script
161    let secp = secp256k1::Secp256k1::new();
162    let message = secp256k1::Message::from_slice(&[0x01; 32][..]).expect("32-byte hash");
163    let interpreter = miniscript::Interpreter::from_txdata(
164        &spk_input_1,
165        &transaction.input[0].script_sig,
166        &transaction.input[0].witness,
167        0,
168        0,
169        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
170    )
171    .unwrap();
172
173    let iter = interpreter.iter_custom(Box::new(|key_sig: &KeySigPair| {
174        let (pk, ecdsa_sig) = key_sig.as_ecdsa().expect("Ecdsa Sig");
175        ecdsa_sig.hash_ty == bitcoin::EcdsaSighashType::All
176            && secp
177                .verify_ecdsa(&message, &ecdsa_sig.sig, &pk.inner)
178                .is_ok()
179    }));
180    println!("\nExample three");
181    for elem in iter {
182        let error = elem.expect_err("evaluation error");
183        println!("Evaluation error: {}", error);
184    }
185}
Source

pub fn is_legacy(&self) -> bool

Whether this is a pre-segwit spend

Source

pub fn is_segwit_v0(&self) -> bool

Whether this is a segwit spend

Source

pub fn is_taproot_v1_key_spend(&self) -> bool

Whether this is a taproot key spend

Source

pub fn is_taproot_v1_script_spend(&self) -> bool

Whether this is a taproot script spend

Source

pub fn inferred_descriptor(&self) -> Result<Descriptor<PublicKey>, Error>

Outputs a “descriptor” which reproduces the spent coins

This may not represent the original descriptor used to produce the transaction, since it cannot distinguish between sorted and unsorted multisigs (and anyway it can only see the final keys, keyorigin info is lost in serializing to Bitcoin). x-only keys are translated to bitcoin::PublicKey with 0x02 prefix.

Examples found in repository?
examples/verify_tx.rs (line 105)
27fn main() {
28    // tx `f27eba163c38ad3f34971198687a3f1882b7ec818599ffe469a8440d82261c98`
29    #[cfg_attr(feature="cargo-fmt", rustfmt_skip)]
30    let tx_bytes = vec![
31        0x01, 0x00, 0x00, 0x00, 0x02, 0xc5, 0x11, 0x1d, 0xb7, 0x93, 0x50, 0xc1,
32        0x70, 0x28, 0x41, 0x39, 0xe8, 0xe3, 0x4e, 0xb0, 0xed, 0xba, 0x64, 0x7b,
33        0x6c, 0x88, 0x7e, 0x9f, 0x92, 0x8f, 0xfd, 0x9b, 0x5c, 0x4a, 0x4b, 0x52,
34        0xd0, 0x01, 0x00, 0x00, 0x00, 0xda, 0x00, 0x47, 0x30, 0x44, 0x02, 0x20,
35        0x1c, 0xcc, 0x1b, 0xe9, 0xaf, 0x73, 0x4a, 0x10, 0x9f, 0x66, 0xfb, 0xed,
36        0xeb, 0x77, 0xb7, 0xa1, 0xf4, 0xb3, 0xc5, 0xff, 0x3d, 0x7f, 0x46, 0xf6,
37        0xde, 0x50, 0x69, 0xbb, 0x52, 0x7f, 0x26, 0x9d, 0x02, 0x20, 0x75, 0x37,
38        0x2f, 0x6b, 0xd7, 0x0c, 0xf6, 0x45, 0x7a, 0xc7, 0x0e, 0x82, 0x6f, 0xc6,
39        0xa7, 0x5b, 0xf7, 0xcf, 0x10, 0x8c, 0x92, 0xea, 0xcf, 0xfc, 0xb5, 0xd9,
40        0xfd, 0x77, 0x66, 0xa3, 0x58, 0xa9, 0x01, 0x48, 0x30, 0x45, 0x02, 0x21,
41        0x00, 0xfe, 0x82, 0x5b, 0xe1, 0xd5, 0xfd, 0x71, 0x67, 0x83, 0xf4, 0x55,
42        0xef, 0xe6, 0x6d, 0x61, 0x58, 0xff, 0xf8, 0xc3, 0x2b, 0x93, 0x1c, 0x5f,
43        0x3f, 0xf9, 0x8e, 0x06, 0x65, 0xa9, 0xfd, 0x8e, 0x64, 0x02, 0x20, 0x22,
44        0x01, 0x0f, 0xdb, 0x53, 0x8d, 0x0f, 0xa6, 0x8b, 0xd7, 0xf5, 0x20, 0x5d,
45        0xc1, 0xdf, 0xa6, 0xc4, 0x28, 0x1b, 0x7b, 0xb7, 0x6f, 0xc2, 0x53, 0xf7,
46        0x51, 0x4d, 0x83, 0x48, 0x52, 0x5f, 0x0d, 0x01, 0x47, 0x52, 0x21, 0x03,
47        0xd0, 0xbf, 0x26, 0x7c, 0x93, 0x78, 0xb3, 0x18, 0xb5, 0x80, 0xc2, 0x10,
48        0xa6, 0x78, 0xc4, 0xbb, 0x60, 0xd8, 0x44, 0x8b, 0x52, 0x0d, 0x21, 0x25,
49        0xa1, 0xbd, 0x37, 0x2b, 0x23, 0xae, 0xa6, 0x49, 0x21, 0x02, 0x11, 0xa8,
50        0x2a, 0xa6, 0x94, 0x63, 0x99, 0x0a, 0x6c, 0xdd, 0x48, 0x36, 0x76, 0x36,
51        0x6a, 0x44, 0xac, 0x3c, 0x98, 0xe7, 0x68, 0x54, 0x69, 0x84, 0x0b, 0xf2,
52        0x7a, 0x72, 0x4e, 0x40, 0x5a, 0x7e, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff,
53        0xea, 0x51, 0x1f, 0x33, 0x7a, 0xf5, 0x72, 0xbb, 0xad, 0xcd, 0x2e, 0x03,
54        0x07, 0x71, 0x62, 0x3a, 0x60, 0xcc, 0x71, 0x82, 0xad, 0x74, 0x53, 0x3e,
55        0xa3, 0x2f, 0xc8, 0xaa, 0x47, 0xd2, 0x0e, 0x71, 0x01, 0x00, 0x00, 0x00,
56        0xda, 0x00, 0x48, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfa, 0x2b, 0xfb, 0x4d,
57        0x49, 0xb7, 0x6d, 0x9f, 0xb4, 0xc6, 0x9c, 0xc7, 0x8c, 0x36, 0xd2, 0x66,
58        0x92, 0x40, 0xe4, 0x57, 0x14, 0xc7, 0x19, 0x06, 0x85, 0xf7, 0xe5, 0x13,
59        0x94, 0xac, 0x4e, 0x37, 0x02, 0x20, 0x04, 0x95, 0x2c, 0xf7, 0x75, 0x1c,
60        0x45, 0x9d, 0x8a, 0x8b, 0x64, 0x76, 0x76, 0xce, 0x86, 0xf3, 0xbd, 0x69,
61        0xff, 0x39, 0x17, 0xcb, 0x99, 0x85, 0x14, 0xbd, 0x73, 0xb7, 0xfc, 0x04,
62        0xf6, 0x4c, 0x01, 0x47, 0x30, 0x44, 0x02, 0x20, 0x31, 0xae, 0x81, 0x1e,
63        0x35, 0x7e, 0x80, 0x00, 0x01, 0xc7, 0x57, 0x27, 0x7a, 0x22, 0x44, 0xa7,
64        0x2b, 0xd5, 0x9d, 0x0a, 0x00, 0xbe, 0xde, 0x49, 0x0a, 0x96, 0x12, 0x3e,
65        0x54, 0xce, 0x03, 0x4c, 0x02, 0x20, 0x05, 0xa2, 0x9f, 0x14, 0x30, 0x1e,
66        0x5e, 0x2f, 0xdc, 0x7c, 0xee, 0x49, 0x43, 0xec, 0x78, 0x78, 0xdf, 0x73,
67        0xde, 0x96, 0x27, 0x00, 0xa4, 0xd9, 0x43, 0x6b, 0xce, 0x24, 0xd6, 0xc3,
68        0xa3, 0x57, 0x01, 0x47, 0x52, 0x21, 0x03, 0x4e, 0x74, 0xde, 0x0b, 0x84,
69        0x3f, 0xaa, 0x60, 0x44, 0x3d, 0xf4, 0x76, 0xf1, 0xf6, 0x14, 0x4a, 0x5b,
70        0x0e, 0x76, 0x49, 0x9e, 0x8a, 0x26, 0x71, 0x07, 0x36, 0x5b, 0x32, 0xfa,
71        0xd5, 0xd0, 0xfd, 0x21, 0x03, 0xb4, 0xa6, 0x82, 0xc8, 0x6a, 0xd9, 0x06,
72        0x38, 0x8f, 0x99, 0x52, 0x76, 0xf0, 0x84, 0x92, 0x72, 0x3a, 0x8c, 0x5f,
73        0x32, 0x3c, 0x6a, 0xf6, 0x92, 0x97, 0x17, 0x40, 0x5d, 0x2e, 0x1b, 0x2f,
74        0x70, 0x52, 0xae, 0xfd, 0xff, 0xff, 0xff, 0x02, 0xa7, 0x32, 0x75, 0x01,
75        0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xfb, 0xf7, 0x76, 0xff,
76        0xeb, 0x3b, 0xb8, 0x89, 0xb2, 0x01, 0xa5, 0x3f, 0x5f, 0xb0, 0x55, 0x4f,
77        0x6e, 0x6f, 0xa2, 0x56, 0x88, 0xac, 0x19, 0x88, 0x56, 0x01, 0x00, 0x00,
78        0x00, 0x00, 0x17, 0xa9, 0x14, 0xd3, 0xb6, 0x1d, 0x34, 0xf6, 0x33, 0x7c,
79        0xd7, 0xc0, 0x28, 0xb7, 0x90, 0xb0, 0xcf, 0x43, 0xe0, 0x27, 0xd9, 0x1d,
80        0xe7, 0x87, 0x09, 0x5d, 0x07, 0x00,
81    ];
82    let transaction =
83        bitcoin::Transaction::consensus_decode(&mut &tx_bytes[..]).expect("decode transaction");
84
85    let spk_input_1 = bitcoin::Script::from(vec![
86        0xa9, 0x14, 0x92, 0x09, 0xa8, 0xf9, 0x0c, 0x58, 0x4b, 0xb5, 0x97, 0x4d, 0x58, 0x68, 0x72,
87        0x49, 0xe5, 0x32, 0xde, 0x59, 0xf4, 0xbc, 0x87,
88    ]);
89    let interpreter = miniscript::Interpreter::from_txdata(
90        &spk_input_1,
91        &transaction.input[0].script_sig,
92        &transaction.input[0].witness,
93        0,
94        0,
95        // TODO: Replace with actual hash
96        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
97    )
98    .unwrap();
99
100    let desc_string = interpreter.inferred_descriptor_string();
101    println!("Descriptor: {}", desc_string);
102    miniscript::Descriptor::<bitcoin::PublicKey>::from_str(&desc_string)
103        .expect("this descriptor can be reparsed with sanity checks passing");
104    interpreter
105        .inferred_descriptor()
106        .expect("we can use this method to do the above from_str for us");
107
108    // 1. Example one: learn which keys were used, not bothering
109    //    to verify the signatures (trusting that if they're on
110    //    the blockchain, standardness would've required they be
111    //    either valid or 0-length.
112    println!("\nExample one");
113    for elem in interpreter.iter_assume_sigs() {
114        // Don't bother checking signatures
115        match elem.expect("no evaluation error") {
116            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
117                // Check that the signature is ecdsa sig
118                let (key, sig) = key_sig
119                    .as_ecdsa()
120                    .expect("Expected Ecdsa sig, found schnorr sig");
121                println!("Signed with {}: {}", key, sig);
122            }
123            _ => {}
124        }
125    }
126
127    // 2. Example two: verify the signatures to ensure that invalid
128    //    signatures are not treated as having participated in the script
129    let secp = secp256k1::Secp256k1::new();
130    // Sometimes it is necessary to have additional information to get the bitcoin::PublicKey
131    // from the MiniscriptKey which can supplied by `to_pk_ctx` parameter. For example,
132    // when calculating the script pubkey of a descriptor with xpubs, the secp context and
133    // child information maybe required.
134    let interpreter = miniscript::Interpreter::from_txdata(
135        &spk_input_1,
136        &transaction.input[0].script_sig,
137        &transaction.input[0].witness,
138        0,
139        0,
140        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
141    )
142    .unwrap();
143
144    // We can set prevouts to be empty list because this is a legacy transaction
145    // and this information is not required for sighash computation.
146    let prevouts = sighash::Prevouts::All::<TxOut>(&[]);
147
148    println!("\nExample two");
149    for elem in interpreter.iter(&secp, &transaction, 0, &prevouts) {
150        match elem.expect("no evaluation error") {
151            miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => {
152                let (key, sig) = key_sig.as_ecdsa().unwrap();
153                println!("Signed with {}: {}", key, sig);
154            }
155            _ => {}
156        }
157    }
158
159    // 3. Example three: same, but with the wrong signature hash, to demonstrate
160    //    what happens given an apparently invalid script
161    let secp = secp256k1::Secp256k1::new();
162    let message = secp256k1::Message::from_slice(&[0x01; 32][..]).expect("32-byte hash");
163    let interpreter = miniscript::Interpreter::from_txdata(
164        &spk_input_1,
165        &transaction.input[0].script_sig,
166        &transaction.input[0].witness,
167        0,
168        0,
169        bitcoin::hashes::sha256::Hash::from_inner([0u8; 32]),
170    )
171    .unwrap();
172
173    let iter = interpreter.iter_custom(Box::new(|key_sig: &KeySigPair| {
174        let (pk, ecdsa_sig) = key_sig.as_ecdsa().expect("Ecdsa Sig");
175        ecdsa_sig.hash_ty == bitcoin::EcdsaSighashType::All
176            && secp
177                .verify_ecdsa(&message, &ecdsa_sig.sig, &pk.inner)
178                .is_ok()
179    }));
180    println!("\nExample three");
181    for elem in iter {
182        let error = elem.expect_err("evaluation error");
183        println!("Evaluation error: {}", error);
184    }
185}

Auto Trait Implementations§

§

impl<'txin> Freeze for Interpreter<'txin>

§

impl<'txin> RefUnwindSafe for Interpreter<'txin>

§

impl<'txin> Send for Interpreter<'txin>

§

impl<'txin> Sync for Interpreter<'txin>

§

impl<'txin> Unpin for Interpreter<'txin>

§

impl<'txin> UnwindSafe for Interpreter<'txin>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.