1use core::fmt;
23use core::str::FromStr;
24
25use bitcoin::blockdata::witness::Witness;
26use bitcoin::hashes::{hash160, ripemd160, sha256};
27use bitcoin::util::{sighash, taproot};
28use bitcoin::{self, secp256k1, LockTime, Sequence, TxOut};
29
30use crate::miniscript::context::{NoChecks, SigType};
31use crate::miniscript::ScriptContext;
32use crate::prelude::*;
33use crate::{hash256, Descriptor, Miniscript, Terminal, ToPublicKey};
34
35mod error;
36mod inner;
37mod stack;
38
39pub use self::error::Error;
40use self::error::PkEvalErrInner;
41use self::stack::Stack;
42use crate::MiniscriptKey;
43
44pub struct Interpreter<'txin> {
46 inner: inner::Inner,
47 stack: Stack<'txin>,
48 script_code: Option<bitcoin::Script>,
51 age: Sequence,
52 lock_time: LockTime,
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum KeySigPair {
61 Ecdsa(bitcoin::PublicKey, bitcoin::EcdsaSig),
63 Schnorr(bitcoin::XOnlyPublicKey, bitcoin::SchnorrSig),
65}
66
67impl KeySigPair {
68 pub fn as_ecdsa(&self) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> {
70 match self {
71 KeySigPair::Ecdsa(pk, sig) => Some((*pk, *sig)),
72 KeySigPair::Schnorr(_, _) => None,
73 }
74 }
75
76 pub fn as_schnorr(&self) -> Option<(bitcoin::XOnlyPublicKey, bitcoin::SchnorrSig)> {
78 match self {
79 KeySigPair::Ecdsa(_, _) => None,
80 KeySigPair::Schnorr(pk, sig) => Some((*pk, *sig)),
81 }
82 }
83}
84
85#[derive(Hash, Eq, Ord, PartialEq, PartialOrd, Clone, Copy, Debug)]
98enum BitcoinKey {
99 Fullkey(bitcoin::PublicKey),
101 XOnlyPublicKey(bitcoin::XOnlyPublicKey),
103}
104
105impl BitcoinKey {
106 fn to_pubkeyhash(&self, sig_type: SigType) -> hash160::Hash {
107 match self {
108 BitcoinKey::Fullkey(pk) => pk.to_pubkeyhash(sig_type),
109 BitcoinKey::XOnlyPublicKey(pk) => pk.to_pubkeyhash(sig_type),
110 }
111 }
112}
113
114impl fmt::Display for BitcoinKey {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 match self {
118 BitcoinKey::Fullkey(pk) => pk.to_public_key().fmt(f),
119 BitcoinKey::XOnlyPublicKey(pk) => pk.to_public_key().fmt(f),
120 }
121 }
122}
123
124impl From<bitcoin::PublicKey> for BitcoinKey {
125 fn from(pk: bitcoin::PublicKey) -> Self {
126 BitcoinKey::Fullkey(pk)
127 }
128}
129
130impl From<bitcoin::XOnlyPublicKey> for BitcoinKey {
131 fn from(xpk: bitcoin::XOnlyPublicKey) -> Self {
132 BitcoinKey::XOnlyPublicKey(xpk)
133 }
134}
135
136impl MiniscriptKey for BitcoinKey {
137 type Sha256 = sha256::Hash;
138 type Hash256 = hash256::Hash;
139 type Ripemd160 = ripemd160::Hash;
140 type Hash160 = hash160::Hash;
141}
142
143impl<'txin> Interpreter<'txin> {
144 pub fn from_txdata(
151 spk: &bitcoin::Script,
152 script_sig: &'txin bitcoin::Script,
153 witness: &'txin Witness,
154 age: Sequence, lock_time: LockTime, ) -> Result<Self, Error> {
157 let (inner, stack, script_code) = inner::from_txdata(spk, script_sig, witness)?;
158 Ok(Interpreter {
159 inner,
160 stack,
161 script_code,
162 age,
163 lock_time,
164 })
165 }
166
167 pub fn iter_custom<'iter>(
171 &'iter self,
172 verify_sig: Box<dyn FnMut(&KeySigPair) -> bool + 'iter>,
173 ) -> Iter<'txin, 'iter> {
174 Iter {
175 verify_sig,
176 public_key: if let inner::Inner::PublicKey(ref pk, _) = self.inner {
177 Some(pk)
178 } else {
179 None
180 },
181 state: if let inner::Inner::Script(ref script, _) = self.inner {
182 vec![NodeEvaluationState {
183 node: script,
184 n_evaluated: 0,
185 n_satisfied: 0,
186 }]
187 } else {
188 vec![]
189 },
190 stack: self.stack.clone(),
193 age: self.age,
194 lock_time: self.lock_time,
195 has_errored: false,
196 sig_type: self.sig_type(),
197 }
198 }
199
200 pub fn verify_sig<C: secp256k1::Verification, T: Borrow<TxOut>>(
210 &self,
211 secp: &secp256k1::Secp256k1<C>,
212 tx: &bitcoin::Transaction,
213 input_idx: usize,
214 prevouts: &sighash::Prevouts<T>,
215 sig: &KeySigPair,
216 ) -> bool {
217 fn get_prevout<'u, T: Borrow<TxOut>>(
218 prevouts: &'u sighash::Prevouts<'u, T>,
219 input_index: usize,
220 ) -> Option<&'u T> {
221 match prevouts {
222 sighash::Prevouts::One(index, prevout) => {
223 if input_index == *index {
224 Some(prevout)
225 } else {
226 None
227 }
228 }
229 sighash::Prevouts::All(prevouts) => prevouts.get(input_index),
230 }
231 }
232 let mut cache = bitcoin::util::sighash::SighashCache::new(tx);
233 match sig {
234 KeySigPair::Ecdsa(key, ecdsa_sig) => {
235 let script_pubkey = self.script_code.as_ref().expect("Legacy have script code");
236 let sighash = if self.is_legacy() {
237 let sighash_u32 = ecdsa_sig.hash_ty.to_u32();
238 cache.legacy_signature_hash(input_idx, script_pubkey, sighash_u32)
239 } else if self.is_segwit_v0() {
240 let amt = match get_prevout(prevouts, input_idx) {
241 Some(txout) => txout.borrow().value,
242 None => return false,
243 };
244 cache.segwit_signature_hash(input_idx, script_pubkey, amt, ecdsa_sig.hash_ty)
245 } else {
246 return false;
248 };
249 let msg =
250 sighash.map(|hash| secp256k1::Message::from_slice(&hash).expect("32 byte"));
251 let success =
252 msg.map(|msg| secp.verify_ecdsa(&msg, &ecdsa_sig.sig, &key.inner).is_ok());
253 success.unwrap_or(false) }
255 KeySigPair::Schnorr(xpk, schnorr_sig) => {
256 let sighash_msg = if self.is_taproot_v1_key_spend() {
257 cache.taproot_key_spend_signature_hash(input_idx, prevouts, schnorr_sig.hash_ty)
258 } else if self.is_taproot_v1_script_spend() {
259 let tap_script = self.script_code.as_ref().expect(
260 "Internal Hack: Saving leaf script instead\
261 of script code for script spend",
262 );
263 let leaf_hash = taproot::TapLeafHash::from_script(
264 tap_script,
265 taproot::LeafVersion::TapScript,
266 );
267 cache.taproot_script_spend_signature_hash(
268 input_idx,
269 prevouts,
270 leaf_hash,
271 schnorr_sig.hash_ty,
272 )
273 } else {
274 return false;
276 };
277 let msg =
278 sighash_msg.map(|hash| secp256k1::Message::from_slice(&hash).expect("32 byte"));
279 let success =
280 msg.map(|msg| secp.verify_schnorr(&schnorr_sig.sig, &msg, xpk).is_ok());
281 success.unwrap_or(false) }
283 }
284 }
285
286 pub fn iter<'iter, C: secp256k1::Verification, T: Borrow<TxOut>>(
304 &'iter self,
305 secp: &'iter secp256k1::Secp256k1<C>,
306 tx: &'txin bitcoin::Transaction,
307 input_idx: usize,
308 prevouts: &'iter sighash::Prevouts<T>, ) -> Iter<'txin, 'iter> {
310 self.iter_custom(Box::new(move |sig| {
311 self.verify_sig(secp, tx, input_idx, prevouts, sig)
312 }))
313 }
314
315 pub fn iter_assume_sigs<'iter>(&'iter self) -> Iter<'txin, 'iter> {
317 self.iter_custom(Box::new(|_| true))
318 }
319
320 pub fn inferred_descriptor_string(&self) -> String {
332 match self.inner {
333 inner::Inner::PublicKey(ref pk, inner::PubkeyType::Pk) => format!("pk({})", pk),
334 inner::Inner::PublicKey(ref pk, inner::PubkeyType::Pkh) => format!("pkh({})", pk),
335 inner::Inner::PublicKey(ref pk, inner::PubkeyType::Wpkh) => format!("wpkh({})", pk),
336 inner::Inner::PublicKey(ref pk, inner::PubkeyType::ShWpkh) => {
337 format!("sh(wpkh({}))", pk)
338 }
339 inner::Inner::PublicKey(ref pk, inner::PubkeyType::Tr) => {
340 format!("rawtr_not_supported_yet({})", pk)
345 }
346 inner::Inner::Script(ref ms, inner::ScriptType::Bare) => format!("{}", ms),
347 inner::Inner::Script(ref ms, inner::ScriptType::Sh) => format!("sh({})", ms),
348 inner::Inner::Script(ref ms, inner::ScriptType::Wsh) => format!("wsh({})", ms),
349 inner::Inner::Script(ref ms, inner::ScriptType::ShWsh) => format!("sh(wsh({}))", ms),
350 inner::Inner::Script(ref ms, inner::ScriptType::Tr) => {
351 format!("tr(hidden_paths_not_yet_supported,{})", ms)
354 }
355 }
356 }
357
358 pub fn is_legacy(&self) -> bool {
360 match self.inner {
361 inner::Inner::PublicKey(_, inner::PubkeyType::Pk) => true,
362 inner::Inner::PublicKey(_, inner::PubkeyType::Pkh) => true,
363 inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh) => false,
364 inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh) => false, inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => false, inner::Inner::Script(_, inner::ScriptType::Bare) => false,
367 inner::Inner::Script(_, inner::ScriptType::Sh) => true,
368 inner::Inner::Script(_, inner::ScriptType::Wsh) => false,
369 inner::Inner::Script(_, inner::ScriptType::ShWsh) => false, inner::Inner::Script(_, inner::ScriptType::Tr) => false,
371 }
372 }
373
374 pub fn is_segwit_v0(&self) -> bool {
376 match self.inner {
377 inner::Inner::PublicKey(_, inner::PubkeyType::Pk) => false,
378 inner::Inner::PublicKey(_, inner::PubkeyType::Pkh) => false,
379 inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh) => true,
380 inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh) => true, inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => false,
382 inner::Inner::Script(_, inner::ScriptType::Bare) => false,
383 inner::Inner::Script(_, inner::ScriptType::Sh) => false,
384 inner::Inner::Script(_, inner::ScriptType::Wsh) => true,
385 inner::Inner::Script(_, inner::ScriptType::ShWsh) => true, inner::Inner::Script(_, inner::ScriptType::Tr) => false,
387 }
388 }
389
390 pub fn is_taproot_v1_key_spend(&self) -> bool {
392 match self.inner {
393 inner::Inner::PublicKey(_, inner::PubkeyType::Pk) => false,
394 inner::Inner::PublicKey(_, inner::PubkeyType::Pkh) => false,
395 inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh) => false,
396 inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh) => false,
397 inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => true,
398 inner::Inner::Script(_, inner::ScriptType::Bare) => false,
399 inner::Inner::Script(_, inner::ScriptType::Sh) => false,
400 inner::Inner::Script(_, inner::ScriptType::Wsh) => false,
401 inner::Inner::Script(_, inner::ScriptType::ShWsh) => false,
402 inner::Inner::Script(_, inner::ScriptType::Tr) => false,
403 }
404 }
405
406 pub fn is_taproot_v1_script_spend(&self) -> bool {
408 match self.inner {
409 inner::Inner::PublicKey(_, inner::PubkeyType::Pk) => false,
410 inner::Inner::PublicKey(_, inner::PubkeyType::Pkh) => false,
411 inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh) => false,
412 inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh) => false,
413 inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => false,
414 inner::Inner::Script(_, inner::ScriptType::Bare) => false,
415 inner::Inner::Script(_, inner::ScriptType::Sh) => false,
416 inner::Inner::Script(_, inner::ScriptType::Wsh) => false,
417 inner::Inner::Script(_, inner::ScriptType::ShWsh) => false,
418 inner::Inner::Script(_, inner::ScriptType::Tr) => true,
419 }
420 }
421
422 pub fn sig_type(&self) -> SigType {
424 match self.inner {
425 inner::Inner::PublicKey(_, inner::PubkeyType::Tr) => SigType::Schnorr,
426 inner::Inner::Script(_, inner::ScriptType::Tr) => SigType::Schnorr,
427 inner::Inner::PublicKey(_, inner::PubkeyType::Pk)
428 | inner::Inner::PublicKey(_, inner::PubkeyType::Pkh)
429 | inner::Inner::PublicKey(_, inner::PubkeyType::Wpkh)
430 | inner::Inner::PublicKey(_, inner::PubkeyType::ShWpkh)
431 | inner::Inner::Script(_, inner::ScriptType::Bare)
432 | inner::Inner::Script(_, inner::ScriptType::Sh)
433 | inner::Inner::Script(_, inner::ScriptType::Wsh)
434 | inner::Inner::Script(_, inner::ScriptType::ShWsh) => SigType::Ecdsa,
435 }
436 }
437
438 pub fn inferred_descriptor(&self) -> Result<Descriptor<bitcoin::PublicKey>, crate::Error> {
445 Descriptor::from_str(&self.inferred_descriptor_string())
446 }
447}
448
449#[derive(Copy, Clone, Debug, Eq, PartialEq)]
451pub enum HashLockType {
452 Sha256(sha256::Hash),
454 Hash256(hash256::Hash),
456 Hash160(hash160::Hash),
458 Ripemd160(ripemd160::Hash),
460}
461
462#[derive(Copy, Clone, Debug, Eq, PartialEq)]
466pub enum SatisfiedConstraint {
467 PublicKey {
469 key_sig: KeySigPair,
471 },
472 PublicKeyHash {
474 keyhash: hash160::Hash,
476 key_sig: KeySigPair,
478 },
479 HashLock {
481 hash: HashLockType,
483 preimage: [u8; 32],
485 },
486 RelativeTimelock {
488 n: Sequence,
490 },
491 AbsoluteTimelock {
493 n: LockTime,
495 },
496}
497
498struct NodeEvaluationState<'intp> {
505 node: &'intp Miniscript<BitcoinKey, NoChecks>,
507 n_evaluated: usize,
509 n_satisfied: usize,
511}
512
513pub struct Iter<'intp, 'txin: 'intp> {
525 verify_sig: Box<dyn FnMut(&KeySigPair) -> bool + 'intp>,
526 public_key: Option<&'intp BitcoinKey>,
527 state: Vec<NodeEvaluationState<'intp>>,
528 stack: Stack<'txin>,
529 age: Sequence,
530 lock_time: LockTime,
531 has_errored: bool,
532 sig_type: SigType,
533}
534
535impl<'intp, 'txin: 'intp> Iterator for Iter<'intp, 'txin>
537where
538 NoChecks: ScriptContext,
539{
540 type Item = Result<SatisfiedConstraint, Error>;
541
542 fn next(&mut self) -> Option<Self::Item> {
543 if self.has_errored {
544 None
546 } else {
547 let res = self.iter_next();
548 if let Some(Err(_)) = res {
549 self.has_errored = true;
550 }
551 res
552 }
553 }
554}
555
556impl<'intp, 'txin: 'intp> Iter<'intp, 'txin>
557where
558 NoChecks: ScriptContext,
559{
560 fn push_evaluation_state(
562 &mut self,
563 node: &'intp Miniscript<BitcoinKey, NoChecks>,
564 n_evaluated: usize,
565 n_satisfied: usize,
566 ) {
567 self.state.push(NodeEvaluationState {
568 node,
569 n_evaluated,
570 n_satisfied,
571 })
572 }
573
574 fn iter_next(&mut self) -> Option<Result<SatisfiedConstraint, Error>> {
576 while let Some(node_state) = self.state.pop() {
577 match node_state.node.node {
579 Terminal::True => {
580 debug_assert_eq!(node_state.n_evaluated, 0);
581 debug_assert_eq!(node_state.n_satisfied, 0);
582 self.stack.push(stack::Element::Satisfied);
583 }
584 Terminal::False => {
585 debug_assert_eq!(node_state.n_evaluated, 0);
586 debug_assert_eq!(node_state.n_satisfied, 0);
587 self.stack.push(stack::Element::Dissatisfied);
588 }
589 Terminal::PkK(ref pk) => {
590 debug_assert_eq!(node_state.n_evaluated, 0);
591 debug_assert_eq!(node_state.n_satisfied, 0);
592 let res = self.stack.evaluate_pk(&mut self.verify_sig, *pk);
593 if res.is_some() {
594 return res;
595 }
596 }
597 Terminal::PkH(ref pk) => {
598 debug_assert_eq!(node_state.n_evaluated, 0);
599 debug_assert_eq!(node_state.n_satisfied, 0);
600 let res = self.stack.evaluate_pkh(
601 &mut self.verify_sig,
602 pk.to_pubkeyhash(self.sig_type),
603 self.sig_type,
604 );
605 if res.is_some() {
606 return res;
607 }
608 }
609 Terminal::RawPkH(ref pkh) => {
610 debug_assert_eq!(node_state.n_evaluated, 0);
611 debug_assert_eq!(node_state.n_satisfied, 0);
612 let res = self
613 .stack
614 .evaluate_pkh(&mut self.verify_sig, *pkh, self.sig_type);
615 if res.is_some() {
616 return res;
617 }
618 }
619 Terminal::After(ref n) => {
620 debug_assert_eq!(node_state.n_evaluated, 0);
621 debug_assert_eq!(node_state.n_satisfied, 0);
622 let res = self.stack.evaluate_after(&n.into(), self.lock_time);
623 if res.is_some() {
624 return res;
625 }
626 }
627 Terminal::Older(ref n) => {
628 debug_assert_eq!(node_state.n_evaluated, 0);
629 debug_assert_eq!(node_state.n_satisfied, 0);
630 let res = self.stack.evaluate_older(n, self.age);
631 if res.is_some() {
632 return res;
633 }
634 }
635 Terminal::Sha256(ref hash) => {
636 debug_assert_eq!(node_state.n_evaluated, 0);
637 debug_assert_eq!(node_state.n_satisfied, 0);
638 let res = self.stack.evaluate_sha256(hash);
639 if res.is_some() {
640 return res;
641 }
642 }
643 Terminal::Hash256(ref hash) => {
644 debug_assert_eq!(node_state.n_evaluated, 0);
645 debug_assert_eq!(node_state.n_satisfied, 0);
646 let res = self.stack.evaluate_hash256(hash);
647 if res.is_some() {
648 return res;
649 }
650 }
651 Terminal::Hash160(ref hash) => {
652 debug_assert_eq!(node_state.n_evaluated, 0);
653 debug_assert_eq!(node_state.n_satisfied, 0);
654 let res = self.stack.evaluate_hash160(hash);
655 if res.is_some() {
656 return res;
657 }
658 }
659 Terminal::Ripemd160(ref hash) => {
660 debug_assert_eq!(node_state.n_evaluated, 0);
661 debug_assert_eq!(node_state.n_satisfied, 0);
662 let res = self.stack.evaluate_ripemd160(hash);
663 if res.is_some() {
664 return res;
665 }
666 }
667 Terminal::Alt(ref sub) | Terminal::Swap(ref sub) | Terminal::Check(ref sub) => {
668 debug_assert_eq!(node_state.n_evaluated, 0);
669 debug_assert_eq!(node_state.n_satisfied, 0);
670 self.push_evaluation_state(sub, 0, 0);
671 }
672 Terminal::DupIf(ref sub) if node_state.n_evaluated == 0 => match self.stack.pop() {
673 Some(stack::Element::Dissatisfied) => {
674 self.stack.push(stack::Element::Dissatisfied);
675 }
676 Some(stack::Element::Satisfied) => {
677 self.push_evaluation_state(node_state.node, 1, 1);
678 self.push_evaluation_state(sub, 0, 0);
679 }
680 Some(stack::Element::Push(_v)) => {
681 return Some(Err(Error::UnexpectedStackElementPush))
682 }
683 None => return Some(Err(Error::UnexpectedStackEnd)),
684 },
685 Terminal::DupIf(ref _sub) if node_state.n_evaluated == 1 => {
686 self.stack.push(stack::Element::Satisfied);
687 }
688 Terminal::ZeroNotEqual(ref sub) | Terminal::Verify(ref sub)
689 if node_state.n_evaluated == 0 =>
690 {
691 self.push_evaluation_state(node_state.node, 1, 0);
692 self.push_evaluation_state(sub, 0, 0);
693 }
694 Terminal::Verify(ref _sub) if node_state.n_evaluated == 1 => {
695 match self.stack.pop() {
696 Some(stack::Element::Satisfied) => (),
697 Some(_) => return Some(Err(Error::VerifyFailed)),
698 None => return Some(Err(Error::UnexpectedStackEnd)),
699 }
700 }
701 Terminal::ZeroNotEqual(ref _sub) if node_state.n_evaluated == 1 => {
702 match self.stack.pop() {
703 Some(stack::Element::Dissatisfied) => {
704 self.stack.push(stack::Element::Dissatisfied)
705 }
706 Some(_) => self.stack.push(stack::Element::Satisfied),
707 None => return Some(Err(Error::UnexpectedStackEnd)),
708 }
709 }
710 Terminal::NonZero(ref sub) => {
711 debug_assert_eq!(node_state.n_evaluated, 0);
712 debug_assert_eq!(node_state.n_satisfied, 0);
713 match self.stack.last() {
714 Some(&stack::Element::Dissatisfied) => (),
715 Some(_) => self.push_evaluation_state(sub, 0, 0),
716 None => return Some(Err(Error::UnexpectedStackEnd)),
717 }
718 }
719 Terminal::AndV(ref left, ref right) => {
720 debug_assert_eq!(node_state.n_evaluated, 0);
721 debug_assert_eq!(node_state.n_satisfied, 0);
722 self.push_evaluation_state(right, 0, 0);
723 self.push_evaluation_state(left, 0, 0);
724 }
725 Terminal::OrB(ref left, ref _right) | Terminal::AndB(ref left, ref _right)
726 if node_state.n_evaluated == 0 =>
727 {
728 self.push_evaluation_state(node_state.node, 1, 0);
729 self.push_evaluation_state(left, 0, 0);
730 }
731 Terminal::OrB(ref _left, ref right) | Terminal::AndB(ref _left, ref right)
732 if node_state.n_evaluated == 1 =>
733 {
734 match self.stack.pop() {
735 Some(stack::Element::Dissatisfied) => {
736 self.push_evaluation_state(node_state.node, 2, 0);
737 self.push_evaluation_state(right, 0, 0);
738 }
739 Some(stack::Element::Satisfied) => {
740 self.push_evaluation_state(node_state.node, 2, 1);
741 self.push_evaluation_state(right, 0, 0);
742 }
743 Some(stack::Element::Push(_v)) => {
744 return Some(Err(Error::UnexpectedStackElementPush))
745 }
746 None => return Some(Err(Error::UnexpectedStackEnd)),
747 }
748 }
749 Terminal::AndB(ref _left, ref _right) if node_state.n_evaluated == 2 => {
750 match self.stack.pop() {
751 Some(stack::Element::Satisfied) if node_state.n_satisfied == 1 => {
752 self.stack.push(stack::Element::Satisfied)
753 }
754 Some(_) => self.stack.push(stack::Element::Dissatisfied),
755 None => return Some(Err(Error::UnexpectedStackEnd)),
756 }
757 }
758 Terminal::AndOr(ref left, ref _right, _)
759 | Terminal::OrC(ref left, ref _right)
760 | Terminal::OrD(ref left, ref _right)
761 if node_state.n_evaluated == 0 =>
762 {
763 self.push_evaluation_state(node_state.node, 1, 0);
764 self.push_evaluation_state(left, 0, 0);
765 }
766 Terminal::OrB(ref _left, ref _right) if node_state.n_evaluated == 2 => {
767 match self.stack.pop() {
768 Some(stack::Element::Dissatisfied) if node_state.n_satisfied == 0 => {
769 self.stack.push(stack::Element::Dissatisfied)
770 }
771 Some(_) => {
772 self.stack.push(stack::Element::Satisfied);
773 }
774 None => return Some(Err(Error::UnexpectedStackEnd)),
775 }
776 }
777 Terminal::OrC(ref _left, ref right) if node_state.n_evaluated == 1 => {
778 match self.stack.pop() {
779 Some(stack::Element::Satisfied) => (),
780 Some(stack::Element::Dissatisfied) => {
781 self.push_evaluation_state(right, 0, 0)
782 }
783 Some(stack::Element::Push(_v)) => {
784 return Some(Err(Error::UnexpectedStackElementPush))
785 }
786 None => return Some(Err(Error::UnexpectedStackEnd)),
787 }
788 }
789 Terminal::OrD(ref _left, ref right) if node_state.n_evaluated == 1 => {
790 match self.stack.pop() {
791 Some(stack::Element::Satisfied) => {
792 self.stack.push(stack::Element::Satisfied)
793 }
794 Some(stack::Element::Dissatisfied) => {
795 self.push_evaluation_state(right, 0, 0)
796 }
797 Some(stack::Element::Push(_v)) => {
798 return Some(Err(Error::UnexpectedStackElementPush))
799 }
800 None => return Some(Err(Error::UnexpectedStackEnd)),
801 }
802 }
803 Terminal::AndOr(_, ref left, ref right) | Terminal::OrI(ref left, ref right) => {
804 match self.stack.pop() {
805 Some(stack::Element::Satisfied) => self.push_evaluation_state(left, 0, 0),
806 Some(stack::Element::Dissatisfied) => {
807 self.push_evaluation_state(right, 0, 0)
808 }
809 Some(stack::Element::Push(_v)) => {
810 return Some(Err(Error::UnexpectedStackElementPush))
811 }
812 None => return Some(Err(Error::UnexpectedStackEnd)),
813 }
814 }
815 Terminal::Thresh(ref _k, ref subs) if node_state.n_evaluated == 0 => {
816 self.push_evaluation_state(node_state.node, 1, 0);
817 self.push_evaluation_state(&subs[0], 0, 0);
818 }
819 Terminal::Thresh(k, ref subs) if node_state.n_evaluated == subs.len() => {
820 match self.stack.pop() {
821 Some(stack::Element::Dissatisfied) if node_state.n_satisfied == k => {
822 self.stack.push(stack::Element::Satisfied)
823 }
824 Some(stack::Element::Satisfied) if node_state.n_satisfied == k - 1 => {
825 self.stack.push(stack::Element::Satisfied)
826 }
827 Some(stack::Element::Satisfied) | Some(stack::Element::Dissatisfied) => {
828 self.stack.push(stack::Element::Dissatisfied)
829 }
830 Some(stack::Element::Push(_v)) => {
831 return Some(Err(Error::UnexpectedStackElementPush))
832 }
833 None => return Some(Err(Error::UnexpectedStackEnd)),
834 }
835 }
836 Terminal::Thresh(ref _k, ref subs) if node_state.n_evaluated != 0 => {
837 match self.stack.pop() {
838 Some(stack::Element::Dissatisfied) => {
839 self.push_evaluation_state(
840 node_state.node,
841 node_state.n_evaluated + 1,
842 node_state.n_satisfied,
843 );
844 self.push_evaluation_state(&subs[node_state.n_evaluated], 0, 0);
845 }
846 Some(stack::Element::Satisfied) => {
847 self.push_evaluation_state(
848 node_state.node,
849 node_state.n_evaluated + 1,
850 node_state.n_satisfied + 1,
851 );
852 self.push_evaluation_state(&subs[node_state.n_evaluated], 0, 0);
853 }
854 Some(stack::Element::Push(_v)) => {
855 return Some(Err(Error::UnexpectedStackElementPush))
856 }
857 None => return Some(Err(Error::UnexpectedStackEnd)),
858 }
859 }
860 Terminal::MultiA(k, ref subs) => {
861 if node_state.n_evaluated == subs.len() {
862 if node_state.n_satisfied == k {
863 self.stack.push(stack::Element::Satisfied);
864 } else {
865 self.stack.push(stack::Element::Dissatisfied);
866 }
867 } else {
868 match self
872 .stack
873 .evaluate_pk(&mut self.verify_sig, subs[node_state.n_evaluated])
874 {
875 Some(Ok(x)) => {
876 self.push_evaluation_state(
877 node_state.node,
878 node_state.n_evaluated + 1,
879 node_state.n_satisfied + 1,
880 );
881 match self.stack.pop() {
882 Some(..) => return Some(Ok(x)),
883 None => return Some(Err(Error::UnexpectedStackEnd)),
884 }
885 }
886 None => {
887 self.push_evaluation_state(
888 node_state.node,
889 node_state.n_evaluated + 1,
890 node_state.n_satisfied,
891 );
892 match self.stack.pop() {
893 Some(..) => {} None => return Some(Err(Error::UnexpectedStackEnd)),
895 }
896 }
897 x => return x, }
899 }
900 }
901 Terminal::Multi(ref k, ref subs) if node_state.n_evaluated == 0 => {
902 let len = self.stack.len();
903 if len < k + 1 {
904 return Some(Err(Error::InsufficientSignaturesMultiSig));
905 } else {
906 match self.stack.last() {
909 Some(&stack::Element::Dissatisfied) => {
910 let sigs = self.stack.split_off(len - (k + 1));
912 let nonsat = sigs
913 .iter()
914 .map(|sig| *sig == stack::Element::Dissatisfied)
915 .filter(|empty| *empty)
916 .count();
917 if nonsat == *k + 1 {
918 self.stack.push(stack::Element::Dissatisfied);
919 } else {
920 return Some(Err(Error::MissingExtraZeroMultiSig));
921 }
922 }
923 None => return Some(Err(Error::UnexpectedStackEnd)),
924 _ => {
925 match self
926 .stack
927 .evaluate_multi(&mut self.verify_sig, &subs[subs.len() - 1])
928 {
929 Some(Ok(x)) => {
930 self.push_evaluation_state(
931 node_state.node,
932 node_state.n_evaluated + 1,
933 node_state.n_satisfied + 1,
934 );
935 return Some(Ok(x));
936 }
937 None => self.push_evaluation_state(
938 node_state.node,
939 node_state.n_evaluated + 1,
940 node_state.n_satisfied,
941 ),
942 x => return x, }
944 }
945 }
946 }
947 }
948 Terminal::Multi(k, ref subs) => {
949 if node_state.n_satisfied == k {
950 if let Some(stack::Element::Dissatisfied) = self.stack.pop() {
952 self.stack.push(stack::Element::Satisfied);
953 } else {
954 return Some(Err(Error::MissingExtraZeroMultiSig));
955 }
956 } else if node_state.n_evaluated == subs.len() {
957 return Some(Err(Error::MultiSigEvaluationError));
958 } else {
959 match self.stack.evaluate_multi(
960 &mut self.verify_sig,
961 &subs[subs.len() - node_state.n_evaluated - 1],
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 return Some(Ok(x));
970 }
971 None => self.push_evaluation_state(
972 node_state.node,
973 node_state.n_evaluated + 1,
974 node_state.n_satisfied,
975 ),
976 x => return x, }
978 }
979 }
980 _ => return Some(Err(Error::CouldNotEvaluate)),
983 };
984 }
985
986 if let Some(pk) = self.public_key {
989 if let Some(stack::Element::Push(sig)) = self.stack.pop() {
990 if let Ok(key_sig) = verify_sersig(&mut self.verify_sig, pk, sig) {
991 self.public_key = None;
994 self.stack.push(stack::Element::Satisfied);
995 Some(Ok(SatisfiedConstraint::PublicKey { key_sig }))
996 } else {
997 Some(Err(Error::PkEvaluationError(PkEvalErrInner::from(*pk))))
998 }
999 } else {
1000 Some(Err(Error::UnexpectedStackEnd))
1001 }
1002 } else {
1003 if self.stack.pop() == Some(stack::Element::Satisfied) && self.stack.is_empty() {
1006 None
1007 } else {
1008 Some(Err(Error::ScriptSatisfactionError))
1009 }
1010 }
1011 }
1012}
1013
1014fn verify_sersig<'txin>(
1016 verify_sig: &mut Box<dyn FnMut(&KeySigPair) -> bool + 'txin>,
1017 pk: &BitcoinKey,
1018 sigser: &[u8],
1019) -> Result<KeySigPair, Error> {
1020 match pk {
1021 BitcoinKey::Fullkey(pk) => {
1022 let ecdsa_sig = bitcoin::EcdsaSig::from_slice(sigser)?;
1023 let key_sig_pair = KeySigPair::Ecdsa(*pk, ecdsa_sig);
1024 if verify_sig(&key_sig_pair) {
1025 Ok(key_sig_pair)
1026 } else {
1027 Err(Error::InvalidEcdsaSignature(*pk))
1028 }
1029 }
1030 BitcoinKey::XOnlyPublicKey(x_only_pk) => {
1031 let schnorr_sig = bitcoin::SchnorrSig::from_slice(sigser)?;
1032 let key_sig_pair = KeySigPair::Schnorr(*x_only_pk, schnorr_sig);
1033 if verify_sig(&key_sig_pair) {
1034 Ok(key_sig_pair)
1035 } else {
1036 Err(Error::InvalidSchnorrSignature(*x_only_pk))
1037 }
1038 }
1039 }
1040}
1041
1042#[cfg(test)]
1043mod tests {
1044
1045 use bitcoin;
1046 use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
1047 use bitcoin::secp256k1::{self, Secp256k1};
1048
1049 use super::inner::ToNoChecks;
1050 use super::*;
1051 use crate::miniscript::analyzable::ExtParams;
1052 use crate::miniscript::context::NoChecks;
1053 use crate::{Miniscript, ToPublicKey};
1054
1055 fn setup_keys_sigs(
1056 n: usize,
1057 ) -> (
1058 Vec<bitcoin::PublicKey>,
1059 Vec<Vec<u8>>,
1060 Vec<bitcoin::EcdsaSig>,
1061 secp256k1::Message,
1062 Secp256k1<secp256k1::All>,
1063 Vec<bitcoin::XOnlyPublicKey>,
1064 Vec<bitcoin::SchnorrSig>,
1065 Vec<Vec<u8>>,
1066 ) {
1067 let secp = secp256k1::Secp256k1::new();
1068 let msg = secp256k1::Message::from_slice(&b"Yoda: btc, I trust. HODL I must!"[..])
1069 .expect("32 bytes");
1070 let mut pks = vec![];
1071 let mut ecdsa_sigs = vec![];
1072 let mut der_sigs = vec![];
1073 let mut x_only_pks = vec![];
1074 let mut schnorr_sigs = vec![];
1075 let mut ser_schnorr_sigs = vec![];
1076
1077 let mut sk = [0; 32];
1078 for i in 1..n + 1 {
1079 sk[0] = i as u8;
1080 sk[1] = (i >> 8) as u8;
1081 sk[2] = (i >> 16) as u8;
1082
1083 let sk = secp256k1::SecretKey::from_slice(&sk[..]).expect("secret key");
1084 let pk = bitcoin::PublicKey {
1085 inner: secp256k1::PublicKey::from_secret_key(&secp, &sk),
1086 compressed: true,
1087 };
1088 let sig = secp.sign_ecdsa(&msg, &sk);
1089 ecdsa_sigs.push(bitcoin::EcdsaSig {
1090 sig,
1091 hash_ty: bitcoin::EcdsaSighashType::All,
1092 });
1093 let mut sigser = sig.serialize_der().to_vec();
1094 sigser.push(0x01); pks.push(pk);
1096 der_sigs.push(sigser);
1097
1098 let keypair = bitcoin::KeyPair::from_secret_key(&secp, &sk);
1099 let (x_only_pk, _parity) = bitcoin::XOnlyPublicKey::from_keypair(&keypair);
1100 x_only_pks.push(x_only_pk);
1101 let schnorr_sig = secp.sign_schnorr_with_aux_rand(&msg, &keypair, &[0u8; 32]);
1102 let schnorr_sig = bitcoin::SchnorrSig {
1103 sig: schnorr_sig,
1104 hash_ty: bitcoin::SchnorrSighashType::Default,
1105 };
1106 ser_schnorr_sigs.push(schnorr_sig.to_vec());
1107 schnorr_sigs.push(schnorr_sig);
1108 }
1109 (
1110 pks,
1111 der_sigs,
1112 ecdsa_sigs,
1113 msg,
1114 secp,
1115 x_only_pks,
1116 schnorr_sigs,
1117 ser_schnorr_sigs,
1118 )
1119 }
1120
1121 #[test]
1122 fn sat_constraints() {
1123 let (pks, der_sigs, ecdsa_sigs, sighash, secp, xpks, schnorr_sigs, ser_schnorr_sigs) =
1124 setup_keys_sigs(10);
1125 let secp_ref = &secp;
1126 let vfyfn_ = |pksig: &KeySigPair| match pksig {
1127 KeySigPair::Ecdsa(pk, ecdsa_sig) => secp_ref
1128 .verify_ecdsa(&sighash, &ecdsa_sig.sig, &pk.inner)
1129 .is_ok(),
1130 KeySigPair::Schnorr(xpk, schnorr_sig) => secp_ref
1131 .verify_schnorr(&schnorr_sig.sig, &sighash, xpk)
1132 .is_ok(),
1133 };
1134
1135 fn from_stack<'txin, 'elem>(
1136 verify_fn: Box<dyn FnMut(&KeySigPair) -> bool + 'elem>,
1137 stack: Stack<'txin>,
1138 ms: &'elem Miniscript<BitcoinKey, NoChecks>,
1139 ) -> Iter<'elem, 'txin> {
1140 Iter {
1141 verify_sig: verify_fn,
1142 stack: stack,
1143 public_key: None,
1144 state: vec![NodeEvaluationState {
1145 node: &ms,
1146 n_evaluated: 0,
1147 n_satisfied: 0,
1148 }],
1149 age: Sequence::from_height(1002),
1150 lock_time: LockTime::from_height(1002).unwrap(),
1151 has_errored: false,
1152 sig_type: SigType::Ecdsa,
1153 }
1154 }
1155
1156 let pk = no_checks_ms(&format!("c:pk_k({})", pks[0]));
1157 let pkh = no_checks_ms(&format!("c:pk_h({})", pks[1]));
1158 let after = no_checks_ms(&format!("after({})", 1000));
1160 let older = no_checks_ms(&format!("older({})", 1000));
1161 let preimage = [0xab as u8; 32];
1163 let sha256_hash = sha256::Hash::hash(&preimage);
1164 let sha256 = no_checks_ms(&format!("sha256({})", sha256_hash));
1165 let hash256_hash = hash256::Hash::hash(&preimage);
1166 let hash256 = no_checks_ms(&format!("hash256({})", hash256_hash));
1167 let hash160_hash = hash160::Hash::hash(&preimage);
1168 let hash160 = no_checks_ms(&format!("hash160({})", hash160_hash));
1169 let ripemd160_hash = ripemd160::Hash::hash(&preimage);
1170 let ripemd160 = no_checks_ms(&format!("ripemd160({})", ripemd160_hash));
1171
1172 let stack = Stack::from(vec![stack::Element::Push(&der_sigs[0])]);
1173 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &pk);
1175 let pk_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1176 assert_eq!(
1177 pk_satisfied.unwrap(),
1178 vec![SatisfiedConstraint::PublicKey {
1179 key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1180 }]
1181 );
1182
1183 let stack = Stack::from(vec![stack::Element::Dissatisfied]);
1185 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &pk);
1187 let pk_err: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1188 assert!(pk_err.is_err());
1189
1190 let pk_bytes = pks[1].to_public_key().to_bytes();
1192 let stack = Stack::from(vec![
1193 stack::Element::Push(&der_sigs[1]),
1194 stack::Element::Push(&pk_bytes),
1195 ]);
1196 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &pkh);
1198 let pkh_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1199 assert_eq!(
1200 pkh_satisfied.unwrap(),
1201 vec![SatisfiedConstraint::PublicKeyHash {
1202 keyhash: pks[1].to_pubkeyhash(SigType::Ecdsa),
1203 key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1204 }]
1205 );
1206
1207 let stack = Stack::from(vec![]);
1209 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &after);
1211 let after_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1212 assert_eq!(
1213 after_satisfied.unwrap(),
1214 vec![SatisfiedConstraint::AbsoluteTimelock {
1215 n: LockTime::from_height(1000).unwrap()
1216 }]
1217 );
1218
1219 let stack = Stack::from(vec![]);
1221 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &older);
1223 let older_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1224 assert_eq!(
1225 older_satisfied.unwrap(),
1226 vec![SatisfiedConstraint::RelativeTimelock {
1227 n: Sequence::from_height(1000)
1228 }]
1229 );
1230
1231 let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1233 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &sha256);
1235 let sah256_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1236 assert_eq!(
1237 sah256_satisfied.unwrap(),
1238 vec![SatisfiedConstraint::HashLock {
1239 hash: HashLockType::Sha256(sha256_hash),
1240 preimage: preimage,
1241 }]
1242 );
1243
1244 let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1246 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &hash256);
1248 let sha256d_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1249 assert_eq!(
1250 sha256d_satisfied.unwrap(),
1251 vec![SatisfiedConstraint::HashLock {
1252 hash: HashLockType::Hash256(hash256_hash),
1253 preimage: preimage,
1254 }]
1255 );
1256
1257 let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1259 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &hash160);
1261 let hash160_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1262 assert_eq!(
1263 hash160_satisfied.unwrap(),
1264 vec![SatisfiedConstraint::HashLock {
1265 hash: HashLockType::Hash160(hash160_hash),
1266 preimage: preimage,
1267 }]
1268 );
1269
1270 let stack = Stack::from(vec![stack::Element::Push(&preimage)]);
1272 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &ripemd160);
1274 let ripemd160_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1275 assert_eq!(
1276 ripemd160_satisfied.unwrap(),
1277 vec![SatisfiedConstraint::HashLock {
1278 hash: HashLockType::Ripemd160(ripemd160_hash),
1279 preimage: preimage
1280 }]
1281 );
1282
1283 let pk_bytes = pks[1].to_public_key().to_bytes();
1285 let stack = Stack::from(vec![
1286 stack::Element::Push(&der_sigs[1]),
1287 stack::Element::Push(&pk_bytes),
1288 stack::Element::Push(&der_sigs[0]),
1289 ]);
1290 let elem = no_checks_ms(&format!("and_v(vc:pk_k({}),c:pk_h({}))", pks[0], pks[1]));
1291 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1293
1294 let and_v_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1295 assert_eq!(
1296 and_v_satisfied.unwrap(),
1297 vec![
1298 SatisfiedConstraint::PublicKey {
1299 key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1300 },
1301 SatisfiedConstraint::PublicKeyHash {
1302 keyhash: pks[1].to_pubkeyhash(SigType::Ecdsa),
1303 key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1304 }
1305 ]
1306 );
1307
1308 let stack = Stack::from(vec![
1310 stack::Element::Push(&preimage),
1311 stack::Element::Push(&der_sigs[0]),
1312 ]);
1313 let elem = no_checks_ms(&format!(
1314 "and_b(c:pk_k({}),sjtv:sha256({}))",
1315 pks[0], sha256_hash
1316 ));
1317 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1319
1320 let and_b_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1321 assert_eq!(
1322 and_b_satisfied.unwrap(),
1323 vec![
1324 SatisfiedConstraint::PublicKey {
1325 key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1326 },
1327 SatisfiedConstraint::HashLock {
1328 hash: HashLockType::Sha256(sha256_hash),
1329 preimage: preimage,
1330 }
1331 ]
1332 );
1333
1334 let stack = Stack::from(vec![
1336 stack::Element::Push(&preimage),
1337 stack::Element::Push(&der_sigs[0]),
1338 ]);
1339 let elem = no_checks_ms(&format!(
1340 "andor(c:pk_k({}),jtv:sha256({}),c:pk_h({}))",
1341 pks[0], sha256_hash, pks[1],
1342 ));
1343 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1345
1346 let and_or_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1347 assert_eq!(
1348 and_or_satisfied.unwrap(),
1349 vec![
1350 SatisfiedConstraint::PublicKey {
1351 key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1352 },
1353 SatisfiedConstraint::HashLock {
1354 hash: HashLockType::Sha256(sha256_hash),
1355 preimage: preimage,
1356 }
1357 ]
1358 );
1359
1360 let pk_bytes = pks[1].to_public_key().to_bytes();
1362 let stack = Stack::from(vec![
1363 stack::Element::Push(&der_sigs[1]),
1364 stack::Element::Push(&pk_bytes),
1365 stack::Element::Dissatisfied,
1366 ]);
1367 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1369
1370 let and_or_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1371 assert_eq!(
1372 and_or_satisfied.unwrap(),
1373 vec![SatisfiedConstraint::PublicKeyHash {
1374 keyhash: pks[1].to_pubkeyhash(SigType::Ecdsa),
1375 key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1376 }]
1377 );
1378
1379 let stack = Stack::from(vec![
1381 stack::Element::Push(&preimage),
1382 stack::Element::Dissatisfied,
1383 ]);
1384 let elem = no_checks_ms(&format!(
1385 "or_b(c:pk_k({}),sjtv:sha256({}))",
1386 pks[0], sha256_hash
1387 ));
1388 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1390
1391 let or_b_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1392 assert_eq!(
1393 or_b_satisfied.unwrap(),
1394 vec![SatisfiedConstraint::HashLock {
1395 hash: HashLockType::Sha256(sha256_hash),
1396 preimage: preimage,
1397 }]
1398 );
1399
1400 let stack = Stack::from(vec![stack::Element::Push(&der_sigs[0])]);
1402 let elem = no_checks_ms(&format!(
1403 "or_d(c:pk_k({}),jtv:sha256({}))",
1404 pks[0], sha256_hash
1405 ));
1406 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1408
1409 let or_d_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1410 assert_eq!(
1411 or_d_satisfied.unwrap(),
1412 vec![SatisfiedConstraint::PublicKey {
1413 key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1414 }]
1415 );
1416
1417 let stack = Stack::from(vec![
1419 stack::Element::Push(&der_sigs[0]),
1420 stack::Element::Dissatisfied,
1421 ]);
1422 let elem = no_checks_ms(&format!(
1423 "t:or_c(jtv:sha256({}),vc:pk_k({}))",
1424 sha256_hash, pks[0]
1425 ));
1426 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1428
1429 let or_c_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1430 assert_eq!(
1431 or_c_satisfied.unwrap(),
1432 vec![SatisfiedConstraint::PublicKey {
1433 key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1434 }]
1435 );
1436
1437 let stack = Stack::from(vec![
1439 stack::Element::Push(&der_sigs[0]),
1440 stack::Element::Dissatisfied,
1441 ]);
1442 let elem = no_checks_ms(&format!(
1443 "or_i(jtv:sha256({}),c:pk_k({}))",
1444 sha256_hash, pks[0]
1445 ));
1446 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1448
1449 let or_i_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1450 assert_eq!(
1451 or_i_satisfied.unwrap(),
1452 vec![SatisfiedConstraint::PublicKey {
1453 key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1454 }]
1455 );
1456
1457 let stack = Stack::from(vec![
1459 stack::Element::Push(&der_sigs[0]),
1460 stack::Element::Push(&der_sigs[1]),
1461 stack::Element::Push(&der_sigs[2]),
1462 stack::Element::Dissatisfied,
1463 stack::Element::Dissatisfied,
1464 ]);
1465 let elem = no_checks_ms(&format!(
1466 "thresh(3,c:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}))",
1467 pks[4], pks[3], pks[2], pks[1], pks[0],
1468 ));
1469 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1471
1472 let thresh_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1473 assert_eq!(
1474 thresh_satisfied.unwrap(),
1475 vec![
1476 SatisfiedConstraint::PublicKey {
1477 key_sig: KeySigPair::Ecdsa(pks[2], ecdsa_sigs[2])
1478 },
1479 SatisfiedConstraint::PublicKey {
1480 key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1481 },
1482 SatisfiedConstraint::PublicKey {
1483 key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1484 }
1485 ]
1486 );
1487
1488 let stack = Stack::from(vec![
1490 stack::Element::Dissatisfied,
1491 stack::Element::Push(&der_sigs[2]),
1492 stack::Element::Push(&der_sigs[1]),
1493 stack::Element::Push(&der_sigs[0]),
1494 ]);
1495 let elem = no_checks_ms(&format!(
1496 "multi(3,{},{},{},{},{})",
1497 pks[4], pks[3], pks[2], pks[1], pks[0],
1498 ));
1499 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1501
1502 let multi_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1503 assert_eq!(
1504 multi_satisfied.unwrap(),
1505 vec![
1506 SatisfiedConstraint::PublicKey {
1507 key_sig: KeySigPair::Ecdsa(pks[0], ecdsa_sigs[0])
1508 },
1509 SatisfiedConstraint::PublicKey {
1510 key_sig: KeySigPair::Ecdsa(pks[1], ecdsa_sigs[1])
1511 },
1512 SatisfiedConstraint::PublicKey {
1513 key_sig: KeySigPair::Ecdsa(pks[2], ecdsa_sigs[2])
1514 },
1515 ]
1516 );
1517
1518 let stack = Stack::from(vec![
1520 stack::Element::Dissatisfied,
1521 stack::Element::Push(&der_sigs[0]),
1522 stack::Element::Push(&der_sigs[2]),
1523 stack::Element::Push(&der_sigs[1]),
1524 ]);
1525 let elem = no_checks_ms(&format!(
1526 "multi(3,{},{},{},{},{})",
1527 pks[4], pks[3], pks[2], pks[1], pks[0],
1528 ));
1529 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1531
1532 let multi_error: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1533 assert!(multi_error.is_err());
1534
1535 let stack = Stack::from(vec![
1537 stack::Element::Dissatisfied,
1538 stack::Element::Dissatisfied,
1539 stack::Element::Push(&ser_schnorr_sigs[2]),
1540 stack::Element::Push(&ser_schnorr_sigs[1]),
1541 stack::Element::Push(&ser_schnorr_sigs[0]),
1542 ]);
1543
1544 let elem = x_only_no_checks_ms(&format!(
1545 "multi_a(3,{},{},{},{},{})",
1546 xpks[0], xpks[1], xpks[2], xpks[3], xpks[4],
1547 ));
1548 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1550
1551 let multi_a_satisfied: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1552 assert_eq!(
1553 multi_a_satisfied.unwrap(),
1554 vec![
1555 SatisfiedConstraint::PublicKey {
1556 key_sig: KeySigPair::Schnorr(xpks[0], schnorr_sigs[0])
1557 },
1558 SatisfiedConstraint::PublicKey {
1559 key_sig: KeySigPair::Schnorr(xpks[1], schnorr_sigs[1])
1560 },
1561 SatisfiedConstraint::PublicKey {
1562 key_sig: KeySigPair::Schnorr(xpks[2], schnorr_sigs[2])
1563 },
1564 ]
1565 );
1566
1567 let stack = Stack::from(vec![
1569 stack::Element::Dissatisfied,
1570 stack::Element::Push(&ser_schnorr_sigs[2]),
1571 stack::Element::Push(&ser_schnorr_sigs[1]),
1572 stack::Element::Push(&ser_schnorr_sigs[0]),
1573 stack::Element::Dissatisfied,
1574 ]);
1575
1576 let elem = x_only_no_checks_ms(&format!(
1577 "multi_a(3,{},{},{},{},{})",
1578 xpks[0], xpks[1], xpks[2], xpks[3], xpks[4],
1579 ));
1580 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack.clone(), &elem);
1582
1583 let multi_a_error: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1584 assert!(multi_a_error.is_err());
1585
1586 let elem = x_only_no_checks_ms(&format!(
1588 "multi_a(2,{},{},{},{},{})",
1589 xpks[0], xpks[1], xpks[2], xpks[3], xpks[4],
1590 ));
1591 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack.clone(), &elem);
1593
1594 let multi_a_error: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1595 assert!(multi_a_error.is_err());
1596
1597 let elem = x_only_no_checks_ms(&format!(
1599 "multi_a(3,{},{},{},{},{},{})",
1600 xpks[0], xpks[1], xpks[2], xpks[3], xpks[4], xpks[5]
1601 ));
1602 let vfyfn = vfyfn_.clone(); let constraints = from_stack(Box::new(vfyfn), stack, &elem);
1604
1605 let multi_a_error: Result<Vec<SatisfiedConstraint>, Error> = constraints.collect();
1606 assert!(multi_a_error.is_err());
1607 }
1608
1609 fn no_checks_ms(ms: &str) -> Miniscript<BitcoinKey, NoChecks> {
1612 let elem: Miniscript<bitcoin::PublicKey, NoChecks> =
1614 Miniscript::from_str_ext(ms, &ExtParams::allow_all()).unwrap();
1615 elem.to_no_checks_ms()
1616 }
1617
1618 fn x_only_no_checks_ms(ms: &str) -> Miniscript<BitcoinKey, NoChecks> {
1619 let elem: Miniscript<bitcoin::XOnlyPublicKey, NoChecks> =
1620 Miniscript::from_str_ext(ms, &ExtParams::allow_all()).unwrap();
1621 elem.to_no_checks_ms()
1622 }
1623}