1use 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
33pub struct Interpreter<'txin, Ext: Extension> {
35 inner: inner::Inner<Ext>,
36 stack: Stack<'txin>,
37 script_code: Option<elements::Script>,
40 age: Sequence,
41 lock_time: LockTime,
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum KeySigPair {
50 Ecdsa(bitcoin::PublicKey, ElementsSig),
52 Schnorr(bitcoin::key::XOnlyPublicKey, elements::SchnorrSig),
54}
55
56impl KeySigPair {
57 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 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#[derive(Hash, Eq, Ord, PartialEq, PartialOrd, Clone, Copy, Debug)]
90pub enum BitcoinKey {
91 Fullkey(bitcoin::PublicKey),
93 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
106impl 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 pub fn from_txdata(
148 spk: &elements::Script,
149 script_sig: &'txin elements::Script,
150 witness: &'txin [Vec<u8>],
151 age: Sequence, lock_time: LockTime, ) -> 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 pub fn from_txdata_ext(
169 spk: &elements::Script,
170 script_sig: &'txin elements::Script,
171 witness: &'txin [Vec<u8>],
172 age: Sequence, lock_time: LockTime, ) -> 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 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 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 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 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 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) }
315 }
316 }
317
318 pub fn iter<'iter, C: secp256k1_zkp::Verification>(
336 &'iter self,
337 secp: &'iter secp256k1_zkp::Secp256k1<C>,
338 txenv: &'txin TxEnv, genesis_hash: elements::BlockHash, ) -> 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 pub fn iter_assume_sigs<'iter>(&'iter self) -> Iter<'txin, 'iter, Ext> {
358 self.iter_custom(Box::new(|_| true), None)
359 }
360
361 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 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 format!("elcovwsh({},{})", pk, ms)
394 }
395 inner::Inner::Script(ref ms, inner::ScriptType::Tr) => {
396 format!("eltr(hidden_paths_not_yet_supported,{})", ms)
399 }
400 }
401 }
402
403 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, inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => false, 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, inner::Inner::CovScript(..) => false,
416 inner::Inner::Script(_, inner::ScriptType::Tr) => false,
417 }
418 }
419
420 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, 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, inner::Inner::Script(_, inner::ScriptType::Tr) => false,
433 inner::Inner::CovScript(_, _) => true,
434 }
435 }
436
437 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 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 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 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#[derive(Copy, Clone, Debug, Eq, PartialEq)]
503pub enum HashLockType {
504 Sha256(sha256::Hash),
506 Hash256(hash256::Hash),
508 Hash160(hash160::Hash),
510 Ripemd160(ripemd160::Hash),
512}
513
514#[derive(Clone, Debug, Eq, PartialEq)]
518pub enum SatisfiedConstraint<Ext: Extension> {
519 PublicKey {
521 key_sig: KeySigPair,
523 },
524 PublicKeyHash {
526 keyhash: hash160::Hash,
528 key_sig: KeySigPair,
530 },
531 HashLock {
533 hash: HashLockType,
535 preimage: [u8; 32],
537 },
538 RelativeTimelock {
540 n: Sequence,
542 },
543 AbsoluteTimelock {
545 n: LockTime,
547 },
548
549 VerEq {
552 n: u32,
554 },
555
556 OutputsPref {
559 pref: Vec<u8>,
561 },
562
563 Ext {
565 ext: Box<Ext>,
567 },
568}
569
570struct NodeEvaluationState<'intp, Ext>
577where
578 Ext: Extension,
579{
580 node: &'intp Miniscript<BitcoinKey, NoChecks, Ext>,
582 n_evaluated: usize,
584 n_satisfied: usize,
586}
587
588pub 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
615impl<'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 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 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 fn iter_next(&mut self) -> Option<Result<SatisfiedConstraint<Ext>, Error>> {
658 while let Some(node_state) = self.state.pop() {
659 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 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(..) => {} None => return Some(Err(Error::UnexpectedStackEnd)),
983 }
984 }
985 x => return x, }
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 match self.stack.last() {
997 Some(&stack::Element::Dissatisfied) => {
998 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, }
1032 }
1033 }
1034 }
1035 }
1036 Terminal::Multi(k, ref subs) => {
1037 if node_state.n_satisfied == k {
1038 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, }
1066 }
1067 }
1068 _ => return Some(Err(Error::CouldNotEvaluate)),
1071 };
1072 }
1073
1074 if let Some(pk) = self.cov {
1077 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 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 {
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 self.cov = None;
1107 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 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 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 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 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
1165fn 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); 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 let after = no_checks_ms(&format!("after({})", 1000));
1311 let older = no_checks_ms(&format!("older({})", 1000));
1312 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 fn no_checks_ms(ms: &str) -> Miniscript<BitcoinKey, NoChecks> {
1750 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}