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