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 elements::hashes::{hash160, ripemd160, sha256, Hash, HashEngine};
17use elements::{self, secp256k1_zkp, sighash, EcdsaSighashType, LockTime, Sequence, Sighash};
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                    let res = self
705                        .stack
706                        .evaluate_after(&LockTime::from(*n), self.lock_time);
707                    if res.is_some() {
708                        return res;
709                    }
710                }
711                Terminal::Older(ref n) => {
712                    debug_assert_eq!(node_state.n_evaluated, 0);
713                    debug_assert_eq!(node_state.n_satisfied, 0);
714                    let res = self.stack.evaluate_older(n, self.age);
715                    if res.is_some() {
716                        return res;
717                    }
718                }
719                Terminal::Sha256(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_sha256(hash);
723                    if res.is_some() {
724                        return res;
725                    }
726                }
727                Terminal::Hash256(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_hash256(hash);
731                    if res.is_some() {
732                        return res;
733                    }
734                }
735                Terminal::Hash160(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_hash160(hash);
739                    if res.is_some() {
740                        return res;
741                    }
742                }
743                Terminal::Ripemd160(ref hash) => {
744                    debug_assert_eq!(node_state.n_evaluated, 0);
745                    debug_assert_eq!(node_state.n_satisfied, 0);
746                    let res = self.stack.evaluate_ripemd160(hash);
747                    if res.is_some() {
748                        return res;
749                    }
750                }
751                Terminal::Ext(ref ext) => {
752                    let res = ext.evaluate(&mut self.stack, self.txenv);
753                    match res {
754                        Ok(true) => {
755                            return Some(Ok(SatisfiedConstraint::Ext {
756                                ext: Box::new(ext.clone()),
757                            }))
758                        }
759                        Err(e) => return Some(Err(e)),
760                        Ok(false) => {}
761                    }
762                }
763                Terminal::Alt(ref sub) | Terminal::Swap(ref sub) | Terminal::Check(ref sub) => {
764                    debug_assert_eq!(node_state.n_evaluated, 0);
765                    debug_assert_eq!(node_state.n_satisfied, 0);
766                    self.push_evaluation_state(sub, 0, 0);
767                }
768                Terminal::DupIf(ref sub) if node_state.n_evaluated == 0 => match self.stack.pop() {
769                    Some(stack::Element::Dissatisfied) => {
770                        self.stack.push(stack::Element::Dissatisfied);
771                    }
772                    Some(stack::Element::Satisfied) => {
773                        self.push_evaluation_state(node_state.node, 1, 1);
774                        self.push_evaluation_state(sub, 0, 0);
775                    }
776                    Some(stack::Element::Push(_v)) => {
777                        return Some(Err(Error::UnexpectedStackElementPush))
778                    }
779                    None => return Some(Err(Error::UnexpectedStackEnd)),
780                },
781                Terminal::DupIf(ref _sub) if node_state.n_evaluated == 1 => {
782                    self.stack.push(stack::Element::Satisfied);
783                }
784                Terminal::ZeroNotEqual(ref sub) | Terminal::Verify(ref sub)
785                    if node_state.n_evaluated == 0 =>
786                {
787                    self.push_evaluation_state(node_state.node, 1, 0);
788                    self.push_evaluation_state(sub, 0, 0);
789                }
790                Terminal::Verify(ref _sub) if node_state.n_evaluated == 1 => {
791                    match self.stack.pop() {
792                        Some(stack::Element::Satisfied) => (),
793                        Some(_) => return Some(Err(Error::VerifyFailed)),
794                        None => return Some(Err(Error::UnexpectedStackEnd)),
795                    }
796                }
797                Terminal::ZeroNotEqual(ref _sub) if node_state.n_evaluated == 1 => {
798                    match self.stack.pop() {
799                        Some(stack::Element::Dissatisfied) => {
800                            self.stack.push(stack::Element::Dissatisfied)
801                        }
802                        Some(_) => self.stack.push(stack::Element::Satisfied),
803                        None => return Some(Err(Error::UnexpectedStackEnd)),
804                    }
805                }
806                Terminal::NonZero(ref sub) => {
807                    debug_assert_eq!(node_state.n_evaluated, 0);
808                    debug_assert_eq!(node_state.n_satisfied, 0);
809                    match self.stack.last() {
810                        Some(&stack::Element::Dissatisfied) => (),
811                        Some(_) => self.push_evaluation_state(sub, 0, 0),
812                        None => return Some(Err(Error::UnexpectedStackEnd)),
813                    }
814                }
815                Terminal::AndV(ref left, ref right) => {
816                    debug_assert_eq!(node_state.n_evaluated, 0);
817                    debug_assert_eq!(node_state.n_satisfied, 0);
818                    self.push_evaluation_state(right, 0, 0);
819                    self.push_evaluation_state(left, 0, 0);
820                }
821                Terminal::OrB(ref left, ref _right) | Terminal::AndB(ref left, ref _right)
822                    if node_state.n_evaluated == 0 =>
823                {
824                    self.push_evaluation_state(node_state.node, 1, 0);
825                    self.push_evaluation_state(left, 0, 0);
826                }
827                Terminal::OrB(ref _left, ref right) | Terminal::AndB(ref _left, ref right)
828                    if node_state.n_evaluated == 1 =>
829                {
830                    match self.stack.pop() {
831                        Some(stack::Element::Dissatisfied) => {
832                            self.push_evaluation_state(node_state.node, 2, 0);
833                            self.push_evaluation_state(right, 0, 0);
834                        }
835                        Some(stack::Element::Satisfied) => {
836                            self.push_evaluation_state(node_state.node, 2, 1);
837                            self.push_evaluation_state(right, 0, 0);
838                        }
839                        Some(stack::Element::Push(_v)) => {
840                            return Some(Err(Error::UnexpectedStackElementPush))
841                        }
842                        None => return Some(Err(Error::UnexpectedStackEnd)),
843                    }
844                }
845                Terminal::AndB(ref _left, ref _right) if node_state.n_evaluated == 2 => {
846                    match self.stack.pop() {
847                        Some(stack::Element::Satisfied) if node_state.n_satisfied == 1 => {
848                            self.stack.push(stack::Element::Satisfied)
849                        }
850                        Some(_) => self.stack.push(stack::Element::Dissatisfied),
851                        None => return Some(Err(Error::UnexpectedStackEnd)),
852                    }
853                }
854                Terminal::AndOr(ref left, ref _right, _)
855                | Terminal::OrC(ref left, ref _right)
856                | Terminal::OrD(ref left, ref _right)
857                    if node_state.n_evaluated == 0 =>
858                {
859                    self.push_evaluation_state(node_state.node, 1, 0);
860                    self.push_evaluation_state(left, 0, 0);
861                }
862                Terminal::OrB(ref _left, ref _right) if node_state.n_evaluated == 2 => {
863                    match self.stack.pop() {
864                        Some(stack::Element::Dissatisfied) if node_state.n_satisfied == 0 => {
865                            self.stack.push(stack::Element::Dissatisfied)
866                        }
867                        Some(_) => {
868                            self.stack.push(stack::Element::Satisfied);
869                        }
870                        None => return Some(Err(Error::UnexpectedStackEnd)),
871                    }
872                }
873                Terminal::OrC(ref _left, ref right) if node_state.n_evaluated == 1 => {
874                    match self.stack.pop() {
875                        Some(stack::Element::Satisfied) => (),
876                        Some(stack::Element::Dissatisfied) => {
877                            self.push_evaluation_state(right, 0, 0)
878                        }
879                        Some(stack::Element::Push(_v)) => {
880                            return Some(Err(Error::UnexpectedStackElementPush))
881                        }
882                        None => return Some(Err(Error::UnexpectedStackEnd)),
883                    }
884                }
885                Terminal::OrD(ref _left, ref right) if node_state.n_evaluated == 1 => {
886                    match self.stack.pop() {
887                        Some(stack::Element::Satisfied) => {
888                            self.stack.push(stack::Element::Satisfied)
889                        }
890                        Some(stack::Element::Dissatisfied) => {
891                            self.push_evaluation_state(right, 0, 0)
892                        }
893                        Some(stack::Element::Push(_v)) => {
894                            return Some(Err(Error::UnexpectedStackElementPush))
895                        }
896                        None => return Some(Err(Error::UnexpectedStackEnd)),
897                    }
898                }
899                Terminal::AndOr(_, ref left, ref right) | Terminal::OrI(ref left, ref right) => {
900                    match self.stack.pop() {
901                        Some(stack::Element::Satisfied) => self.push_evaluation_state(left, 0, 0),
902                        Some(stack::Element::Dissatisfied) => {
903                            self.push_evaluation_state(right, 0, 0)
904                        }
905                        Some(stack::Element::Push(_v)) => {
906                            return Some(Err(Error::UnexpectedStackElementPush))
907                        }
908                        None => return Some(Err(Error::UnexpectedStackEnd)),
909                    }
910                }
911                Terminal::Thresh(ref _k, ref subs) if node_state.n_evaluated == 0 => {
912                    self.push_evaluation_state(node_state.node, 1, 0);
913                    self.push_evaluation_state(&subs[0], 0, 0);
914                }
915                Terminal::Thresh(k, ref subs) if node_state.n_evaluated == subs.len() => {
916                    match self.stack.pop() {
917                        Some(stack::Element::Dissatisfied) if node_state.n_satisfied == k => {
918                            self.stack.push(stack::Element::Satisfied)
919                        }
920                        Some(stack::Element::Satisfied) if node_state.n_satisfied == k - 1 => {
921                            self.stack.push(stack::Element::Satisfied)
922                        }
923                        Some(stack::Element::Satisfied) | Some(stack::Element::Dissatisfied) => {
924                            self.stack.push(stack::Element::Dissatisfied)
925                        }
926                        Some(stack::Element::Push(_v)) => {
927                            return Some(Err(Error::UnexpectedStackElementPush))
928                        }
929                        None => return Some(Err(Error::UnexpectedStackEnd)),
930                    }
931                }
932                Terminal::Thresh(ref _k, ref subs) if node_state.n_evaluated != 0 => {
933                    match self.stack.pop() {
934                        Some(stack::Element::Dissatisfied) => {
935                            self.push_evaluation_state(
936                                node_state.node,
937                                node_state.n_evaluated + 1,
938                                node_state.n_satisfied,
939                            );
940                            self.push_evaluation_state(&subs[node_state.n_evaluated], 0, 0);
941                        }
942                        Some(stack::Element::Satisfied) => {
943                            self.push_evaluation_state(
944                                node_state.node,
945                                node_state.n_evaluated + 1,
946                                node_state.n_satisfied + 1,
947                            );
948                            self.push_evaluation_state(&subs[node_state.n_evaluated], 0, 0);
949                        }
950                        Some(stack::Element::Push(_v)) => {
951                            return Some(Err(Error::UnexpectedStackElementPush))
952                        }
953                        None => return Some(Err(Error::UnexpectedStackEnd)),
954                    }
955                }
956                Terminal::MultiA(k, ref subs) => {
957                    if node_state.n_evaluated == subs.len() {
958                        if node_state.n_satisfied == k {
959                            self.stack.push(stack::Element::Satisfied);
960                        } else {
961                            self.stack.push(stack::Element::Dissatisfied);
962                        }
963                    } else {
964                        // evaluate each key with as a pk
965                        // note that evaluate_pk will error on non-empty incorrect sigs
966                        // push 1 on satisfied sigs and push 0 on empty sigs
967                        match self
968                            .stack
969                            .evaluate_pk(&mut self.verify_sig, subs[node_state.n_evaluated])
970                        {
971                            Some(Ok(x)) => {
972                                self.push_evaluation_state(
973                                    node_state.node,
974                                    node_state.n_evaluated + 1,
975                                    node_state.n_satisfied + 1,
976                                );
977                                match self.stack.pop() {
978                                    Some(..) => return Some(Ok(x)),
979                                    None => return Some(Err(Error::UnexpectedStackEnd)),
980                                }
981                            }
982                            None => {
983                                self.push_evaluation_state(
984                                    node_state.node,
985                                    node_state.n_evaluated + 1,
986                                    node_state.n_satisfied,
987                                );
988                                match self.stack.pop() {
989                                    Some(..) => {} // not-satisfied, look for next key
990                                    None => return Some(Err(Error::UnexpectedStackEnd)),
991                                }
992                            }
993                            x => return x, //forward errors as is
994                        }
995                    }
996                }
997                Terminal::Multi(ref k, ref subs) if node_state.n_evaluated == 0 => {
998                    let len = self.stack.len();
999                    if len < k + 1 {
1000                        return Some(Err(Error::InsufficientSignaturesMultiSig));
1001                    } else {
1002                        //Non-sat case. If the first sig is empty, others k elements must
1003                        //be empty.
1004                        match self.stack.last() {
1005                            Some(&stack::Element::Dissatisfied) => {
1006                                //Remove the extra zero from multi-sig check
1007                                let sigs = self.stack.split_off(len - (k + 1));
1008                                let nonsat = sigs
1009                                    .iter()
1010                                    .map(|sig| *sig == stack::Element::Dissatisfied)
1011                                    .filter(|empty| *empty)
1012                                    .count();
1013                                if nonsat == *k + 1 {
1014                                    self.stack.push(stack::Element::Dissatisfied);
1015                                } else {
1016                                    return Some(Err(Error::MissingExtraZeroMultiSig));
1017                                }
1018                            }
1019                            None => return Some(Err(Error::UnexpectedStackEnd)),
1020                            _ => {
1021                                match self
1022                                    .stack
1023                                    .evaluate_multi(&mut self.verify_sig, &subs[subs.len() - 1])
1024                                {
1025                                    Some(Ok(x)) => {
1026                                        self.push_evaluation_state(
1027                                            node_state.node,
1028                                            node_state.n_evaluated + 1,
1029                                            node_state.n_satisfied + 1,
1030                                        );
1031                                        return Some(Ok(x));
1032                                    }
1033                                    None => self.push_evaluation_state(
1034                                        node_state.node,
1035                                        node_state.n_evaluated + 1,
1036                                        node_state.n_satisfied,
1037                                    ),
1038                                    x => return x, //forward errors as is
1039                                }
1040                            }
1041                        }
1042                    }
1043                }
1044                Terminal::Multi(k, ref subs) => {
1045                    if node_state.n_satisfied == k {
1046                        //multi-sig bug: Pop extra 0
1047                        if let Some(stack::Element::Dissatisfied) = self.stack.pop() {
1048                            self.stack.push(stack::Element::Satisfied);
1049                        } else {
1050                            return Some(Err(Error::MissingExtraZeroMultiSig));
1051                        }
1052                    } else if node_state.n_evaluated == subs.len() {
1053                        return Some(Err(Error::MultiSigEvaluationError));
1054                    } else {
1055                        match self.stack.evaluate_multi(
1056                            &mut self.verify_sig,
1057                            &subs[subs.len() - node_state.n_evaluated - 1],
1058                        ) {
1059                            Some(Ok(x)) => {
1060                                self.push_evaluation_state(
1061                                    node_state.node,
1062                                    node_state.n_evaluated + 1,
1063                                    node_state.n_satisfied + 1,
1064                                );
1065                                return Some(Ok(x));
1066                            }
1067                            None => self.push_evaluation_state(
1068                                node_state.node,
1069                                node_state.n_evaluated + 1,
1070                                node_state.n_satisfied,
1071                            ),
1072                            x => return x, //forward errors as is
1073                        }
1074                    }
1075                }
1076                //All other match patterns should not be reached in any valid
1077                //type checked Miniscript
1078                _ => return Some(Err(Error::CouldNotEvaluate)),
1079            };
1080        }
1081
1082        //state empty implies that either the execution has terminated or we have a
1083        //Pk based descriptor or a Covenant descriptor
1084        if let Some(pk) = self.cov {
1085            // First verify the top of Miniscript.
1086            // At this point, the stack must contain 13 elements
1087            // pop the satisfied top and verify the covenant code.
1088            if self.stack.pop() != Some(stack::Element::Satisfied) {
1089                return Some(Err(Error::IncorrectCovenantWitness));
1090            }
1091            if self.stack.len() != 12 {
1092                return Some(Err(Error::UnexpectedStackEnd));
1093            }
1094            // safe to unwrap 12 times
1095            for i in 0..12 {
1096                if let Err(e) = self.stack[i].try_push() {
1097                    return Some(Err(e));
1098                }
1099            }
1100            let mut ser_sig = Vec::new();
1101            // 1.29 errors
1102            {
1103                let sighash_bytes = self.stack[1].as_push().expect("Push checked above");
1104                let sighash_u32 = util::slice_to_u32_le(sighash_bytes);
1105                let sighash_ty = EcdsaSighashType::from_u32(sighash_u32);
1106                let sig_vec = self.stack[0].as_push().expect("Size checked above");
1107                ser_sig.extend(sig_vec);
1108                ser_sig.push(sighash_ty as u8);
1109            }
1110
1111            if let Ok(sig) = verify_sersig(&mut self.verify_sig, pk, &ser_sig) {
1112                //Signature check successful, set cov to None to
1113                //terminate the next() function in the subsequent call
1114                self.cov = None;
1115                // Do the checkSigFromStackCheck
1116                let sighash_msg: Vec<u8> = self.stack.0[1..]
1117                    .iter()
1118                    .rev()
1119                    .flat_map(|x| Vec::from(x.as_push().expect("Push checked above")))
1120                    .collect();
1121                let mut eng = Sighash::engine();
1122                eng.input(&sighash_msg);
1123                let sighash_u256 = Sighash::from_engine(eng);
1124                let msg =
1125                    elements::secp256k1_zkp::Message::from_digest_slice(&sighash_u256[..]).unwrap();
1126
1127                // Legacy Cov scripts only operate on Ecdsa key sig pairs
1128                let (ec_pk, ecdsa_sig) = match sig {
1129                    KeySigPair::Ecdsa(pk, sig) => (pk, sig.0),
1130                    KeySigPair::Schnorr(_, _) => {
1131                        unreachable!("Internal error: Legacy cov check in schnorr sigs")
1132                    }
1133                };
1134                // Creating a context is no-longer expensive
1135                let secp = secp256k1_zkp::Secp256k1::verification_only();
1136                if secp.verify_ecdsa(&msg, &ecdsa_sig, &ec_pk.inner).is_err() {
1137                    return Some(Err(Error::PkEvaluationError(PkEvalErrInner::from(*pk))));
1138                }
1139                self.stack.0.clear();
1140                self.stack.push(stack::Element::Satisfied);
1141                return Some(Ok(SatisfiedConstraint::PublicKey { key_sig: sig }));
1142            } else {
1143                return Some(Err(Error::PkEvaluationError(PkEvalErrInner::from(*pk))));
1144            }
1145        }
1146        if let Some(pk) = self.public_key {
1147            if let Some(stack::Element::Push(sig)) = self.stack.pop() {
1148                if let Ok(key_sig) = verify_sersig(&mut self.verify_sig, pk, sig) {
1149                    //Signature check successful, set public_key to None to
1150                    //terminate the next() function in the subsequent call
1151                    self.public_key = None;
1152                    self.stack.push(stack::Element::Satisfied);
1153                    Some(Ok(SatisfiedConstraint::PublicKey { key_sig }))
1154                } else {
1155                    Some(Err(Error::PkEvaluationError(PkEvalErrInner::from(*pk))))
1156                }
1157            } else {
1158                Some(Err(Error::UnexpectedStackEnd))
1159            }
1160        } else {
1161            //All the script has been executed.
1162            //Check that the stack must contain exactly 1 satisfied element
1163            if self.stack.pop() == Some(stack::Element::Satisfied) && self.stack.is_empty() {
1164                None
1165            } else {
1166                Some(Err(Error::ScriptSatisfactionError))
1167            }
1168        }
1169    }
1170}
1171
1172/// Helper function to verify serialized signature
1173fn verify_sersig<'txin>(
1174    verify_sig: &mut Box<dyn FnMut(&KeySigPair) -> bool + 'txin>,
1175    pk: &BitcoinKey,
1176    sigser: &[u8],
1177) -> Result<KeySigPair, Error> {
1178    match pk {
1179        BitcoinKey::Fullkey(pk) => {
1180            let ecdsa_sig = elementssig_from_rawsig(sigser)?;
1181            let key_sig_pair = KeySigPair::Ecdsa(*pk, ecdsa_sig);
1182            if verify_sig(&key_sig_pair) {
1183                Ok(key_sig_pair)
1184            } else {
1185                Err(Error::InvalidEcdsaSignature(*pk))
1186            }
1187        }
1188        BitcoinKey::XOnlyPublicKey(x_only_pk) => {
1189            let schnorr_sig = elements::SchnorrSig::from_slice(sigser)?;
1190            let key_sig_pair = KeySigPair::Schnorr(*x_only_pk, schnorr_sig);
1191            if verify_sig(&key_sig_pair) {
1192                Ok(key_sig_pair)
1193            } else {
1194                Err(Error::InvalidSchnorrSignature(*x_only_pk))
1195            }
1196        }
1197    }
1198}
1199
1200#[cfg(test)]
1201mod tests {
1202
1203    use bitcoin;
1204    use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
1205    use elements::secp256k1_zkp::{self, Secp256k1};
1206
1207    use super::inner::ToNoChecks;
1208    use super::*;
1209    use crate::miniscript::analyzable::ExtParams;
1210    use crate::miniscript::context::NoChecks;
1211    use crate::{ElementsSig, Miniscript, NoExt, ToPublicKey};
1212
1213    fn setup_keys_sigs(
1214        n: usize,
1215    ) -> (
1216        Vec<bitcoin::PublicKey>,
1217        Vec<Vec<u8>>,
1218        Vec<ElementsSig>,
1219        secp256k1_zkp::Message,
1220        Secp256k1<secp256k1_zkp::All>,
1221        Vec<bitcoin::key::XOnlyPublicKey>,
1222        Vec<elements::SchnorrSig>,
1223        Vec<Vec<u8>>,
1224    ) {
1225        let secp = secp256k1_zkp::Secp256k1::new();
1226        let msg =
1227            secp256k1_zkp::Message::from_digest_slice(&b"Yoda: btc, I trust. HODL I must!"[..])
1228                .expect("32 bytes");
1229        let mut pks = vec![];
1230        let mut ecdsa_sigs = vec![];
1231        let mut der_sigs = vec![];
1232        let mut x_only_pks = vec![];
1233        let mut schnorr_sigs = vec![];
1234        let mut ser_schnorr_sigs = vec![];
1235
1236        let mut sk = [0; 32];
1237        for i in 1..n + 1 {
1238            sk[0] = i as u8;
1239            sk[1] = (i >> 8) as u8;
1240            sk[2] = (i >> 16) as u8;
1241
1242            let sk = secp256k1_zkp::SecretKey::from_slice(&sk[..]).expect("secret key");
1243            let pk = bitcoin::PublicKey {
1244                inner: secp256k1_zkp::PublicKey::from_secret_key(&secp, &sk),
1245                compressed: true,
1246            };
1247            let sig = secp.sign_ecdsa(&msg, &sk);
1248            ecdsa_sigs.push((sig, elements::EcdsaSighashType::All));
1249            let mut sigser = sig.serialize_der().to_vec();
1250            sigser.push(0x01); // sighash_all
1251            pks.push(pk);
1252            der_sigs.push(sigser);
1253
1254            let keypair = bitcoin::key::Keypair::from_secret_key(&secp, &sk);
1255            let (x_only_pk, _parity) = bitcoin::key::XOnlyPublicKey::from_keypair(&keypair);
1256            x_only_pks.push(x_only_pk);
1257            let schnorr_sig = secp.sign_schnorr_with_aux_rand(&msg, &keypair, &[0u8; 32]);
1258            let schnorr_sig = elements::SchnorrSig {
1259                sig: schnorr_sig,
1260                hash_ty: elements::SchnorrSighashType::Default,
1261            };
1262            ser_schnorr_sigs.push(schnorr_sig.to_vec());
1263            schnorr_sigs.push(schnorr_sig);
1264        }
1265        (
1266            pks,
1267            der_sigs,
1268            ecdsa_sigs,
1269            msg,
1270            secp,
1271            x_only_pks,
1272            schnorr_sigs,
1273            ser_schnorr_sigs,
1274        )
1275    }
1276
1277    #[test]
1278    fn sat_constraints() {
1279        let (pks, der_sigs, ecdsa_sigs, sighash, secp, xpks, schnorr_sigs, ser_schnorr_sigs) =
1280            setup_keys_sigs(10);
1281        let secp_ref = &secp;
1282        let vfyfn = |pksig: &KeySigPair| match pksig {
1283            KeySigPair::Ecdsa(pk, ecdsa_sig) => secp_ref
1284                .verify_ecdsa(&sighash, &ecdsa_sig.0, &pk.inner)
1285                .is_ok(),
1286            KeySigPair::Schnorr(xpk, schnorr_sig) => secp_ref
1287                .verify_schnorr(&schnorr_sig.sig, &sighash, xpk)
1288                .is_ok(),
1289        };
1290
1291        fn from_stack<'txin, 'elem>(
1292            verify_fn: Box<dyn FnMut(&KeySigPair) -> bool + 'elem>,
1293            stack: Stack<'txin>,
1294            ms: &'elem Miniscript<BitcoinKey, NoChecks, NoExt>,
1295        ) -> Iter<'elem, 'txin, NoExt> {
1296            Iter {
1297                verify_sig: verify_fn,
1298                stack,
1299                public_key: None,
1300                state: vec![NodeEvaluationState {
1301                    node: ms,
1302                    n_evaluated: 0,
1303                    n_satisfied: 0,
1304                }],
1305                age: Sequence::from_height(1002),
1306                lock_time: LockTime::from_height(1002).unwrap(),
1307                cov: None,
1308                has_errored: false,
1309                txenv: None,
1310                sig_type: SigType::Ecdsa,
1311            }
1312        }
1313
1314        let pk = no_checks_ms(&format!("c:pk_k({})", pks[0]));
1315        let pkh = no_checks_ms(&format!("c:pk_h({})", pks[1]));
1316        //Time
1317        let after = no_checks_ms(&format!("after({})", 1000));
1318        let older = no_checks_ms(&format!("older({})", 1000));
1319        //Hashes
1320        let preimage = [0xab; 32];
1321        let sha256_hash = sha256::Hash::hash(&preimage);
1322        let sha256 = no_checks_ms(&format!("sha256({})", sha256_hash));
1323        let hash256_hash = hash256::Hash::hash(&preimage);
1324        let hash256 = no_checks_ms(&format!("hash256({})", hash256_hash));
1325        let hash160_hash = hash160::Hash::hash(&preimage);
1326        let hash160 = no_checks_ms(&format!("hash160({})", hash160_hash));
1327        let ripemd160_hash = ripemd160::Hash::hash(&preimage);
1328        let ripemd160 = no_checks_ms(&format!("ripemd160({})", ripemd160_hash));
1329
1330        let stack = Stack::from(vec![stack::Element::Push(&der_sigs[0])]);
1331        let constraints = from_stack(Box::new(vfyfn), stack, &pk);
1332        let pk_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1333
1334        assert_eq!(
1335            pk_satisfied.unwrap(),
1336            vec![SatisfiedConstraint::PublicKey {
1337                key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1338            }]
1339        );
1340
1341        //Check Pk failure with wrong signature
1342        let stack = Stack::from(vec![stack::Element::Dissatisfied]);
1343        let constraints = from_stack(Box::new(vfyfn), stack, &pk);
1344
1345        let pk_err: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1346        assert!(pk_err.is_err());
1347
1348        //Check Pkh
1349        let pk_bytes = pks[1].to_public_key().to_bytes();
1350        let stack = Stack::from(vec![
1351            stack::Element::Push(&der_sigs[1]),
1352            stack::Element::Push(&pk_bytes),
1353        ]);
1354        let constraints = from_stack(Box::new(vfyfn), stack, &pkh);
1355        let pkh_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1356        assert_eq!(
1357            pkh_satisfied.unwrap(),
1358            vec![SatisfiedConstraint::PublicKeyHash {
1359                keyhash: pks[1].to_pubkeyhash(SigType::Ecdsa),
1360                key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1361            }]
1362        );
1363
1364        //Check After
1365        let stack = Stack::from(vec![]);
1366        let constraints = from_stack(Box::new(vfyfn), stack, &after);
1367        let after_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1368        assert_eq!(
1369            after_satisfied.unwrap(),
1370            vec![SatisfiedConstraint::AbsoluteTimelock {
1371                n: LockTime::from_height(1000).unwrap()
1372            }]
1373        );
1374
1375        //Check Older
1376        let stack = Stack::from(vec![]);
1377        let constraints = from_stack(Box::new(vfyfn), stack, &older);
1378        let older_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1379        assert_eq!(
1380            older_satisfied.unwrap(),
1381            vec![SatisfiedConstraint::RelativeTimelock {
1382                n: Sequence::from_height(1000)
1383            }]
1384        );
1385
1386        //Check Sha256
1387        let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1388        let constraints = from_stack(Box::new(vfyfn), stack, &sha256);
1389        let sah256_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1390            constraints.collect();
1391        assert_eq!(
1392            sah256_satisfied.unwrap(),
1393            vec![SatisfiedConstraint::HashLock {
1394                hash: HashLockType::Sha256(sha256_hash),
1395                preimage,
1396            }]
1397        );
1398
1399        //Check Shad256
1400        let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1401        let constraints = from_stack(Box::new(vfyfn), stack, &hash256);
1402        let sha256d_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1403            constraints.collect();
1404        assert_eq!(
1405            sha256d_satisfied.unwrap(),
1406            vec![SatisfiedConstraint::HashLock {
1407                hash: HashLockType::Hash256(hash256_hash),
1408                preimage,
1409            }]
1410        );
1411
1412        //Check hash160
1413        let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1414        let constraints = from_stack(Box::new(vfyfn), stack, &hash160);
1415        let hash160_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1416            constraints.collect();
1417        assert_eq!(
1418            hash160_satisfied.unwrap(),
1419            vec![SatisfiedConstraint::HashLock {
1420                hash: HashLockType::Hash160(hash160_hash),
1421                preimage,
1422            }]
1423        );
1424
1425        //Check ripemd160
1426        let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1427        let constraints = from_stack(Box::new(vfyfn), stack, &ripemd160);
1428        let ripemd160_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1429            constraints.collect();
1430
1431        assert_eq!(
1432            ripemd160_satisfied.unwrap(),
1433            vec![SatisfiedConstraint::HashLock {
1434                hash: HashLockType::Ripemd160(ripemd160_hash),
1435                preimage,
1436            }]
1437        );
1438
1439        //Check AndV
1440        let pk_bytes = pks[1].to_public_key().to_bytes();
1441        let stack = Stack::from(vec![
1442            stack::Element::Push(&der_sigs[1]),
1443            stack::Element::Push(&pk_bytes),
1444            stack::Element::Push(&der_sigs[0]),
1445        ]);
1446        let elem = no_checks_ms(&format!("and_v(vc:pk_k({}),c:pk_h({}))", pks[0], pks[1]));
1447        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1448
1449        let and_v_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1450        assert_eq!(
1451            and_v_satisfied.unwrap(),
1452            vec![
1453                SatisfiedConstraint::PublicKey {
1454                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1455                },
1456                SatisfiedConstraint::PublicKeyHash {
1457                    keyhash: pks[1].to_pubkeyhash(SigType::Ecdsa),
1458                    key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1459                }
1460            ]
1461        );
1462
1463        //Check AndB
1464        let stack = Stack::from(vec![
1465            stack::Element::Push(&preimage),
1466            stack::Element::Push(&der_sigs[0]),
1467        ]);
1468        let elem = no_checks_ms(&format!(
1469            "and_b(c:pk_k({}),sjtv:sha256({}))",
1470            pks[0], sha256_hash
1471        ));
1472        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1473
1474        let and_b_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1475        assert_eq!(
1476            and_b_satisfied.unwrap(),
1477            vec![
1478                SatisfiedConstraint::PublicKey {
1479                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1480                },
1481                SatisfiedConstraint::HashLock {
1482                    hash: HashLockType::Sha256(sha256_hash),
1483                    preimage,
1484                }
1485            ]
1486        );
1487
1488        //Check AndOr
1489        let stack = Stack::from(vec![
1490            stack::Element::Push(&preimage),
1491            stack::Element::Push(&der_sigs[0]),
1492        ]);
1493        let elem = no_checks_ms(&format!(
1494            "andor(c:pk_k({}),jtv:sha256({}),c:pk_h({}))",
1495            pks[0], sha256_hash, pks[1],
1496        ));
1497        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1498
1499        let and_or_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1500            constraints.collect();
1501        assert_eq!(
1502            and_or_satisfied.unwrap(),
1503            vec![
1504                SatisfiedConstraint::PublicKey {
1505                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1506                },
1507                SatisfiedConstraint::HashLock {
1508                    hash: HashLockType::Sha256(sha256_hash),
1509                    preimage,
1510                }
1511            ]
1512        );
1513
1514        //AndOr second satisfaction path
1515        let pk_bytes = pks[1].to_public_key().to_bytes();
1516        let stack = Stack::from(vec![
1517            stack::Element::Push(&der_sigs[1]),
1518            stack::Element::Push(&pk_bytes),
1519            stack::Element::Dissatisfied,
1520        ]);
1521        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1522
1523        let and_or_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1524            constraints.collect();
1525        assert_eq!(
1526            and_or_satisfied.unwrap(),
1527            vec![SatisfiedConstraint::PublicKeyHash {
1528                keyhash: pks[1].to_pubkeyhash(SigType::Ecdsa),
1529                key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1530            }]
1531        );
1532
1533        //Check OrB
1534        let stack = Stack::from(vec![
1535            stack::Element::Push(&preimage),
1536            stack::Element::Dissatisfied,
1537        ]);
1538        let elem = no_checks_ms(&format!(
1539            "or_b(c:pk_k({}),sjtv:sha256({}))",
1540            pks[0], sha256_hash
1541        ));
1542        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1543
1544        let or_b_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1545        assert_eq!(
1546            or_b_satisfied.unwrap(),
1547            vec![SatisfiedConstraint::HashLock {
1548                hash: HashLockType::Sha256(sha256_hash),
1549                preimage,
1550            }]
1551        );
1552
1553        //Check OrD
1554        let stack = Stack::from(vec![stack::Element::Push(&der_sigs[0])]);
1555        let elem = no_checks_ms(&format!(
1556            "or_d(c:pk_k({}),jtv:sha256({}))",
1557            pks[0], sha256_hash
1558        ));
1559        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1560
1561        let or_d_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1562        assert_eq!(
1563            or_d_satisfied.unwrap(),
1564            vec![SatisfiedConstraint::PublicKey {
1565                key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1566            }]
1567        );
1568
1569        //Check OrC
1570        let stack = Stack::from(vec![
1571            stack::Element::Push(&der_sigs[0]),
1572            stack::Element::Dissatisfied,
1573        ]);
1574        let elem = no_checks_ms(&format!(
1575            "t:or_c(jtv:sha256({}),vc:pk_k({}))",
1576            sha256_hash, pks[0]
1577        ));
1578        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1579
1580        let or_c_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1581        assert_eq!(
1582            or_c_satisfied.unwrap(),
1583            vec![SatisfiedConstraint::PublicKey {
1584                key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1585            }]
1586        );
1587
1588        //Check OrI
1589        let stack = Stack::from(vec![
1590            stack::Element::Push(&der_sigs[0]),
1591            stack::Element::Dissatisfied,
1592        ]);
1593        let elem = no_checks_ms(&format!(
1594            "or_i(jtv:sha256({}),c:pk_k({}))",
1595            sha256_hash, pks[0]
1596        ));
1597        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1598
1599        let or_i_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1600        assert_eq!(
1601            or_i_satisfied.unwrap(),
1602            vec![SatisfiedConstraint::PublicKey {
1603                key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1604            }]
1605        );
1606
1607        //Check Thres
1608        let stack = Stack::from(vec![
1609            stack::Element::Push(&der_sigs[0]),
1610            stack::Element::Push(&der_sigs[1]),
1611            stack::Element::Push(&der_sigs[2]),
1612            stack::Element::Dissatisfied,
1613            stack::Element::Dissatisfied,
1614        ]);
1615        let elem = no_checks_ms(&format!(
1616            "thresh(3,c:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}))",
1617            pks[4], pks[3], pks[2], pks[1], pks[0],
1618        ));
1619        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1620
1621        let thresh_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1622            constraints.collect();
1623        assert_eq!(
1624            thresh_satisfied.unwrap(),
1625            vec![
1626                SatisfiedConstraint::PublicKey {
1627                    key_sig: KeySigPair::Ecdsa(pks[2], ecdsa_sigs[2])
1628                },
1629                SatisfiedConstraint::PublicKey {
1630                    key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1631                },
1632                SatisfiedConstraint::PublicKey {
1633                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1634                }
1635            ]
1636        );
1637
1638        // Check multi
1639        let stack = Stack::from(vec![
1640            stack::Element::Dissatisfied,
1641            stack::Element::Push(&der_sigs[2]),
1642            stack::Element::Push(&der_sigs[1]),
1643            stack::Element::Push(&der_sigs[0]),
1644        ]);
1645        let elem = no_checks_ms(&format!(
1646            "multi(3,{},{},{},{},{})",
1647            pks[4], pks[3], pks[2], pks[1], pks[0],
1648        ));
1649        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1650
1651        let multi_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1652        assert_eq!(
1653            multi_satisfied.unwrap(),
1654            vec![
1655                SatisfiedConstraint::PublicKey {
1656                    key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1657                },
1658                SatisfiedConstraint::PublicKey {
1659                    key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1660                },
1661                SatisfiedConstraint::PublicKey {
1662                    key_sig: KeySigPair::Ecdsa(pks[2], ecdsa_sigs[2])
1663                },
1664            ]
1665        );
1666
1667        // Error multi: Invalid order of sigs
1668        let stack = Stack::from(vec![
1669            stack::Element::Dissatisfied,
1670            stack::Element::Push(&der_sigs[0]),
1671            stack::Element::Push(&der_sigs[2]),
1672            stack::Element::Push(&der_sigs[1]),
1673        ]);
1674        let elem = no_checks_ms(&format!(
1675            "multi(3,{},{},{},{},{})",
1676            pks[4], pks[3], pks[2], pks[1], pks[0],
1677        ));
1678        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1679
1680        let multi_error: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1681        assert!(multi_error.is_err());
1682
1683        // multi_a tests
1684        let stack = Stack::from(vec![
1685            stack::Element::Dissatisfied,
1686            stack::Element::Dissatisfied,
1687            stack::Element::Push(&ser_schnorr_sigs[2]),
1688            stack::Element::Push(&ser_schnorr_sigs[1]),
1689            stack::Element::Push(&ser_schnorr_sigs[0]),
1690        ]);
1691
1692        let elem = x_only_no_checks_ms(&format!(
1693            "multi_a(3,{},{},{},{},{})",
1694            xpks[0], xpks[1], xpks[2], xpks[3], xpks[4],
1695        ));
1696        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1697
1698        let multi_a_satisfied: Result<Vec<SatisfiedConstraint<NoExt>>, Error> =
1699            constraints.collect();
1700        assert_eq!(
1701            multi_a_satisfied.unwrap(),
1702            vec![
1703                SatisfiedConstraint::PublicKey {
1704                    key_sig: KeySigPair::Schnorr(xpks[0], schnorr_sigs[0])
1705                },
1706                SatisfiedConstraint::PublicKey {
1707                    key_sig: KeySigPair::Schnorr(xpks[1], schnorr_sigs[1])
1708                },
1709                SatisfiedConstraint::PublicKey {
1710                    key_sig: KeySigPair::Schnorr(xpks[2], schnorr_sigs[2])
1711                },
1712            ]
1713        );
1714
1715        // multi_a tests: wrong order of sigs
1716        let stack = Stack::from(vec![
1717            stack::Element::Dissatisfied,
1718            stack::Element::Push(&ser_schnorr_sigs[2]),
1719            stack::Element::Push(&ser_schnorr_sigs[1]),
1720            stack::Element::Push(&ser_schnorr_sigs[0]),
1721            stack::Element::Dissatisfied,
1722        ]);
1723
1724        let elem = x_only_no_checks_ms(&format!(
1725            "multi_a(3,{},{},{},{},{})",
1726            xpks[0], xpks[1], xpks[2], xpks[3], xpks[4],
1727        ));
1728        let constraints = from_stack(Box::new(vfyfn), stack.clone(), &elem);
1729
1730        let multi_a_error: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1731        assert!(multi_a_error.is_err());
1732
1733        // multi_a wrong thresh: k = 2, but three sigs
1734        let elem = x_only_no_checks_ms(&format!(
1735            "multi_a(2,{},{},{},{},{})",
1736            xpks[0], xpks[1], xpks[2], xpks[3], xpks[4],
1737        ));
1738        let constraints = from_stack(Box::new(vfyfn), stack.clone(), &elem);
1739
1740        let multi_a_error: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1741        assert!(multi_a_error.is_err());
1742
1743        // multi_a correct thresh, but small stack
1744        let elem = x_only_no_checks_ms(&format!(
1745            "multi_a(3,{},{},{},{},{},{})",
1746            xpks[0], xpks[1], xpks[2], xpks[3], xpks[4], xpks[5]
1747        ));
1748        let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1749
1750        let multi_a_error: Result<Vec<SatisfiedConstraint<NoExt>>, Error> = constraints.collect();
1751        assert!(multi_a_error.is_err());
1752    }
1753
1754    // By design there is no support for parse a miniscript with BitcoinKey
1755    // because it does not implement FromStr
1756    fn no_checks_ms(ms: &str) -> Miniscript<BitcoinKey, NoChecks> {
1757        // Parsing should allow raw hashes in the interpreter
1758        let elem: Miniscript<bitcoin::PublicKey, NoChecks> =
1759            Miniscript::from_str_ext(ms, &ExtParams::allow_all()).unwrap();
1760        elem.to_no_checks_ms()
1761    }
1762
1763    fn x_only_no_checks_ms(ms: &str) -> Miniscript<BitcoinKey, NoChecks> {
1764        let elem: Miniscript<bitcoin::key::XOnlyPublicKey, NoChecks> =
1765            Miniscript::from_str_ext(ms, &ExtParams::allow_all()).unwrap();
1766        elem.to_no_checks_ms()
1767    }
1768}