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