1use 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
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 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 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(..) => {} None => return Some(Err(Error::UnexpectedStackEnd)),
991 }
992 }
993 x => return x, }
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 match self.stack.last() {
1005 Some(&stack::Element::Dissatisfied) => {
1006 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, }
1040 }
1041 }
1042 }
1043 }
1044 Terminal::Multi(k, ref subs) => {
1045 if node_state.n_satisfied == k {
1046 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, }
1074 }
1075 }
1076 _ => return Some(Err(Error::CouldNotEvaluate)),
1079 };
1080 }
1081
1082 if let Some(pk) = self.cov {
1085 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 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 {
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 self.cov = None;
1115 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 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 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 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 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
1172fn 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); 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 let after = no_checks_ms(&format!("after({})", 1000));
1318 let older = no_checks_ms(&format!("older({})", 1000));
1319 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 fn no_checks_ms(ms: &str) -> Miniscript<BitcoinKey, NoChecks> {
1757 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}