Skip to main content

elements_miniscript/interpreter/
mod.rs

1// Written in 2019 by Sanket Kanjular and Andrew Poelstra
2// SPDX-License-Identifier: CC0-1.0
3
4//! Interpreter
5//!
6//! Provides a Miniscript-based script interpreter which can be used to
7//! iterate over the set of conditions satisfied by a spending transaction,
8//! assuming that the spent coin was descriptor controlled.
9//!
10
11use std::borrow::Borrow;
12use std::fmt;
13use std::str::FromStr;
14
15use bitcoin;
16use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash, HashEngine};
17use elements::{self, secp256k1_zkp, sighash, EcdsaSighashType, LockTime, Sequence};
18
19use crate::extensions::{CovExtArgs, ParseableExt, TxEnv};
20use crate::miniscript::context::{NoChecks, SigType};
21use crate::miniscript::ScriptContext;
22use crate::{hash256, util, Descriptor, ElementsSig, Miniscript, Terminal, ToPublicKey};
23
24mod error;
25mod inner;
26mod stack;
27
28pub use self::error::Error;
29use self::error::PkEvalErrInner;
30pub use self::stack::{Element, Stack};
31use crate::{elementssig_from_rawsig, CovenantExt, Extension, MiniscriptKey};
32
33/// An iterable Miniscript-structured representation of the spending of a coin
34pub struct Interpreter<'txin, Ext: Extension> {
35    inner: inner::Inner<Ext>,
36    stack: Stack<'txin>,
37    /// For non-Taproot spends, the scriptCode; for Taproot script-spends, this
38    /// is the leaf script; for key-spends it is `None`.
39    script_code: Option<elements::Script>,
40    age: Sequence,
41    lock_time: LockTime,
42}
43
44// A type representing functions for checking signatures that accept both
45// Ecdsa and Schnorr signatures
46
47/// A type for representing signatures supported as of bitcoin core 22.0
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum KeySigPair {
50    /// A Full public key and corresponding Ecdsa signature
51    Ecdsa(bitcoin::PublicKey, ElementsSig),
52    /// A x-only key and corresponding Schnorr signature
53    Schnorr(bitcoin::key::XOnlyPublicKey, elements::SchnorrSig),
54}
55
56impl KeySigPair {
57    /// Obtain a pair of ([`bitcoin::PublicKey`], [`ElementsSig`]) from [`KeySigPair`]
58    pub fn as_ecdsa(&self) -> Option<(bitcoin::PublicKey, ElementsSig)> {
59        match self {
60            KeySigPair::Ecdsa(pk, sig) => Some((*pk, *sig)),
61            KeySigPair::Schnorr(_, _) => None,
62        }
63    }
64
65    /// Obtain a pair of ([`bitcoin::key::XOnlyPublicKey`], [`elements::SchnorrSig`]) from [`KeySigPair`]
66    pub fn as_schnorr(&self) -> Option<(bitcoin::key::XOnlyPublicKey, elements::SchnorrSig)> {
67        match self {
68            KeySigPair::Ecdsa(_, _) => None,
69            KeySigPair::Schnorr(pk, sig) => Some((*pk, *sig)),
70        }
71    }
72}
73
74/// This type is exported in elements-miniscript because it also captures information
75/// about the type of Extension. For rust-miniscript, this is not an issue because there
76/// are no extensions.
77/// Internally used enum for different types of bitcoin keys
78/// Even though we implement MiniscriptKey for BitcoinKey, we make sure that there
79/// are little mis-use
80/// - The only constructors for this are only called in from_txdata that take care
81///   using the correct enum variant
82/// - This does not implement ToPublicKey to avoid context dependant encoding/decoding of 33/32
83///   byte keys. This allows us to keep a single NoChecks context instead of a context for
84///   for NoChecksSchnorr/NoChecksEcdsa.
85// Long term TODO: There really should be not be any need for Miniscript<Pk: MiniscriptKey> struct
86// to have the Pk: MiniscriptKey bound. The bound should be on all of it's methods. That would
87// require changing Miniscript struct to three generics Miniscript<Pk, Pkh, Ctx> and bound on
88// all of the methods of Miniscript to ensure that Pkh = Pk::Hash
89#[derive(Hash, Eq, Ord, PartialEq, PartialOrd, Clone, Copy, Debug)]
90pub enum BitcoinKey {
91    /// Full key
92    Fullkey(bitcoin::PublicKey),
93    /// Xonly key
94    XOnlyPublicKey(bitcoin::key::XOnlyPublicKey),
95}
96
97impl BitcoinKey {
98    fn to_pubkeyhash(self, sig_type: SigType) -> hash160::Hash {
99        match self {
100            BitcoinKey::Fullkey(pk) => pk.to_pubkeyhash(sig_type),
101            BitcoinKey::XOnlyPublicKey(pk) => pk.to_pubkeyhash(sig_type),
102        }
103    }
104}
105
106// Displayed in full 33 byte representation. X-only keys are displayed with 0x02 prefix
107impl fmt::Display for BitcoinKey {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        match self {
110            BitcoinKey::Fullkey(pk) => pk.to_public_key().fmt(f),
111            BitcoinKey::XOnlyPublicKey(pk) => pk.to_public_key().fmt(f),
112        }
113    }
114}
115
116impl From<bitcoin::PublicKey> for BitcoinKey {
117    fn from(pk: bitcoin::PublicKey) -> Self {
118        BitcoinKey::Fullkey(pk)
119    }
120}
121
122impl From<bitcoin::key::XOnlyPublicKey> for BitcoinKey {
123    fn from(xpk: bitcoin::key::XOnlyPublicKey) -> Self {
124        BitcoinKey::XOnlyPublicKey(xpk)
125    }
126}
127
128impl MiniscriptKey for BitcoinKey {
129    type Sha256 = sha256::Hash;
130    type Hash256 = hash256::Hash;
131    type Ripemd160 = ripemd160::Hash;
132    type Hash160 = hash160::Hash;
133
134    fn num_der_paths(&self) -> usize {
135        0
136    }
137}
138
139impl<'txin> Interpreter<'txin, CovenantExt<CovExtArgs>> {
140    /// Constructs an interpreter from the data of a spending transaction
141    ///
142    /// Accepts a signature-validating function. If you are willing to trust
143    /// that ECSDA signatures are valid, this can be set to the constant true
144    /// function; otherwise, it should be a closure containing a sighash and
145    /// secp context, which can actually verify a given signature.
146    /// For downstream cursom implementations of [`Extension`], use [`Interpreter::from_txdata_ext`]
147    pub fn from_txdata(
148        spk: &elements::Script,
149        script_sig: &'txin elements::Script,
150        witness: &'txin [Vec<u8>],
151        age: Sequence,       // CSV, relative lock time.
152        lock_time: LockTime, // CLTV, absolute lock time.
153    ) -> Result<Self, Error> {
154        Interpreter::from_txdata_ext(spk, script_sig, witness, age, lock_time)
155    }
156}
157
158impl<'txin, Ext> Interpreter<'txin, Ext>
159where
160    Ext: ParseableExt,
161{
162    /// Constructs an interpreter from the data of a spending transaction
163    ///
164    /// Accepts a signature-validating function. If you are willing to trust
165    /// that ECSDA signatures are valid, this can be set to the constant true
166    /// function; otherwise, it should be a closure containing a sighash and
167    /// secp context, which can actually verify a given signature.
168    pub fn from_txdata_ext(
169        spk: &elements::Script,
170        script_sig: &'txin elements::Script,
171        witness: &'txin [Vec<u8>],
172        age: Sequence,       // CSV, relative lock time.
173        lock_time: LockTime, // CLTV, absolute lock time.
174    ) -> Result<Self, Error> {
175        let (inner, stack, script_code) = inner::from_txdata(spk, script_sig, witness)?;
176        Ok(Interpreter {
177            inner,
178            stack,
179            script_code,
180            age,
181            lock_time,
182        })
183    }
184
185    /// Same as [`Interpreter::iter`], but allows for a custom verification function.
186    /// See [Self::iter_assume_sigs] for a simpler API without information about Prevouts
187    /// but skips the signature verification
188    pub fn iter_custom<'iter>(
189        &'iter self,
190        verify_sig: Box<dyn FnMut(&KeySigPair) -> bool + 'iter>,
191        txenv: Option<&'txin TxEnv<'txin, 'txin>>,
192    ) -> Iter<'txin, 'iter, Ext> {
193        Iter {
194            verify_sig,
195            public_key: if let inner::Inner::PublicKey(ref pk, _) = self.inner {
196                Some(pk)
197            } else {
198                None
199            },
200            state: match self.inner {
201                inner::Inner::Script(ref ms, _) => vec![NodeEvaluationState {
202                    node: ms,
203                    n_evaluated: 0,
204                    n_satisfied: 0,
205                }],
206                inner::Inner::CovScript(ref _pk, ref ms) => vec![NodeEvaluationState {
207                    node: ms,
208                    n_evaluated: 0,
209                    n_satisfied: 0,
210                }],
211                inner::Inner::PublicKey(ref _pk, _) => vec![],
212            },
213            // Cloning the references to elements of stack should be fine as it allows
214            // call interpreter.iter() without mutating interpreter
215            stack: self.stack.clone(),
216            age: self.age,
217            lock_time: self.lock_time,
218            cov: if let inner::Inner::CovScript(ref pk, ref _ms) = self.inner {
219                Some(pk)
220            } else {
221                None
222            },
223            has_errored: false,
224            txenv,
225            sig_type: self.sig_type(),
226        }
227    }
228
229    /// Verify a signature for a given transaction and prevout information
230    /// This is a low level API, [`Interpreter::iter`] or [`Interpreter::iter_assume_sigs`]
231    /// should satisfy most use-cases.
232    /// Returns false if
233    /// - the signature verification fails
234    /// - the input index is out of range
235    /// - Insufficient sighash information is present
236    /// - sighash single without corresponding output
237    // TODO: Create a good first isse to change this to error
238    pub fn verify_sig<C: secp256k1_zkp::Verification, T: Borrow<elements::TxOut>>(
239        &self,
240        secp: &secp256k1_zkp::Secp256k1<C>,
241        tx: &elements::Transaction,
242        input_idx: usize,
243        prevouts: &sighash::Prevouts<'_, T>,
244        genesis_hash: elements::BlockHash,
245        sig: &KeySigPair,
246    ) -> bool {
247        fn get_prevout<'u, T: Borrow<elements::TxOut>>(
248            prevouts: &'u sighash::Prevouts<'u, T>,
249            input_index: usize,
250        ) -> Option<&'u T> {
251            match prevouts {
252                sighash::Prevouts::One(index, prevout) => {
253                    if input_index == *index {
254                        Some(prevout)
255                    } else {
256                        None
257                    }
258                }
259                sighash::Prevouts::All(prevouts) => prevouts.get(input_index),
260            }
261        }
262        let mut cache = elements::sighash::SighashCache::new(tx);
263        match sig {
264            KeySigPair::Ecdsa(key, ecdsa_sig) => {
265                let script_pubkey = self.script_code.as_ref().expect("Legacy have script code");
266                let sighash = if self.is_legacy() {
267                    cache.legacy_sighash(input_idx, script_pubkey, ecdsa_sig.1)
268                } else if self.is_segwit_v0() {
269                    let amt = match get_prevout(prevouts, input_idx) {
270                        Some(txout) => txout.borrow().value,
271                        None => return false,
272                    };
273                    cache.segwitv0_sighash(input_idx, script_pubkey, amt, ecdsa_sig.1)
274                } else {
275                    // taproot(or future) signatures in segwitv0 context
276                    return false;
277                };
278                let msg =
279                    secp256k1_zkp::Message::from_digest_slice(sighash.as_ref()).expect("32 byte");
280                secp.verify_ecdsa(&msg, &ecdsa_sig.0, &key.inner).is_ok()
281            }
282            KeySigPair::Schnorr(xpk, schnorr_sig) => {
283                let sighash_msg = if self.is_taproot_v1_key_spend() {
284                    cache.taproot_key_spend_signature_hash(
285                        input_idx,
286                        prevouts,
287                        schnorr_sig.hash_ty,
288                        genesis_hash,
289                    )
290                } else if self.is_taproot_v1_script_spend() {
291                    let tap_script = self.script_code.as_ref().expect(
292                        "Internal Hack: Saving leaf script instead\
293                        of script code for script spend",
294                    );
295                    let leaf_hash =
296                        elements::sighash::ScriptPath::with_defaults(tap_script).leaf_hash();
297                    cache.taproot_script_spend_signature_hash(
298                        input_idx,
299                        prevouts,
300                        leaf_hash,
301                        schnorr_sig.hash_ty,
302                        genesis_hash,
303                    )
304                } else {
305                    // schnorr sigs in ecdsa descriptors
306                    return false;
307                };
308                let msg = sighash_msg.map(|hash| {
309                    secp256k1_zkp::Message::from_digest_slice(hash.as_ref()).expect("32 byte")
310                });
311                let success =
312                    msg.map(|msg| secp.verify_schnorr(&schnorr_sig.sig, &msg, xpk).is_ok());
313                success.unwrap_or(false) // unwrap_or_default checks for errors, while success would have checksig results
314            }
315        }
316    }
317
318    /// Creates an iterator over the satisfied spending conditions
319    ///
320    /// Returns all satisfied constraints, even if they were redundant (i.e. did
321    /// not contribute to the script being satisfied). For example, if a signature
322    /// were provided for an `and_b(Pk,false)` fragment, that signature will be
323    /// returned, even though the entire and_b must have failed and must not have
324    /// been used.
325    ///
326    /// In case the script is actually dissatisfied, this may return several values
327    /// before ultimately returning an error.
328    ///
329    /// Not all fields are used by legacy/segwitv0 descriptors; if you are sure this is a legacy
330    /// spend (you can check with the `is_legacy\is_segwitv0` method) you can provide dummy data for
331    /// the amount/prevouts/genesis_hash.
332    /// - For legacy outputs, no information about prevouts is required
333    /// - For segwitv0 outputs, prevout at corresponding index with correct amount must be provided
334    /// - For taproot outputs, information about all prevouts must be supplied and genesis_hash must be supplied
335    pub fn iter<'iter, C: secp256k1_zkp::Verification>(
336        &'iter self,
337        secp: &'iter secp256k1_zkp::Secp256k1<C>,
338        txenv: &'txin TxEnv, // actually a 'prevouts, but 'prevouts: 'iter
339        genesis_hash: elements::BlockHash, // required for sighash computation in BIP341
340    ) -> Iter<'txin, 'iter, Ext> {
341        self.iter_custom(
342            Box::new(move |sig| {
343                self.verify_sig(
344                    secp,
345                    txenv.tx(),
346                    txenv.idx(),
347                    &sighash::Prevouts::All(txenv.spent_utxos()),
348                    genesis_hash,
349                    sig,
350                )
351            }),
352            Some(txenv),
353        )
354    }
355
356    /// Creates an iterator over the satisfied spending conditions without checking signatures
357    pub fn iter_assume_sigs<'iter>(&'iter self) -> Iter<'txin, 'iter, Ext> {
358        self.iter_custom(Box::new(|_| true), None)
359    }
360
361    /// Outputs a "descriptor" string which reproduces the spent coins
362    ///
363    /// This may not represent the original descriptor used to produce the transaction,
364    /// since it cannot distinguish between sorted and unsorted multisigs (and anyway
365    /// it can only see the final keys, keyorigin info is lost in serializing to Bitcoin).
366    ///
367    /// If you are using the interpreter as a sanity check on a transaction,
368    /// it is worthwhile to try to parse this as a descriptor using `from_str`
369    /// which will check standardness and consensus limits, which the interpreter
370    /// does not do on its own. Or use the `inferred_descriptor` method which
371    /// does this for you.
372    pub fn inferred_descriptor_string(&self) -> String {
373        match self.inner {
374            inner::Inner::PublicKey(ref pk, inner::PubkeyType::Pk) => format!("elpk({})", pk),
375            inner::Inner::PublicKey(ref pk, inner::PubkeyType::Pkh) => format!("elpkh({})", pk),
376            inner::Inner::PublicKey(ref pk, inner::PubkeyType::Wpkh) => format!("elwpkh({})", pk),
377            inner::Inner::PublicKey(ref pk, inner::PubkeyType::ShWpkh) => {
378                format!("elsh(wpkh({}))", pk)
379            }
380            inner::Inner::PublicKey(ref pk, inner::PubkeyType::Tr) => {
381                // In tr descriptors, normally the internal key is represented inside the tr part
382                // But there is no way to infer the internal key from output descriptor status
383                // instead we infer a rawtr.
384                // Note that rawtr is parsing is currently not supported.
385                format!("rawtr_not_supported_yet({})", pk)
386            }
387            inner::Inner::Script(ref ms, inner::ScriptType::Bare) => format!("{}", ms),
388            inner::Inner::Script(ref ms, inner::ScriptType::Sh) => format!("elsh({})", ms),
389            inner::Inner::Script(ref ms, inner::ScriptType::Wsh) => format!("elwsh({})", ms),
390            inner::Inner::Script(ref ms, inner::ScriptType::ShWsh) => format!("elsh(wsh({}))", ms),
391            inner::Inner::CovScript(ref pk, ref ms) => {
392                // always wsh for now
393                format!("elcovwsh({},{})", pk, ms)
394            }
395            inner::Inner::Script(ref ms, inner::ScriptType::Tr) => {
396                // Hidden paths are still under discussion, once the spec is finalized, we can support
397                // rawnode and raw leaf.
398                format!("eltr(hidden_paths_not_yet_supported,{})", ms)
399            }
400        }
401    }
402
403    /// Whether this is a pre-segwit spend
404    pub fn is_legacy(&self) -> bool {
405        match self.inner {
406            inner::Inner::PublicKey(_, inner::PubkeyType::Pk) => true,
407            inner::Inner::PublicKey(_, inner::PubkeyType::Pkh) => true,
408            inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh) => false,
409            inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh) => false, // lol "sorta"
410            inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => false,     // lol "sorta"
411            inner::Inner::Script(_, inner::ScriptType::Bare) => false,
412            inner::Inner::Script(_, inner::ScriptType::Sh) => true,
413            inner::Inner::Script(_, inner::ScriptType::Wsh) => false,
414            inner::Inner::Script(_, inner::ScriptType::ShWsh) => false, // lol "sorta"
415            inner::Inner::CovScript(..) => false,
416            inner::Inner::Script(_, inner::ScriptType::Tr) => false,
417        }
418    }
419
420    /// Whether this is a segwit spend
421    pub fn is_segwit_v0(&self) -> bool {
422        match self.inner {
423            inner::Inner::PublicKey(_, inner::PubkeyType::Pk) => false,
424            inner::Inner::PublicKey(_, inner::PubkeyType::Pkh) => false,
425            inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh) => true,
426            inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh) => true, // lol "sorta"
427            inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => false,
428            inner::Inner::Script(_, inner::ScriptType::Bare) => false,
429            inner::Inner::Script(_, inner::ScriptType::Sh) => false,
430            inner::Inner::Script(_, inner::ScriptType::Wsh) => true,
431            inner::Inner::Script(_, inner::ScriptType::ShWsh) => true, // lol "sorta"
432            inner::Inner::Script(_, inner::ScriptType::Tr) => false,
433            inner::Inner::CovScript(_, _) => true,
434        }
435    }
436
437    /// Whether this is a taproot key spend
438    pub fn is_taproot_v1_key_spend(&self) -> bool {
439        match self.inner {
440            inner::Inner::PublicKey(_, inner::PubkeyType::Pk) => false,
441            inner::Inner::PublicKey(_, inner::PubkeyType::Pkh) => false,
442            inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh) => false,
443            inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh) => false,
444            inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => true,
445            inner::Inner::Script(_, inner::ScriptType::Bare) => false,
446            inner::Inner::Script(_, inner::ScriptType::Sh) => false,
447            inner::Inner::Script(_, inner::ScriptType::Wsh) => false,
448            inner::Inner::Script(_, inner::ScriptType::ShWsh) => false,
449            inner::Inner::Script(_, inner::ScriptType::Tr) => false,
450            inner::Inner::CovScript(_, _) => false,
451        }
452    }
453
454    /// Whether this is a taproot script spend
455    pub fn is_taproot_v1_script_spend(&self) -> bool {
456        match self.inner {
457            inner::Inner::PublicKey(_, inner::PubkeyType::Pk) => false,
458            inner::Inner::PublicKey(_, inner::PubkeyType::Pkh) => false,
459            inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh) => false,
460            inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh) => false,
461            inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => false,
462            inner::Inner::Script(_, inner::ScriptType::Bare) => false,
463            inner::Inner::Script(_, inner::ScriptType::Sh) => false,
464            inner::Inner::Script(_, inner::ScriptType::Wsh) => false,
465            inner::Inner::Script(_, inner::ScriptType::ShWsh) => false,
466            inner::Inner::Script(_, inner::ScriptType::Tr) => true,
467            inner::Inner::CovScript(_, _) => false,
468        }
469    }
470
471    /// Signature type of the spend
472    pub fn sig_type(&self) -> SigType {
473        match self.inner {
474            inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => SigType::Schnorr,
475            inner::Inner::Script(_, inner::ScriptType::Tr) => SigType::Schnorr,
476            inner::Inner::PublicKey(_, inner::PubkeyType::Pk)
477            | inner::Inner::PublicKey(_, inner::PubkeyType::Pkh)
478            | inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh)
479            | inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh)
480            | inner::Inner::Script(_, inner::ScriptType::Bare)
481            | inner::Inner::Script(_, inner::ScriptType::Sh)
482            | inner::Inner::Script(_, inner::ScriptType::Wsh)
483            | inner::Inner::Script(_, inner::ScriptType::ShWsh)
484            | inner::Inner::CovScript(_, _) => SigType::Ecdsa,
485        }
486    }
487
488    /// Outputs a "descriptor" which reproduces the spent coins
489    ///
490    /// This may not represent the original descriptor used to produce the transaction,
491    /// since it cannot distinguish between sorted and unsorted multisigs (and anyway
492    /// it can only see the final keys, keyorigin info is lost in serializing to Bitcoin).
493    /// x-only keys are translated to [`bitcoin::PublicKey`] with 0x02 prefix.
494    pub fn inferred_descriptor(
495        &self,
496    ) -> Result<Descriptor<bitcoin::PublicKey, CovenantExt<CovExtArgs>>, crate::Error> {
497        Descriptor::from_str(&self.inferred_descriptor_string())
498    }
499}
500
501/// Type of HashLock used for SatisfiedConstraint structure
502#[derive(Copy, Clone, Debug, Eq, PartialEq)]
503pub enum HashLockType {
504    ///SHA 256 hashlock
505    Sha256(sha256::Hash),
506    ///Hash 256 hashlock
507    Hash256(hash256::Hash),
508    ///Hash160 hashlock
509    Hash160(hash160::Hash),
510    ///Ripemd160 hashlock
511    Ripemd160(ripemd160::Hash),
512}
513
514/// A satisfied Miniscript condition (Signature, Hashlock, Timelock)
515/// 'intp represents the lifetime of descriptor and `stack represents
516/// the lifetime of witness
517#[derive(Clone, Debug, Eq, PartialEq)]
518pub enum SatisfiedConstraint<Ext: Extension> {
519    ///Public key and corresponding signature
520    PublicKey {
521        /// KeySig pair
522        key_sig: KeySigPair,
523    },
524    ///PublicKeyHash, corresponding pubkey and signature
525    PublicKeyHash {
526        /// The pubkey hash
527        keyhash: hash160::Hash,
528        /// public key and signature
529        key_sig: KeySigPair,
530    },
531    ///Hashlock and preimage for SHA256
532    HashLock {
533        /// The type of Hashlock
534        hash: HashLockType,
535        /// The preimage used for satisfaction
536        preimage: [u8; 32],
537    },
538    ///Relative Timelock for CSV.
539    RelativeTimelock {
540        /// The value of RelativeTimelock
541        n: Sequence,
542    },
543    ///Absolute Timelock for CLTV.
544    AbsoluteTimelock {
545        /// The value of Absolute timelock
546        n: LockTime,
547    },
548
549    /// Elements
550    /// Check Version eq
551    VerEq {
552        /// The version of transaction
553        n: u32,
554    },
555
556    /// Serialized outputs of this transaction start
557    /// this prefix
558    OutputsPref {
559        /// The version of transaction
560        pref: Vec<u8>,
561    },
562
563    /// Extension Interpreter
564    Ext {
565        /// Extension
566        ext: Box<Ext>,
567    },
568}
569
570///This is used by the interpreter to know which evaluation state a AstemElem is.
571///This is required because whenever a same node(for eg. OrB) appears on the stack, we don't
572///know if the left child has been evaluated or not. And based on the result on
573///the top of the stack, we need to decide whether to execute right child or not.
574///This is also useful for wrappers and thresholds which push a value on the stack
575///depending on evaluation of the children.
576struct NodeEvaluationState<'intp, Ext>
577where
578    Ext: Extension,
579{
580    ///The node which is being evaluated
581    node: &'intp Miniscript<BitcoinKey, NoChecks, Ext>,
582    ///number of children evaluated
583    n_evaluated: usize,
584    ///number of children satisfied
585    n_satisfied: usize,
586}
587
588/// Iterator over all the constraints satisfied by a completed scriptPubKey
589/// and witness stack
590///
591/// Returns all satisfied constraints, even if they were redundant (i.e. did
592/// not contribute to the script being satisfied). For example, if a signature
593/// were provided for an `and_b(Pk,false)` fragment, that signature will be
594/// returned, even though the entire and_b must have failed and must not have
595/// been used.
596///
597/// In case the script is actually dissatisfied, this may return several values
598/// before ultimately returning an error.
599pub struct Iter<'intp, 'txin: 'intp, Ext>
600where
601    Ext: Extension,
602{
603    verify_sig: Box<dyn FnMut(&KeySigPair) -> bool + 'intp>,
604    public_key: Option<&'intp BitcoinKey>,
605    state: Vec<NodeEvaluationState<'intp, Ext>>,
606    stack: Stack<'txin>,
607    txenv: Option<&'txin TxEnv<'txin, 'txin>>,
608    age: Sequence,
609    lock_time: LockTime,
610    cov: Option<&'intp BitcoinKey>,
611    has_errored: bool,
612    sig_type: SigType,
613}
614
615///Iterator for Iter
616impl<'intp, 'txin: 'intp, Ext> Iterator for Iter<'intp, 'txin, Ext>
617where
618    NoChecks: ScriptContext,
619    Ext: ParseableExt,
620{
621    type Item = Result<SatisfiedConstraint<Ext>, Error>;
622
623    fn next(&mut self) -> Option<Self::Item> {
624        if self.has_errored {
625            // Stop yielding values after the first error
626            None
627        } else {
628            let res = self.iter_next();
629            if let Some(Err(_)) = res {
630                self.has_errored = true;
631            }
632            res
633        }
634    }
635}
636
637impl<'intp, 'txin: 'intp, Ext> Iter<'intp, 'txin, Ext>
638where
639    NoChecks: ScriptContext,
640    Ext: ParseableExt,
641{
642    /// Helper function to push a NodeEvaluationState on state stack
643    fn push_evaluation_state(
644        &mut self,
645        node: &'intp Miniscript<BitcoinKey, NoChecks, Ext>,
646        n_evaluated: usize,
647        n_satisfied: usize,
648    ) {
649        self.state.push(NodeEvaluationState {
650            node,
651            n_evaluated,
652            n_satisfied,
653        })
654    }
655
656    /// Helper function to step the iterator
657    fn iter_next(&mut self) -> Option<Result<SatisfiedConstraint<Ext>, Error>> {
658        while let Some(node_state) = self.state.pop() {
659            //non-empty stack
660            match node_state.node.node {
661                Terminal::True => {
662                    debug_assert_eq!(node_state.n_evaluated, 0);
663                    debug_assert_eq!(node_state.n_satisfied, 0);
664                    self.stack.push(stack::Element::Satisfied);
665                }
666                Terminal::False => {
667                    debug_assert_eq!(node_state.n_evaluated, 0);
668                    debug_assert_eq!(node_state.n_satisfied, 0);
669                    self.stack.push(stack::Element::Dissatisfied);
670                }
671                Terminal::PkK(ref pk) => {
672                    debug_assert_eq!(node_state.n_evaluated, 0);
673                    debug_assert_eq!(node_state.n_satisfied, 0);
674                    let res = self.stack.evaluate_pk(&mut self.verify_sig, *pk);
675                    if res.is_some() {
676                        return res;
677                    }
678                }
679                Terminal::PkH(ref pk) => {
680                    debug_assert_eq!(node_state.n_evaluated, 0);
681                    debug_assert_eq!(node_state.n_satisfied, 0);
682                    let res = self.stack.evaluate_pkh(
683                        &mut self.verify_sig,
684                        pk.to_pubkeyhash(self.sig_type),
685                        self.sig_type,
686                    );
687                    if res.is_some() {
688                        return res;
689                    }
690                }
691                Terminal::RawPkH(ref pkh) => {
692                    debug_assert_eq!(node_state.n_evaluated, 0);
693                    debug_assert_eq!(node_state.n_satisfied, 0);
694                    let res = self
695                        .stack
696                        .evaluate_pkh(&mut self.verify_sig, *pkh, self.sig_type);
697                    if res.is_some() {
698                        return res;
699                    }
700                }
701                Terminal::After(ref n) => {
702                    debug_assert_eq!(node_state.n_evaluated, 0);
703                    debug_assert_eq!(node_state.n_satisfied, 0);
704                    return Some(self.stack.evaluate_after(LockTime::from(*n), self.lock_time));
705                }
706                Terminal::Older(ref n) => {
707                    debug_assert_eq!(node_state.n_evaluated, 0);
708                    debug_assert_eq!(node_state.n_satisfied, 0);
709                    return Some(self.stack.evaluate_older(*n, self.age));
710                }
711                Terminal::Sha256(ref hash) => {
712                    debug_assert_eq!(node_state.n_evaluated, 0);
713                    debug_assert_eq!(node_state.n_satisfied, 0);
714                    let res = self.stack.evaluate_sha256(hash);
715                    if res.is_some() {
716                        return res;
717                    }
718                }
719                Terminal::Hash256(ref hash) => {
720                    debug_assert_eq!(node_state.n_evaluated, 0);
721                    debug_assert_eq!(node_state.n_satisfied, 0);
722                    let res = self.stack.evaluate_hash256(hash);
723                    if res.is_some() {
724                        return res;
725                    }
726                }
727                Terminal::Hash160(ref hash) => {
728                    debug_assert_eq!(node_state.n_evaluated, 0);
729                    debug_assert_eq!(node_state.n_satisfied, 0);
730                    let res = self.stack.evaluate_hash160(hash);
731                    if res.is_some() {
732                        return res;
733                    }
734                }
735                Terminal::Ripemd160(ref hash) => {
736                    debug_assert_eq!(node_state.n_evaluated, 0);
737                    debug_assert_eq!(node_state.n_satisfied, 0);
738                    let res = self.stack.evaluate_ripemd160(hash);
739                    if res.is_some() {
740                        return res;
741                    }
742                }
743                Terminal::Ext(ref ext) => {
744                    let res = ext.evaluate(&mut self.stack, self.txenv);
745                    match res {
746                        Ok(true) => {
747                            return Some(Ok(SatisfiedConstraint::Ext {
748                                ext: Box::new(ext.clone()),
749                            }))
750                        }
751                        Err(e) => return Some(Err(e)),
752                        Ok(false) => {}
753                    }
754                }
755                Terminal::Alt(ref sub) | Terminal::Swap(ref sub) | Terminal::Check(ref sub) => {
756                    debug_assert_eq!(node_state.n_evaluated, 0);
757                    debug_assert_eq!(node_state.n_satisfied, 0);
758                    self.push_evaluation_state(sub, 0, 0);
759                }
760                Terminal::DupIf(ref sub) if node_state.n_evaluated == 0 => match self.stack.pop() {
761                    Some(stack::Element::Dissatisfied) => {
762                        self.stack.push(stack::Element::Dissatisfied);
763                    }
764                    Some(stack::Element::Satisfied) => {
765                        self.push_evaluation_state(node_state.node, 1, 1);
766                        self.push_evaluation_state(sub, 0, 0);
767                    }
768                    Some(stack::Element::Push(_v)) => {
769                        return Some(Err(Error::UnexpectedStackElementPush))
770                    }
771                    None => return Some(Err(Error::UnexpectedStackEnd)),
772                },
773                Terminal::DupIf(ref _sub) if node_state.n_evaluated == 1 => {
774                    self.stack.push(stack::Element::Satisfied);
775                }
776                Terminal::ZeroNotEqual(ref sub) | Terminal::Verify(ref sub)
777                    if node_state.n_evaluated == 0 =>
778                {
779                    self.push_evaluation_state(node_state.node, 1, 0);
780                    self.push_evaluation_state(sub, 0, 0);
781                }
782                Terminal::Verify(ref _sub) if node_state.n_evaluated == 1 => {
783                    match self.stack.pop() {
784                        Some(stack::Element::Satisfied) => (),
785                        Some(_) => return Some(Err(Error::VerifyFailed)),
786                        None => return Some(Err(Error::UnexpectedStackEnd)),
787                    }
788                }
789                Terminal::ZeroNotEqual(ref _sub) if node_state.n_evaluated == 1 => {
790                    match self.stack.pop() {
791                        Some(stack::Element::Dissatisfied) => {
792                            self.stack.push(stack::Element::Dissatisfied)
793                        }
794                        Some(_) => self.stack.push(stack::Element::Satisfied),
795                        None => return Some(Err(Error::UnexpectedStackEnd)),
796                    }
797                }
798                Terminal::NonZero(ref sub) => {
799                    debug_assert_eq!(node_state.n_evaluated, 0);
800                    debug_assert_eq!(node_state.n_satisfied, 0);
801                    match self.stack.last() {
802                        Some(&stack::Element::Dissatisfied) => (),
803                        Some(_) => self.push_evaluation_state(sub, 0, 0),
804                        None => return Some(Err(Error::UnexpectedStackEnd)),
805                    }
806                }
807                Terminal::AndV(ref left, ref right) => {
808                    debug_assert_eq!(node_state.n_evaluated, 0);
809                    debug_assert_eq!(node_state.n_satisfied, 0);
810                    self.push_evaluation_state(right, 0, 0);
811                    self.push_evaluation_state(left, 0, 0);
812                }
813                Terminal::OrB(ref left, ref _right) | Terminal::AndB(ref left, ref _right)
814                    if node_state.n_evaluated == 0 =>
815                {
816                    self.push_evaluation_state(node_state.node, 1, 0);
817                    self.push_evaluation_state(left, 0, 0);
818                }
819                Terminal::OrB(ref _left, ref right) | Terminal::AndB(ref _left, ref right)
820                    if node_state.n_evaluated == 1 =>
821                {
822                    match self.stack.pop() {
823                        Some(stack::Element::Dissatisfied) => {
824                            self.push_evaluation_state(node_state.node, 2, 0);
825                            self.push_evaluation_state(right, 0, 0);
826                        }
827                        Some(stack::Element::Satisfied) => {
828                            self.push_evaluation_state(node_state.node, 2, 1);
829                            self.push_evaluation_state(right, 0, 0);
830                        }
831                        Some(stack::Element::Push(_v)) => {
832                            return Some(Err(Error::UnexpectedStackElementPush))
833                        }
834                        None => return Some(Err(Error::UnexpectedStackEnd)),
835                    }
836                }
837                Terminal::AndB(ref _left, ref _right) if node_state.n_evaluated == 2 => {
838                    match self.stack.pop() {
839                        Some(stack::Element::Satisfied) if node_state.n_satisfied == 1 => {
840                            self.stack.push(stack::Element::Satisfied)
841                        }
842                        Some(_) => self.stack.push(stack::Element::Dissatisfied),
843                        None => return Some(Err(Error::UnexpectedStackEnd)),
844                    }
845                }
846                Terminal::AndOr(ref left, ref _right, _)
847                | Terminal::OrC(ref left, ref _right)
848                | Terminal::OrD(ref left, ref _right)
849                    if node_state.n_evaluated == 0 =>
850                {
851                    self.push_evaluation_state(node_state.node, 1, 0);
852                    self.push_evaluation_state(left, 0, 0);
853                }
854                Terminal::OrB(ref _left, ref _right) if node_state.n_evaluated == 2 => {
855                    match self.stack.pop() {
856                        Some(stack::Element::Dissatisfied) if node_state.n_satisfied == 0 => {
857                            self.stack.push(stack::Element::Dissatisfied)
858                        }
859                        Some(_) => {
860                            self.stack.push(stack::Element::Satisfied);
861                        }
862                        None => return Some(Err(Error::UnexpectedStackEnd)),
863                    }
864                }
865                Terminal::OrC(ref _left, ref right) if node_state.n_evaluated == 1 => {
866                    match self.stack.pop() {
867                        Some(stack::Element::Satisfied) => (),
868                        Some(stack::Element::Dissatisfied) => {
869                            self.push_evaluation_state(right, 0, 0)
870                        }
871                        Some(stack::Element::Push(_v)) => {
872                            return Some(Err(Error::UnexpectedStackElementPush))
873                        }
874                        None => return Some(Err(Error::UnexpectedStackEnd)),
875                    }
876                }
877                Terminal::OrD(ref _left, ref right) if node_state.n_evaluated == 1 => {
878                    match self.stack.pop() {
879                        Some(stack::Element::Satisfied) => {
880                            self.stack.push(stack::Element::Satisfied)
881                        }
882                        Some(stack::Element::Dissatisfied) => {
883                            self.push_evaluation_state(right, 0, 0)
884                        }
885                        Some(stack::Element::Push(_v)) => {
886                            return Some(Err(Error::UnexpectedStackElementPush))
887                        }
888                        None => return Some(Err(Error::UnexpectedStackEnd)),
889                    }
890                }
891                Terminal::AndOr(_, ref left, ref right) | Terminal::OrI(ref left, ref right) => {
892                    match self.stack.pop() {
893                        Some(stack::Element::Satisfied) => self.push_evaluation_state(left, 0, 0),
894                        Some(stack::Element::Dissatisfied) => {
895                            self.push_evaluation_state(right, 0, 0)
896                        }
897                        Some(stack::Element::Push(_v)) => {
898                            return Some(Err(Error::UnexpectedStackElementPush))
899                        }
900                        None => return Some(Err(Error::UnexpectedStackEnd)),
901                    }
902                }
903                Terminal::Thresh(ref _k, ref subs) if node_state.n_evaluated == 0 => {
904                    self.push_evaluation_state(node_state.node, 1, 0);
905                    self.push_evaluation_state(&subs[0], 0, 0);
906                }
907                Terminal::Thresh(k, ref subs) if node_state.n_evaluated == subs.len() => {
908                    match self.stack.pop() {
909                        Some(stack::Element::Dissatisfied) if node_state.n_satisfied == k => {
910                            self.stack.push(stack::Element::Satisfied)
911                        }
912                        Some(stack::Element::Satisfied) if node_state.n_satisfied == k - 1 => {
913                            self.stack.push(stack::Element::Satisfied)
914                        }
915                        Some(stack::Element::Satisfied) | Some(stack::Element::Dissatisfied) => {
916                            self.stack.push(stack::Element::Dissatisfied)
917                        }
918                        Some(stack::Element::Push(_v)) => {
919                            return Some(Err(Error::UnexpectedStackElementPush))
920                        }
921                        None => return Some(Err(Error::UnexpectedStackEnd)),
922                    }
923                }
924                Terminal::Thresh(ref _k, ref subs) if node_state.n_evaluated != 0 => {
925                    match self.stack.pop() {
926                        Some(stack::Element::Dissatisfied) => {
927                            self.push_evaluation_state(
928                                node_state.node,
929                                node_state.n_evaluated + 1,
930                                node_state.n_satisfied,
931                            );
932                            self.push_evaluation_state(&subs[node_state.n_evaluated], 0, 0);
933                        }
934                        Some(stack::Element::Satisfied) => {
935                            self.push_evaluation_state(
936                                node_state.node,
937                                node_state.n_evaluated + 1,
938                                node_state.n_satisfied + 1,
939                            );
940                            self.push_evaluation_state(&subs[node_state.n_evaluated], 0, 0);
941                        }
942                        Some(stack::Element::Push(_v)) => {
943                            return Some(Err(Error::UnexpectedStackElementPush))
944                        }
945                        None => return Some(Err(Error::UnexpectedStackEnd)),
946                    }
947                }
948                Terminal::MultiA(k, ref subs) => {
949                    if node_state.n_evaluated == subs.len() {
950                        if node_state.n_satisfied == k {
951                            self.stack.push(stack::Element::Satisfied);
952                        } else {
953                            self.stack.push(stack::Element::Dissatisfied);
954                        }
955                    } else {
956                        // evaluate each key with as a pk
957                        // note that evaluate_pk will error on non-empty incorrect sigs
958                        // push 1 on satisfied sigs and push 0 on empty sigs
959                        match self
960                            .stack
961                            .evaluate_pk(&mut self.verify_sig, subs[node_state.n_evaluated])
962                        {
963                            Some(Ok(x)) => {
964                                self.push_evaluation_state(
965                                    node_state.node,
966                                    node_state.n_evaluated + 1,
967                                    node_state.n_satisfied + 1,
968                                );
969                                match self.stack.pop() {
970                                    Some(..) => return Some(Ok(x)),
971                                    None => return Some(Err(Error::UnexpectedStackEnd)),
972                                }
973                            }
974                            None => {
975                                self.push_evaluation_state(
976                                    node_state.node,
977                                    node_state.n_evaluated + 1,
978                                    node_state.n_satisfied,
979                                );
980                                match self.stack.pop() {
981                                    Some(..) => {} // not-satisfied, look for next key
982                                    None => return Some(Err(Error::UnexpectedStackEnd)),
983                                }
984                            }
985                            x => return x, //forward errors as is
986                        }
987                    }
988                }
989                Terminal::Multi(ref k, ref subs) if node_state.n_evaluated == 0 => {
990                    let len = self.stack.len();
991                    if len < k + 1 {
992                        return Some(Err(Error::InsufficientSignaturesMultiSig));
993                    } else {
994                        //Non-sat case. If the first sig is empty, others k elements must
995                        //be empty.
996                        match self.stack.last() {
997                            Some(&stack::Element::Dissatisfied) => {
998                                //Remove the extra zero from multi-sig check
999                                let sigs = self.stack.split_off(len - (k + 1));
1000                                let nonsat = sigs
1001                                    .iter()
1002                                    .map(|sig| *sig == stack::Element::Dissatisfied)
1003                                    .filter(|empty| *empty)
1004                                    .count();
1005                                if nonsat == *k + 1 {
1006                                    self.stack.push(stack::Element::Dissatisfied);
1007                                } else {
1008                                    return Some(Err(Error::MissingExtraZeroMultiSig));
1009                                }
1010                            }
1011                            None => return Some(Err(Error::UnexpectedStackEnd)),
1012                            _ => {
1013                                match self
1014                                    .stack
1015                                    .evaluate_multi(&mut self.verify_sig, &subs[subs.len() - 1])
1016                                {
1017                                    Some(Ok(x)) => {
1018                                        self.push_evaluation_state(
1019                                            node_state.node,
1020                                            node_state.n_evaluated + 1,
1021                                            node_state.n_satisfied + 1,
1022                                        );
1023                                        return Some(Ok(x));
1024                                    }
1025                                    None => self.push_evaluation_state(
1026                                        node_state.node,
1027                                        node_state.n_evaluated + 1,
1028                                        node_state.n_satisfied,
1029                                    ),
1030                                    x => return x, //forward errors as is
1031                                }
1032                            }
1033                        }
1034                    }
1035                }
1036                Terminal::Multi(k, ref subs) => {
1037                    if node_state.n_satisfied == k {
1038                        //multi-sig bug: Pop extra 0
1039                        if let Some(stack::Element::Dissatisfied) = self.stack.pop() {
1040                            self.stack.push(stack::Element::Satisfied);
1041                        } else {
1042                            return Some(Err(Error::MissingExtraZeroMultiSig));
1043                        }
1044                    } else if node_state.n_evaluated == subs.len() {
1045                        return Some(Err(Error::MultiSigEvaluationError));
1046                    } else {
1047                        match self.stack.evaluate_multi(
1048                            &mut self.verify_sig,
1049                            &subs[subs.len() - node_state.n_evaluated - 1],
1050                        ) {
1051                            Some(Ok(x)) => {
1052                                self.push_evaluation_state(
1053                                    node_state.node,
1054                                    node_state.n_evaluated + 1,
1055                                    node_state.n_satisfied + 1,
1056                                );
1057                                return Some(Ok(x));
1058                            }
1059                            None => self.push_evaluation_state(
1060                                node_state.node,
1061                                node_state.n_evaluated + 1,
1062                                node_state.n_satisfied,
1063                            ),
1064                            x => return x, //forward errors as is
1065                        }
1066                    }
1067                }
1068                //All other match patterns should not be reached in any valid
1069                //type checked Miniscript
1070                _ => return Some(Err(Error::CouldNotEvaluate)),
1071            };
1072        }
1073
1074        //state empty implies that either the execution has terminated or we have a
1075        //Pk based descriptor or a Covenant descriptor
1076        if let Some(pk) = self.cov {
1077            // First verify the top of Miniscript.
1078            // At this point, the stack must contain 13 elements
1079            // pop the satisfied top and verify the covenant code.
1080            if self.stack.pop() != Some(stack::Element::Satisfied) {
1081                return Some(Err(Error::IncorrectCovenantWitness));
1082            }
1083            if self.stack.len() != 12 {
1084                return Some(Err(Error::UnexpectedStackEnd));
1085            }
1086            // safe to unwrap 12 times
1087            for i in 0..12 {
1088                if let Err(e) = self.stack[i].try_push() {
1089                    return Some(Err(e));
1090                }
1091            }
1092            let mut ser_sig = Vec::new();
1093            // 1.29 errors
1094            {
1095                let sighash_bytes = self.stack[1].as_push().expect("Push checked above");
1096                let sighash_u32 = util::slice_to_u32_le(sighash_bytes);
1097                let sighash_ty = EcdsaSighashType::from_u32(sighash_u32);
1098                let sig_vec = self.stack[0].as_push().expect("Size checked above");
1099                ser_sig.extend(sig_vec);
1100                ser_sig.push(sighash_ty as u8);
1101            }
1102
1103            if let Ok(sig) = verify_sersig(&mut self.verify_sig, pk, &ser_sig) {
1104                //Signature check successful, set cov to None to
1105                //terminate the next() function in the subsequent call
1106                self.cov = None;
1107                // Do the checkSigFromStackCheck
1108                let sighash_msg: Vec<u8> = self.stack.0[1..]
1109                    .iter()
1110                    .rev()
1111                    .flat_map(|x| Vec::from(x.as_push().expect("Push checked above")))
1112                    .collect();
1113                let mut eng = sha256d::Hash::engine();
1114                eng.input(&sighash_msg);
1115                let sighash_u256 = sha256d::Hash::from_engine(eng);
1116                let msg =
1117                    elements::secp256k1_zkp::Message::from_digest_slice(sighash_u256.as_ref())
1118                        .unwrap();
1119
1120                // Legacy Cov scripts only operate on Ecdsa key sig pairs
1121                let (ec_pk, ecdsa_sig) = match sig {
1122                    KeySigPair::Ecdsa(pk, sig) => (pk, sig.0),
1123                    KeySigPair::Schnorr(_, _) => {
1124                        unreachable!("Internal error: Legacy cov check in schnorr sigs")
1125                    }
1126                };
1127                // Creating a context is no-longer expensive
1128                let secp = secp256k1_zkp::Secp256k1::verification_only();
1129                if secp.verify_ecdsa(&msg, &ecdsa_sig, &ec_pk.inner).is_err() {
1130                    return Some(Err(Error::PkEvaluationError(PkEvalErrInner::from(*pk))));
1131                }
1132                self.stack.0.clear();
1133                self.stack.push(stack::Element::Satisfied);
1134                return Some(Ok(SatisfiedConstraint::PublicKey { key_sig: sig }));
1135            } else {
1136                return Some(Err(Error::PkEvaluationError(PkEvalErrInner::from(*pk))));
1137            }
1138        }
1139        if let Some(pk) = self.public_key {
1140            if let Some(stack::Element::Push(sig)) = self.stack.pop() {
1141                if let Ok(key_sig) = verify_sersig(&mut self.verify_sig, pk, sig) {
1142                    //Signature check successful, set public_key to None to
1143                    //terminate the next() function in the subsequent call
1144                    self.public_key = None;
1145                    self.stack.push(stack::Element::Satisfied);
1146                    Some(Ok(SatisfiedConstraint::PublicKey { key_sig }))
1147                } else {
1148                    Some(Err(Error::PkEvaluationError(PkEvalErrInner::from(*pk))))
1149                }
1150            } else {
1151                Some(Err(Error::UnexpectedStackEnd))
1152            }
1153        } else {
1154            //All the script has been executed.
1155            //Check that the stack must contain exactly 1 satisfied element
1156            if self.stack.pop() == Some(stack::Element::Satisfied) && self.stack.is_empty() {
1157                None
1158            } else {
1159                Some(Err(Error::ScriptSatisfactionError))
1160            }
1161        }
1162    }
1163}
1164
1165/// Helper function to verify serialized signature
1166fn verify_sersig<'txin>(
1167    verify_sig: &mut Box<dyn FnMut(&KeySigPair) -> bool + 'txin>,
1168    pk: &BitcoinKey,
1169    sigser: &[u8],
1170) -> Result<KeySigPair, Error> {
1171    match pk {
1172        BitcoinKey::Fullkey(pk) => {
1173            let ecdsa_sig = elementssig_from_rawsig(sigser)?;
1174            let key_sig_pair = KeySigPair::Ecdsa(*pk, ecdsa_sig);
1175            if verify_sig(&key_sig_pair) {
1176                Ok(key_sig_pair)
1177            } else {
1178                Err(Error::InvalidEcdsaSignature(*pk))
1179            }
1180        }
1181        BitcoinKey::XOnlyPublicKey(x_only_pk) => {
1182            let schnorr_sig = elements::SchnorrSig::from_slice(sigser)?;
1183            let key_sig_pair = KeySigPair::Schnorr(*x_only_pk, schnorr_sig);
1184            if verify_sig(&key_sig_pair) {
1185                Ok(key_sig_pair)
1186            } else {
1187                Err(Error::InvalidSchnorrSignature(*x_only_pk))
1188            }
1189        }
1190    }
1191}
1192
1193#[cfg(test)]
1194mod tests {
1195
1196    use bitcoin;
1197    use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
1198    use elements::secp256k1_zkp::{self, Secp256k1};
1199
1200    use super::inner::ToNoChecks;
1201    use super::*;
1202    use crate::miniscript::analyzable::ExtParams;
1203    use crate::miniscript::context::NoChecks;
1204    use crate::{ElementsSig, Miniscript, NoExt, ToPublicKey};
1205
1206    fn setup_keys_sigs(
1207        n: usize,
1208    ) -> (
1209        Vec<bitcoin::PublicKey>,
1210        Vec<Vec<u8>>,
1211        Vec<ElementsSig>,
1212        secp256k1_zkp::Message,
1213        Secp256k1<secp256k1_zkp::All>,
1214        Vec<bitcoin::key::XOnlyPublicKey>,
1215        Vec<elements::SchnorrSig>,
1216        Vec<Vec<u8>>,
1217    ) {
1218        let secp = secp256k1_zkp::Secp256k1::new();
1219        let msg =
1220            secp256k1_zkp::Message::from_digest_slice(&b"Yoda: btc, I trust. HODL I must!"[..])
1221                .expect("32 bytes");
1222        let mut pks = vec![];
1223        let mut ecdsa_sigs = vec![];
1224        let mut der_sigs = vec![];
1225        let mut x_only_pks = vec![];
1226        let mut schnorr_sigs = vec![];
1227        let mut ser_schnorr_sigs = vec![];
1228
1229        let mut sk = [0; 32];
1230        for i in 1..n + 1 {
1231            sk[0] = i as u8;
1232            sk[1] = (i >> 8) as u8;
1233            sk[2] = (i >> 16) as u8;
1234
1235            let sk = secp256k1_zkp::SecretKey::from_slice(&sk[..]).expect("secret key");
1236            let pk = bitcoin::PublicKey {
1237                inner: secp256k1_zkp::PublicKey::from_secret_key(&secp, &sk),
1238                compressed: true,
1239            };
1240            let sig = secp.sign_ecdsa(&msg, &sk);
1241            ecdsa_sigs.push((sig, elements::EcdsaSighashType::All));
1242            let mut sigser = sig.serialize_der().to_vec();
1243            sigser.push(0x01); // sighash_all
1244            pks.push(pk);
1245            der_sigs.push(sigser);
1246
1247            let keypair = bitcoin::key::Keypair::from_secret_key(&secp, &sk);
1248            let (x_only_pk, _parity) = bitcoin::key::XOnlyPublicKey::from_keypair(&keypair);
1249            x_only_pks.push(x_only_pk);
1250            let schnorr_sig = secp.sign_schnorr_with_aux_rand(&msg, &keypair, &[0u8; 32]);
1251            let schnorr_sig = elements::SchnorrSig {
1252                sig: schnorr_sig,
1253                hash_ty: elements::SchnorrSighashType::Default,
1254            };
1255            ser_schnorr_sigs.push(schnorr_sig.to_vec());
1256            schnorr_sigs.push(schnorr_sig);
1257        }
1258        (
1259            pks,
1260            der_sigs,
1261            ecdsa_sigs,
1262            msg,
1263            secp,
1264            x_only_pks,
1265            schnorr_sigs,
1266            ser_schnorr_sigs,
1267        )
1268    }
1269
1270    #[test]
1271    fn sat_constraints() {
1272        let (pks, der_sigs, ecdsa_sigs, sighash, secp, xpks, schnorr_sigs, ser_schnorr_sigs) =
1273            setup_keys_sigs(10);
1274        let secp_ref = &secp;
1275        let vfyfn = |pksig: &KeySigPair| match pksig {
1276            KeySigPair::Ecdsa(pk, ecdsa_sig) => secp_ref
1277                .verify_ecdsa(&sighash, &ecdsa_sig.0, &pk.inner)
1278                .is_ok(),
1279            KeySigPair::Schnorr(xpk, schnorr_sig) => secp_ref
1280                .verify_schnorr(&schnorr_sig.sig, &sighash, xpk)
1281                .is_ok(),
1282        };
1283
1284        fn from_stack<'txin, 'elem>(
1285            verify_fn: Box<dyn FnMut(&KeySigPair) -> bool + 'elem>,
1286            stack: Stack<'txin>,
1287            ms: &'elem Miniscript<BitcoinKey, NoChecks, NoExt>,
1288        ) -> Iter<'elem, 'txin, NoExt> {
1289            Iter {
1290                verify_sig: verify_fn,
1291                stack,
1292                public_key: None,
1293                state: vec![NodeEvaluationState {
1294                    node: ms,
1295                    n_evaluated: 0,
1296                    n_satisfied: 0,
1297                }],
1298                age: Sequence::from_height(1002),
1299                lock_time: LockTime::from_height(1002).unwrap(),
1300                cov: None,
1301                has_errored: false,
1302                txenv: None,
1303                sig_type: SigType::Ecdsa,
1304            }
1305        }
1306
1307        let pk = no_checks_ms(&format!("c:pk_k({})", pks[0]));
1308        let pkh = no_checks_ms(&format!("c:pk_h({})", pks[1]));
1309        //Time
1310        let after = no_checks_ms(&format!("after({})", 1000));
1311        let older = no_checks_ms(&format!("older({})", 1000));
1312        //Hashes
1313        let preimage = [0xab; 32];
1314        let sha256_hash = sha256::Hash::hash(&preimage);
1315        let sha256 = no_checks_ms(&format!("sha256({})", sha256_hash));
1316        let hash256_hash = hash256::Hash::hash(&preimage);
1317        let hash256 = no_checks_ms(&format!("hash256({})", hash256_hash));
1318        let hash160_hash = hash160::Hash::hash(&preimage);
1319        let hash160 = no_checks_ms(&format!("hash160({})", hash160_hash));
1320        let ripemd160_hash = ripemd160::Hash::hash(&preimage);
1321        let ripemd160 = no_checks_ms(&format!("ripemd160({})", ripemd160_hash));
1322
1323        let stack = Stack::from(vec![stack::Element::Push(&der_sigs[0])]);
1324        let constraints = from_stack(Box::new(vfyfn), stack, &pk);
1325        let pk_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1326
1327        assert_eq!(
1328            pk_satisfied.unwrap(),
1329            vec![SatisfiedConstraint::PublicKey {
1330                key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1331            }]
1332        );
1333
1334        //Check Pk failure with wrong signature
1335        let stack = Stack::from(vec![stack::Element::Dissatisfied]);
1336        let constraints = from_stack(Box::new(vfyfn), stack, &pk);
1337
1338        let pk_err: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1339        assert!(pk_err.is_err());
1340
1341        //Check Pkh
1342        let pk_bytes = pks[1].to_public_key().to_bytes();
1343        let stack = Stack::from(vec![
1344            stack::Element::Push(&der_sigs[1]),
1345            stack::Element::Push(&pk_bytes),
1346        ]);
1347        let constraints = from_stack(Box::new(vfyfn), stack, &pkh);
1348        let pkh_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1349        assert_eq!(
1350            pkh_satisfied.unwrap(),
1351            vec![SatisfiedConstraint::PublicKeyHash {
1352                keyhash: pks[1].to_pubkeyhash(SigType::Ecdsa),
1353                key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1354            }]
1355        );
1356
1357        //Check After
1358        let stack = Stack::from(vec![]);
1359        let constraints = from_stack(Box::new(vfyfn), stack, &after);
1360        let after_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1361        assert_eq!(
1362            after_satisfied.unwrap(),
1363            vec![SatisfiedConstraint::AbsoluteTimelock {
1364                n: LockTime::from_height(1000).unwrap()
1365            }]
1366        );
1367
1368        //Check Older
1369        let stack = Stack::from(vec![]);
1370        let constraints = from_stack(Box::new(vfyfn), stack, &older);
1371        let older_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1372        assert_eq!(
1373            older_satisfied.unwrap(),
1374            vec![SatisfiedConstraint::RelativeTimelock {
1375                n: Sequence::from_height(1000)
1376            }]
1377        );
1378
1379        //Check Sha256
1380        let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1381        let constraints = from_stack(Box::new(vfyfn), stack, &sha256);
1382        let sah256_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1383            constraints.collect();
1384        assert_eq!(
1385            sah256_satisfied.unwrap(),
1386            vec![SatisfiedConstraint::HashLock {
1387                hash: HashLockType::Sha256(sha256_hash),
1388                preimage,
1389            }]
1390        );
1391
1392        //Check Shad256
1393        let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1394        let constraints = from_stack(Box::new(vfyfn), stack, &hash256);
1395        let sha256d_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1396            constraints.collect();
1397        assert_eq!(
1398            sha256d_satisfied.unwrap(),
1399            vec![SatisfiedConstraint::HashLock {
1400                hash: HashLockType::Hash256(hash256_hash),
1401                preimage,
1402            }]
1403        );
1404
1405        //Check hash160
1406        let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1407        let constraints = from_stack(Box::new(vfyfn), stack, &hash160);
1408        let hash160_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1409            constraints.collect();
1410        assert_eq!(
1411            hash160_satisfied.unwrap(),
1412            vec![SatisfiedConstraint::HashLock {
1413                hash: HashLockType::Hash160(hash160_hash),
1414                preimage,
1415            }]
1416        );
1417
1418        //Check ripemd160
1419        let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1420        let constraints = from_stack(Box::new(vfyfn), stack, &ripemd160);
1421        let ripemd160_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1422            constraints.collect();
1423
1424        assert_eq!(
1425            ripemd160_satisfied.unwrap(),
1426            vec![SatisfiedConstraint::HashLock {
1427                hash: HashLockType::Ripemd160(ripemd160_hash),
1428                preimage,
1429            }]
1430        );
1431
1432        //Check AndV
1433        let pk_bytes = pks[1].to_public_key().to_bytes();
1434        let stack = Stack::from(vec![
1435            stack::Element::Push(&der_sigs[1]),
1436            stack::Element::Push(&pk_bytes),
1437            stack::Element::Push(&der_sigs[0]),
1438        ]);
1439        let elem = no_checks_ms(&format!("and_v(vc:pk_k({}),c:pk_h({}))", pks[0], pks[1]));
1440        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1441
1442        let and_v_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1443        assert_eq!(
1444            and_v_satisfied.unwrap(),
1445            vec![
1446                SatisfiedConstraint::PublicKey {
1447                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1448                },
1449                SatisfiedConstraint::PublicKeyHash {
1450                    keyhash: pks[1].to_pubkeyhash(SigType::Ecdsa),
1451                    key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1452                }
1453            ]
1454        );
1455
1456        //Check AndB
1457        let stack = Stack::from(vec![
1458            stack::Element::Push(&preimage),
1459            stack::Element::Push(&der_sigs[0]),
1460        ]);
1461        let elem = no_checks_ms(&format!(
1462            "and_b(c:pk_k({}),sjtv:sha256({}))",
1463            pks[0], sha256_hash
1464        ));
1465        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1466
1467        let and_b_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1468        assert_eq!(
1469            and_b_satisfied.unwrap(),
1470            vec![
1471                SatisfiedConstraint::PublicKey {
1472                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1473                },
1474                SatisfiedConstraint::HashLock {
1475                    hash: HashLockType::Sha256(sha256_hash),
1476                    preimage,
1477                }
1478            ]
1479        );
1480
1481        //Check AndOr
1482        let stack = Stack::from(vec![
1483            stack::Element::Push(&preimage),
1484            stack::Element::Push(&der_sigs[0]),
1485        ]);
1486        let elem = no_checks_ms(&format!(
1487            "andor(c:pk_k({}),jtv:sha256({}),c:pk_h({}))",
1488            pks[0], sha256_hash, pks[1],
1489        ));
1490        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1491
1492        let and_or_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1493            constraints.collect();
1494        assert_eq!(
1495            and_or_satisfied.unwrap(),
1496            vec![
1497                SatisfiedConstraint::PublicKey {
1498                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1499                },
1500                SatisfiedConstraint::HashLock {
1501                    hash: HashLockType::Sha256(sha256_hash),
1502                    preimage,
1503                }
1504            ]
1505        );
1506
1507        //AndOr second satisfaction path
1508        let pk_bytes = pks[1].to_public_key().to_bytes();
1509        let stack = Stack::from(vec![
1510            stack::Element::Push(&der_sigs[1]),
1511            stack::Element::Push(&pk_bytes),
1512            stack::Element::Dissatisfied,
1513        ]);
1514        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1515
1516        let and_or_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1517            constraints.collect();
1518        assert_eq!(
1519            and_or_satisfied.unwrap(),
1520            vec![SatisfiedConstraint::PublicKeyHash {
1521                keyhash: pks[1].to_pubkeyhash(SigType::Ecdsa),
1522                key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1523            }]
1524        );
1525
1526        //Check OrB
1527        let stack = Stack::from(vec![
1528            stack::Element::Push(&preimage),
1529            stack::Element::Dissatisfied,
1530        ]);
1531        let elem = no_checks_ms(&format!(
1532            "or_b(c:pk_k({}),sjtv:sha256({}))",
1533            pks[0], sha256_hash
1534        ));
1535        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1536
1537        let or_b_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1538        assert_eq!(
1539            or_b_satisfied.unwrap(),
1540            vec![SatisfiedConstraint::HashLock {
1541                hash: HashLockType::Sha256(sha256_hash),
1542                preimage,
1543            }]
1544        );
1545
1546        //Check OrD
1547        let stack = Stack::from(vec![stack::Element::Push(&der_sigs[0])]);
1548        let elem = no_checks_ms(&format!(
1549            "or_d(c:pk_k({}),jtv:sha256({}))",
1550            pks[0], sha256_hash
1551        ));
1552        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1553
1554        let or_d_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1555        assert_eq!(
1556            or_d_satisfied.unwrap(),
1557            vec![SatisfiedConstraint::PublicKey {
1558                key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1559            }]
1560        );
1561
1562        //Check OrC
1563        let stack = Stack::from(vec![
1564            stack::Element::Push(&der_sigs[0]),
1565            stack::Element::Dissatisfied,
1566        ]);
1567        let elem = no_checks_ms(&format!(
1568            "t:or_c(jtv:sha256({}),vc:pk_k({}))",
1569            sha256_hash, pks[0]
1570        ));
1571        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1572
1573        let or_c_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1574        assert_eq!(
1575            or_c_satisfied.unwrap(),
1576            vec![SatisfiedConstraint::PublicKey {
1577                key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1578            }]
1579        );
1580
1581        //Check OrI
1582        let stack = Stack::from(vec![
1583            stack::Element::Push(&der_sigs[0]),
1584            stack::Element::Dissatisfied,
1585        ]);
1586        let elem = no_checks_ms(&format!(
1587            "or_i(jtv:sha256({}),c:pk_k({}))",
1588            sha256_hash, pks[0]
1589        ));
1590        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1591
1592        let or_i_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1593        assert_eq!(
1594            or_i_satisfied.unwrap(),
1595            vec![SatisfiedConstraint::PublicKey {
1596                key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1597            }]
1598        );
1599
1600        //Check Thres
1601        let stack = Stack::from(vec![
1602            stack::Element::Push(&der_sigs[0]),
1603            stack::Element::Push(&der_sigs[1]),
1604            stack::Element::Push(&der_sigs[2]),
1605            stack::Element::Dissatisfied,
1606            stack::Element::Dissatisfied,
1607        ]);
1608        let elem = no_checks_ms(&format!(
1609            "thresh(3,c:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}))",
1610            pks[4], pks[3], pks[2], pks[1], pks[0],
1611        ));
1612        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1613
1614        let thresh_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1615            constraints.collect();
1616        assert_eq!(
1617            thresh_satisfied.unwrap(),
1618            vec![
1619                SatisfiedConstraint::PublicKey {
1620                    key_sig: KeySigPair::Ecdsa(pks[2], ecdsa_sigs[2])
1621                },
1622                SatisfiedConstraint::PublicKey {
1623                    key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1624                },
1625                SatisfiedConstraint::PublicKey {
1626                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1627                }
1628            ]
1629        );
1630
1631        // Check multi
1632        let stack = Stack::from(vec![
1633            stack::Element::Dissatisfied,
1634            stack::Element::Push(&der_sigs[2]),
1635            stack::Element::Push(&der_sigs[1]),
1636            stack::Element::Push(&der_sigs[0]),
1637        ]);
1638        let elem = no_checks_ms(&format!(
1639            "multi(3,{},{},{},{},{})",
1640            pks[4], pks[3], pks[2], pks[1], pks[0],
1641        ));
1642        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1643
1644        let multi_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1645        assert_eq!(
1646            multi_satisfied.unwrap(),
1647            vec![
1648                SatisfiedConstraint::PublicKey {
1649                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1650                },
1651                SatisfiedConstraint::PublicKey {
1652                    key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1653                },
1654                SatisfiedConstraint::PublicKey {
1655                    key_sig: KeySigPair::Ecdsa(pks[2], ecdsa_sigs[2])
1656                },
1657            ]
1658        );
1659
1660        // Error multi: Invalid order of sigs
1661        let stack = Stack::from(vec![
1662            stack::Element::Dissatisfied,
1663            stack::Element::Push(&der_sigs[0]),
1664            stack::Element::Push(&der_sigs[2]),
1665            stack::Element::Push(&der_sigs[1]),
1666        ]);
1667        let elem = no_checks_ms(&format!(
1668            "multi(3,{},{},{},{},{})",
1669            pks[4], pks[3], pks[2], pks[1], pks[0],
1670        ));
1671        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1672
1673        let multi_error: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1674        assert!(multi_error.is_err());
1675
1676        // multi_a tests
1677        let stack = Stack::from(vec![
1678            stack::Element::Dissatisfied,
1679            stack::Element::Dissatisfied,
1680            stack::Element::Push(&ser_schnorr_sigs[2]),
1681            stack::Element::Push(&ser_schnorr_sigs[1]),
1682            stack::Element::Push(&ser_schnorr_sigs[0]),
1683        ]);
1684
1685        let elem = x_only_no_checks_ms(&format!(
1686            "multi_a(3,{},{},{},{},{})",
1687            xpks[0], xpks[1], xpks[2], xpks[3], xpks[4],
1688        ));
1689        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1690
1691        let multi_a_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1692            constraints.collect();
1693        assert_eq!(
1694            multi_a_satisfied.unwrap(),
1695            vec![
1696                SatisfiedConstraint::PublicKey {
1697                    key_sig: KeySigPair::Schnorr(xpks[0], schnorr_sigs[0])
1698                },
1699                SatisfiedConstraint::PublicKey {
1700                    key_sig: KeySigPair::Schnorr(xpks[1], schnorr_sigs[1])
1701                },
1702                SatisfiedConstraint::PublicKey {
1703                    key_sig: KeySigPair::Schnorr(xpks[2], schnorr_sigs[2])
1704                },
1705            ]
1706        );
1707
1708        // multi_a tests: wrong order of sigs
1709        let stack = Stack::from(vec![
1710            stack::Element::Dissatisfied,
1711            stack::Element::Push(&ser_schnorr_sigs[2]),
1712            stack::Element::Push(&ser_schnorr_sigs[1]),
1713            stack::Element::Push(&ser_schnorr_sigs[0]),
1714            stack::Element::Dissatisfied,
1715        ]);
1716
1717        let elem = x_only_no_checks_ms(&format!(
1718            "multi_a(3,{},{},{},{},{})",
1719            xpks[0], xpks[1], xpks[2], xpks[3], xpks[4],
1720        ));
1721        let constraints = from_stack(Box::new(vfyfn), stack.clone(), &elem);
1722
1723        let multi_a_error: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1724        assert!(multi_a_error.is_err());
1725
1726        // multi_a wrong thresh: k = 2, but three sigs
1727        let elem = x_only_no_checks_ms(&format!(
1728            "multi_a(2,{},{},{},{},{})",
1729            xpks[0], xpks[1], xpks[2], xpks[3], xpks[4],
1730        ));
1731        let constraints = from_stack(Box::new(vfyfn), stack.clone(), &elem);
1732
1733        let multi_a_error: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1734        assert!(multi_a_error.is_err());
1735
1736        // multi_a correct thresh, but small stack
1737        let elem = x_only_no_checks_ms(&format!(
1738            "multi_a(3,{},{},{},{},{},{})",
1739            xpks[0], xpks[1], xpks[2], xpks[3], xpks[4], xpks[5]
1740        ));
1741        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1742
1743        let multi_a_error: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1744        assert!(multi_a_error.is_err());
1745    }
1746
1747    // By design there is no support for parse a miniscript with BitcoinKey
1748    // because it does not implement FromStr
1749    fn no_checks_ms(ms: &str) -> Miniscript<BitcoinKey, NoChecks> {
1750        // Parsing should allow raw hashes in the interpreter
1751        let elem: Miniscript<bitcoin::PublicKey, NoChecks> =
1752            Miniscript::from_str_ext(ms, &ExtParams::allow_all()).unwrap();
1753        elem.to_no_checks_ms()
1754    }
1755
1756    fn x_only_no_checks_ms(ms: &str) -> Miniscript<BitcoinKey, NoChecks> {
1757        let elem: Miniscript<bitcoin::key::XOnlyPublicKey, NoChecks> =
1758            Miniscript::from_str_ext(ms, &ExtParams::allow_all()).unwrap();
1759        elem.to_no_checks_ms()
1760    }
1761}