1pub mod correctness;
9pub mod extra_props;
10pub mod malleability;
11
12use core::fmt;
13#[cfg(feature = "std")]
14use std::error;
15
16use qtum::{absolute, Sequence};
17
18pub use self::correctness::{Base, Correctness, Input};
19pub use self::extra_props::ExtData;
20pub use self::malleability::{Dissat, Malleability};
21use super::ScriptContext;
22use crate::{MiniscriptKey, Terminal};
23
24fn return_none<T>(_: usize) -> Option<T> {
27 None
28}
29
30#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
32pub enum ErrorKind {
33 InvalidTime,
35 NonZeroDupIf,
37 ZeroThreshold,
39 OverThreshold(usize, usize),
42 NoStrongChild,
48 LeftNotDissatisfiable,
51 RightNotDissatisfiable,
53 SwapNonOne,
56 NonZeroZero,
59 LeftNotUnit,
62 ChildBase1(Base),
65 ChildBase2(Base, Base),
68 ChildBase3(Base, Base, Base),
71 ThresholdBase(usize, Base),
74 ThresholdDissat(usize),
77 ThresholdNonUnit(usize),
79 ThresholdNotStrong {
81 k: usize,
83 n: usize,
85 n_strong: usize,
87 },
88}
89
90#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
92pub struct Error<Pk: MiniscriptKey, Ctx: ScriptContext> {
93 pub fragment: Terminal<Pk, Ctx>,
95 pub error: ErrorKind,
97}
98
99impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Error<Pk, Ctx> {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 match self.error {
102 ErrorKind::InvalidTime => write!(
103 f,
104 "fragment «{}» represents a timelock which value is invalid (time must be in [1; 0x80000000])",
105 self.fragment,
106 ),
107 ErrorKind::NonZeroDupIf => write!(
108 f,
109 "fragment «{}» represents needs to be `z`, needs to consume zero elements from the stack",
110 self.fragment,
111 ),
112 ErrorKind::ZeroThreshold => write!(
113 f,
114 "fragment «{}» has a threshold value of 0",
115 self.fragment,
116 ),
117 ErrorKind::OverThreshold(k, n) => write!(
118 f,
119 "fragment «{}» is a {}-of-{} threshold, which does not
120 make sense",
121 self.fragment, k, n,
122 ),
123 ErrorKind::NoStrongChild => write!(
124 f,
125 "fragment «{}» requires at least one strong child \
126 (a 3rd party cannot create a witness without having \
127 seen one before) to prevent malleability",
128 self.fragment,
129 ),
130 ErrorKind::LeftNotDissatisfiable => write!(
131 f,
132 "fragment «{}» requires its left child be dissatisfiable",
133 self.fragment,
134 ),
135 ErrorKind::RightNotDissatisfiable => write!(
136 f,
137 "fragment «{}» requires its right child be dissatisfiable",
138 self.fragment,
139 ),
140 ErrorKind::SwapNonOne => write!(
141 f,
142 "fragment «{}» attempts to use `SWAP` to prefix something
143 which does not take exactly one input",
144 self.fragment,
145 ),
146 ErrorKind::NonZeroZero => write!(
147 f,
148 "fragment «{}» attempts to use use the `j:` wrapper around a
149 fragment which might be satisfied by an input of size zero",
150 self.fragment,
151 ),
152 ErrorKind::LeftNotUnit => write!(
153 f,
154 "fragment «{}» requires its left child be a unit (outputs
155 exactly 1 given a satisfying input)",
156 self.fragment,
157 ),
158 ErrorKind::ChildBase1(base) => write!(
159 f,
160 "fragment «{}» cannot wrap a fragment of type {:?}",
161 self.fragment, base,
162 ),
163 ErrorKind::ChildBase2(base1, base2) => write!(
164 f,
165 "fragment «{}» cannot accept children of types {:?} and {:?}",
166 self.fragment, base1, base2,
167 ),
168 ErrorKind::ChildBase3(base1, base2, base3) => write!(
169 f,
170 "fragment «{}» cannot accept children of types {:?}, {:?} and {:?}",
171 self.fragment, base1, base2, base3,
172 ),
173 ErrorKind::ThresholdBase(idx, base) => write!(
174 f,
175 "fragment «{}» sub-fragment {} has type {:?} rather than {:?}",
176 self.fragment,
177 idx,
178 base,
179 if idx == 0 { Base::B } else { Base::W },
180 ),
181 ErrorKind::ThresholdDissat(idx) => write!(
182 f,
183 "fragment «{}» sub-fragment {} can not be dissatisfied \
184 and cannot be used in a threshold",
185 self.fragment, idx,
186 ),
187 ErrorKind::ThresholdNonUnit(idx) => write!(
188 f,
189 "fragment «{}» sub-fragment {} is not a unit (does not put \
190 exactly 1 on the stack given a satisfying input)",
191 self.fragment, idx,
192 ),
193 ErrorKind::ThresholdNotStrong { k, n, n_strong } => write!(
194 f,
195 "fragment «{}» is a {}-of-{} threshold, and needs {} of \
196 its children to be strong to prevent malleability; however \
197 only {} children were strong.",
198 self.fragment,
199 k,
200 n,
201 n - k,
202 n_strong,
203 ),
204 }
205 }
206}
207
208#[cfg(feature = "std")]
209impl<Pk: MiniscriptKey, Ctx: ScriptContext> error::Error for Error<Pk, Ctx> {
210 fn cause(&self) -> Option<&dyn error::Error> {
211 None
212 }
213}
214
215#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
218pub struct Type {
219 pub corr: Correctness,
221 pub mall: Malleability,
223}
224
225impl Type {
226 pub fn is_subtype(&self, other: Self) -> bool {
231 self.corr.is_subtype(other.corr) && self.mall.is_subtype(other.mall)
232 }
233}
234pub trait Property: Sized {
237 fn sanity_checks(&self) {
240 }
242
243 fn from_true() -> Self;
245
246 fn from_false() -> Self;
248
249 fn from_pk_k<Ctx: ScriptContext>() -> Self;
251
252 fn from_pk_h<Ctx: ScriptContext>() -> Self;
254
255 fn from_multi(k: usize, n: usize) -> Self;
257
258 fn from_multi_a(k: usize, n: usize) -> Self;
260
261 fn from_hash() -> Self;
263
264 fn from_sha256() -> Self {
267 Self::from_hash()
268 }
269
270 fn from_hash256() -> Self {
273 Self::from_hash()
274 }
275
276 fn from_ripemd160() -> Self {
279 Self::from_hash()
280 }
281
282 fn from_hash160() -> Self {
285 Self::from_hash()
286 }
287
288 fn from_time(t: u32) -> Self;
290
291 fn from_after(t: absolute::LockTime) -> Self {
294 Self::from_time(t.to_consensus_u32())
295 }
296
297 fn from_older(t: Sequence) -> Self {
300 Self::from_time(t.to_consensus_u32())
301 }
302
303 fn cast_alt(self) -> Result<Self, ErrorKind>;
305
306 fn cast_swap(self) -> Result<Self, ErrorKind>;
308
309 fn cast_check(self) -> Result<Self, ErrorKind>;
311
312 fn cast_dupif(self) -> Result<Self, ErrorKind>;
314
315 fn cast_verify(self) -> Result<Self, ErrorKind>;
317
318 fn cast_nonzero(self) -> Result<Self, ErrorKind>;
320
321 fn cast_zeronotequal(self) -> Result<Self, ErrorKind>;
323
324 fn cast_true(self) -> Result<Self, ErrorKind> {
326 Self::and_v(self, Self::from_true())
327 }
328
329 fn cast_or_i_false(self) -> Result<Self, ErrorKind>;
331
332 fn cast_unlikely(self) -> Result<Self, ErrorKind> {
335 Self::or_i(self, Self::from_false())
336 }
337
338 fn cast_likely(self) -> Result<Self, ErrorKind> {
341 Self::or_i(Self::from_false(), self)
342 }
343
344 fn and_b(left: Self, right: Self) -> Result<Self, ErrorKind>;
346
347 fn and_v(left: Self, right: Self) -> Result<Self, ErrorKind>;
349
350 fn and_n(left: Self, right: Self) -> Result<Self, ErrorKind> {
352 Self::and_or(left, right, Self::from_false())
353 }
354
355 fn or_b(left: Self, right: Self) -> Result<Self, ErrorKind>;
357
358 fn or_d(left: Self, right: Self) -> Result<Self, ErrorKind>;
360
361 fn or_c(left: Self, right: Self) -> Result<Self, ErrorKind>;
363
364 fn or_i(left: Self, right: Self) -> Result<Self, ErrorKind>;
366
367 fn and_or(a: Self, b: Self, c: Self) -> Result<Self, ErrorKind>;
369
370 fn threshold<S>(k: usize, n: usize, sub_ck: S) -> Result<Self, ErrorKind>
372 where
373 S: FnMut(usize) -> Result<Self, ErrorKind>;
374
375 fn type_check<Pk, Ctx, C>(
379 fragment: &Terminal<Pk, Ctx>,
380 mut child: C,
381 ) -> Result<Self, Error<Pk, Ctx>>
382 where
383 C: FnMut(usize) -> Option<Self>,
384 Pk: MiniscriptKey,
385 Ctx: ScriptContext,
386 {
387 let mut get_child = |sub, n| {
388 child(n)
389 .map(Ok)
390 .unwrap_or_else(|| Self::type_check(sub, return_none))
391 };
392 let wrap_err = |result: Result<Self, ErrorKind>| {
393 result.map_err(|kind| Error {
394 fragment: fragment.clone(),
395 error: kind,
396 })
397 };
398
399 let ret = match *fragment {
400 Terminal::True => Ok(Self::from_true()),
401 Terminal::False => Ok(Self::from_false()),
402 Terminal::PkK(..) => Ok(Self::from_pk_k::<Ctx>()),
403 Terminal::PkH(..) | Terminal::RawPkH(..) => Ok(Self::from_pk_h::<Ctx>()),
404 Terminal::Multi(k, ref pks) | Terminal::MultiA(k, ref pks) => {
405 if k == 0 {
406 return Err(Error {
407 fragment: fragment.clone(),
408 error: ErrorKind::ZeroThreshold,
409 });
410 }
411 if k > pks.len() {
412 return Err(Error {
413 fragment: fragment.clone(),
414 error: ErrorKind::OverThreshold(k, pks.len()),
415 });
416 }
417 match *fragment {
418 Terminal::Multi(..) => Ok(Self::from_multi(k, pks.len())),
419 Terminal::MultiA(..) => Ok(Self::from_multi_a(k, pks.len())),
420 _ => unreachable!(),
421 }
422 }
423 Terminal::After(t) => {
424 if t == absolute::LockTime::ZERO.into() {
428 return Err(Error {
429 fragment: fragment.clone(),
430 error: ErrorKind::InvalidTime,
431 });
432 }
433 Ok(Self::from_after(t.into()))
434 }
435 Terminal::Older(t) => {
436 if t == Sequence::ZERO || !t.is_relative_lock_time() {
437 return Err(Error {
438 fragment: fragment.clone(),
439 error: ErrorKind::InvalidTime,
440 });
441 }
442 Ok(Self::from_older(t))
443 }
444 Terminal::Sha256(..) => Ok(Self::from_sha256()),
445 Terminal::Hash256(..) => Ok(Self::from_hash256()),
446 Terminal::Ripemd160(..) => Ok(Self::from_ripemd160()),
447 Terminal::Hash160(..) => Ok(Self::from_hash160()),
448 Terminal::Alt(ref sub) => wrap_err(Self::cast_alt(get_child(&sub.node, 0)?)),
449 Terminal::Swap(ref sub) => wrap_err(Self::cast_swap(get_child(&sub.node, 0)?)),
450 Terminal::Check(ref sub) => wrap_err(Self::cast_check(get_child(&sub.node, 0)?)),
451 Terminal::DupIf(ref sub) => wrap_err(Self::cast_dupif(get_child(&sub.node, 0)?)),
452 Terminal::Verify(ref sub) => wrap_err(Self::cast_verify(get_child(&sub.node, 0)?)),
453 Terminal::NonZero(ref sub) => wrap_err(Self::cast_nonzero(get_child(&sub.node, 0)?)),
454 Terminal::ZeroNotEqual(ref sub) => {
455 wrap_err(Self::cast_zeronotequal(get_child(&sub.node, 0)?))
456 }
457 Terminal::AndB(ref l, ref r) => {
458 let ltype = get_child(&l.node, 0)?;
459 let rtype = get_child(&r.node, 1)?;
460 wrap_err(Self::and_b(ltype, rtype))
461 }
462 Terminal::AndV(ref l, ref r) => {
463 let ltype = get_child(&l.node, 0)?;
464 let rtype = get_child(&r.node, 1)?;
465 wrap_err(Self::and_v(ltype, rtype))
466 }
467 Terminal::OrB(ref l, ref r) => {
468 let ltype = get_child(&l.node, 0)?;
469 let rtype = get_child(&r.node, 1)?;
470 wrap_err(Self::or_b(ltype, rtype))
471 }
472 Terminal::OrD(ref l, ref r) => {
473 let ltype = get_child(&l.node, 0)?;
474 let rtype = get_child(&r.node, 1)?;
475 wrap_err(Self::or_d(ltype, rtype))
476 }
477 Terminal::OrC(ref l, ref r) => {
478 let ltype = get_child(&l.node, 0)?;
479 let rtype = get_child(&r.node, 1)?;
480 wrap_err(Self::or_c(ltype, rtype))
481 }
482 Terminal::OrI(ref l, ref r) => {
483 let ltype = get_child(&l.node, 0)?;
484 let rtype = get_child(&r.node, 1)?;
485 wrap_err(Self::or_i(ltype, rtype))
486 }
487 Terminal::AndOr(ref a, ref b, ref c) => {
488 let atype = get_child(&a.node, 0)?;
489 let btype = get_child(&b.node, 1)?;
490 let ctype = get_child(&c.node, 2)?;
491 wrap_err(Self::and_or(atype, btype, ctype))
492 }
493 Terminal::Thresh(k, ref subs) => {
494 if k == 0 {
495 return Err(Error {
496 fragment: fragment.clone(),
497 error: ErrorKind::ZeroThreshold,
498 });
499 }
500 if k > subs.len() {
501 return Err(Error {
502 fragment: fragment.clone(),
503 error: ErrorKind::OverThreshold(k, subs.len()),
504 });
505 }
506
507 let mut last_err_frag = None;
508 let res = Self::threshold(k, subs.len(), |n| match get_child(&subs[n].node, n) {
509 Ok(x) => Ok(x),
510 Err(e) => {
511 last_err_frag = Some(e.fragment);
512 Err(e.error)
513 }
514 });
515
516 res.map_err(|kind| Error {
517 fragment: last_err_frag.unwrap_or_else(|| fragment.clone()),
518 error: kind,
519 })
520 }
521 };
522 if let Ok(ref ret) = ret {
523 ret.sanity_checks()
524 }
525 ret
526 }
527}
528
529impl Property for Type {
530 fn sanity_checks(&self) {
531 debug_assert!(!self.corr.dissatisfiable || self.mall.dissat != Dissat::None);
532 debug_assert!(self.mall.dissat == Dissat::None || self.corr.base != Base::V);
533 debug_assert!(self.mall.safe || self.corr.base != Base::K);
534 debug_assert!(self.mall.non_malleable || self.corr.input != Input::Zero);
535 }
536
537 fn from_true() -> Self {
538 Type {
539 corr: Property::from_true(),
540 mall: Property::from_true(),
541 }
542 }
543
544 fn from_false() -> Self {
545 Type {
546 corr: Property::from_false(),
547 mall: Property::from_false(),
548 }
549 }
550
551 fn from_pk_k<Ctx: ScriptContext>() -> Self {
552 Type {
553 corr: Property::from_pk_k::<Ctx>(),
554 mall: Property::from_pk_k::<Ctx>(),
555 }
556 }
557
558 fn from_pk_h<Ctx: ScriptContext>() -> Self {
559 Type {
560 corr: Property::from_pk_h::<Ctx>(),
561 mall: Property::from_pk_h::<Ctx>(),
562 }
563 }
564
565 fn from_multi(k: usize, n: usize) -> Self {
566 Type {
567 corr: Property::from_multi(k, n),
568 mall: Property::from_multi(k, n),
569 }
570 }
571
572 fn from_multi_a(k: usize, n: usize) -> Self {
573 Type {
574 corr: Property::from_multi_a(k, n),
575 mall: Property::from_multi_a(k, n),
576 }
577 }
578
579 fn from_hash() -> Self {
580 Type {
581 corr: Property::from_hash(),
582 mall: Property::from_hash(),
583 }
584 }
585
586 fn from_sha256() -> Self {
587 Type {
588 corr: Property::from_sha256(),
589 mall: Property::from_sha256(),
590 }
591 }
592
593 fn from_hash256() -> Self {
594 Type {
595 corr: Property::from_hash256(),
596 mall: Property::from_hash256(),
597 }
598 }
599
600 fn from_ripemd160() -> Self {
601 Type {
602 corr: Property::from_ripemd160(),
603 mall: Property::from_ripemd160(),
604 }
605 }
606
607 fn from_hash160() -> Self {
608 Type {
609 corr: Property::from_hash160(),
610 mall: Property::from_hash160(),
611 }
612 }
613
614 fn from_time(t: u32) -> Self {
615 Type {
616 corr: Property::from_time(t),
617 mall: Property::from_time(t),
618 }
619 }
620
621 fn from_after(t: absolute::LockTime) -> Self {
622 Type {
623 corr: Property::from_after(t),
624 mall: Property::from_after(t),
625 }
626 }
627
628 fn from_older(t: Sequence) -> Self {
629 Type {
630 corr: Property::from_older(t),
631 mall: Property::from_older(t),
632 }
633 }
634
635 fn cast_alt(self) -> Result<Self, ErrorKind> {
636 Ok(Type {
637 corr: Property::cast_alt(self.corr)?,
638 mall: Property::cast_alt(self.mall)?,
639 })
640 }
641
642 fn cast_swap(self) -> Result<Self, ErrorKind> {
643 Ok(Type {
644 corr: Property::cast_swap(self.corr)?,
645 mall: Property::cast_swap(self.mall)?,
646 })
647 }
648
649 fn cast_check(self) -> Result<Self, ErrorKind> {
650 Ok(Type {
651 corr: Property::cast_check(self.corr)?,
652 mall: Property::cast_check(self.mall)?,
653 })
654 }
655
656 fn cast_dupif(self) -> Result<Self, ErrorKind> {
657 Ok(Type {
658 corr: Property::cast_dupif(self.corr)?,
659 mall: Property::cast_dupif(self.mall)?,
660 })
661 }
662
663 fn cast_verify(self) -> Result<Self, ErrorKind> {
664 Ok(Type {
665 corr: Property::cast_verify(self.corr)?,
666 mall: Property::cast_verify(self.mall)?,
667 })
668 }
669
670 fn cast_nonzero(self) -> Result<Self, ErrorKind> {
671 Ok(Type {
672 corr: Property::cast_nonzero(self.corr)?,
673 mall: Property::cast_nonzero(self.mall)?,
674 })
675 }
676
677 fn cast_zeronotequal(self) -> Result<Self, ErrorKind> {
678 Ok(Type {
679 corr: Property::cast_zeronotequal(self.corr)?,
680 mall: Property::cast_zeronotequal(self.mall)?,
681 })
682 }
683
684 fn cast_true(self) -> Result<Self, ErrorKind> {
685 Ok(Type {
686 corr: Property::cast_true(self.corr)?,
687 mall: Property::cast_true(self.mall)?,
688 })
689 }
690
691 fn cast_or_i_false(self) -> Result<Self, ErrorKind> {
692 Ok(Type {
693 corr: Property::cast_or_i_false(self.corr)?,
694 mall: Property::cast_or_i_false(self.mall)?,
695 })
696 }
697
698 fn cast_unlikely(self) -> Result<Self, ErrorKind> {
699 Ok(Type {
700 corr: Property::cast_unlikely(self.corr)?,
701 mall: Property::cast_unlikely(self.mall)?,
702 })
703 }
704
705 fn cast_likely(self) -> Result<Self, ErrorKind> {
706 Ok(Type {
707 corr: Property::cast_likely(self.corr)?,
708 mall: Property::cast_likely(self.mall)?,
709 })
710 }
711
712 fn and_b(left: Self, right: Self) -> Result<Self, ErrorKind> {
713 Ok(Type {
714 corr: Property::and_b(left.corr, right.corr)?,
715 mall: Property::and_b(left.mall, right.mall)?,
716 })
717 }
718
719 fn and_v(left: Self, right: Self) -> Result<Self, ErrorKind> {
720 Ok(Type {
721 corr: Property::and_v(left.corr, right.corr)?,
722 mall: Property::and_v(left.mall, right.mall)?,
723 })
724 }
725
726 fn or_b(left: Self, right: Self) -> Result<Self, ErrorKind> {
727 Ok(Type {
728 corr: Property::or_b(left.corr, right.corr)?,
729 mall: Property::or_b(left.mall, right.mall)?,
730 })
731 }
732
733 fn or_d(left: Self, right: Self) -> Result<Self, ErrorKind> {
734 Ok(Type {
735 corr: Property::or_d(left.corr, right.corr)?,
736 mall: Property::or_d(left.mall, right.mall)?,
737 })
738 }
739
740 fn or_c(left: Self, right: Self) -> Result<Self, ErrorKind> {
741 Ok(Type {
742 corr: Property::or_c(left.corr, right.corr)?,
743 mall: Property::or_c(left.mall, right.mall)?,
744 })
745 }
746
747 fn or_i(left: Self, right: Self) -> Result<Self, ErrorKind> {
748 Ok(Type {
749 corr: Property::or_i(left.corr, right.corr)?,
750 mall: Property::or_i(left.mall, right.mall)?,
751 })
752 }
753
754 fn and_or(a: Self, b: Self, c: Self) -> Result<Self, ErrorKind> {
755 Ok(Type {
756 corr: Property::and_or(a.corr, b.corr, c.corr)?,
757 mall: Property::and_or(a.mall, b.mall, c.mall)?,
758 })
759 }
760
761 fn threshold<S>(k: usize, n: usize, mut sub_ck: S) -> Result<Self, ErrorKind>
762 where
763 S: FnMut(usize) -> Result<Self, ErrorKind>,
764 {
765 Ok(Type {
766 corr: Property::threshold(k, n, |n| Ok(sub_ck(n)?.corr))?,
767 mall: Property::threshold(k, n, |n| Ok(sub_ck(n)?.mall))?,
768 })
769 }
770
771 fn type_check<Pk, Ctx, C>(
774 fragment: &Terminal<Pk, Ctx>,
775 _child: C,
776 ) -> Result<Self, Error<Pk, Ctx>>
777 where
778 C: FnMut(usize) -> Option<Self>,
779 Pk: MiniscriptKey,
780 Ctx: ScriptContext,
781 {
782 let wrap_err = |result: Result<Self, ErrorKind>| {
783 result.map_err(|kind| Error {
784 fragment: fragment.clone(),
785 error: kind,
786 })
787 };
788
789 let ret = match *fragment {
790 Terminal::True => Ok(Self::from_true()),
791 Terminal::False => Ok(Self::from_false()),
792 Terminal::PkK(..) => Ok(Self::from_pk_k::<Ctx>()),
793 Terminal::PkH(..) | Terminal::RawPkH(..) => Ok(Self::from_pk_h::<Ctx>()),
794 Terminal::Multi(k, ref pks) | Terminal::MultiA(k, ref pks) => {
795 if k == 0 {
796 return Err(Error {
797 fragment: fragment.clone(),
798 error: ErrorKind::ZeroThreshold,
799 });
800 }
801 if k > pks.len() {
802 return Err(Error {
803 fragment: fragment.clone(),
804 error: ErrorKind::OverThreshold(k, pks.len()),
805 });
806 }
807 match *fragment {
808 Terminal::Multi(..) => Ok(Self::from_multi(k, pks.len())),
809 Terminal::MultiA(..) => Ok(Self::from_multi_a(k, pks.len())),
810 _ => unreachable!(),
811 }
812 }
813 Terminal::After(t) => {
814 if t == absolute::LockTime::ZERO.into() {
818 return Err(Error {
819 fragment: fragment.clone(),
820 error: ErrorKind::InvalidTime,
821 });
822 }
823 Ok(Self::from_after(t.into()))
824 }
825 Terminal::Older(t) => {
826 if t == Sequence::ZERO || !t.is_relative_lock_time() {
827 return Err(Error {
828 fragment: fragment.clone(),
829 error: ErrorKind::InvalidTime,
830 });
831 }
832 Ok(Self::from_older(t))
833 }
834 Terminal::Sha256(..) => Ok(Self::from_sha256()),
835 Terminal::Hash256(..) => Ok(Self::from_hash256()),
836 Terminal::Ripemd160(..) => Ok(Self::from_ripemd160()),
837 Terminal::Hash160(..) => Ok(Self::from_hash160()),
838 Terminal::Alt(ref sub) => wrap_err(Self::cast_alt(sub.ty)),
839 Terminal::Swap(ref sub) => wrap_err(Self::cast_swap(sub.ty)),
840 Terminal::Check(ref sub) => wrap_err(Self::cast_check(sub.ty)),
841 Terminal::DupIf(ref sub) => wrap_err(Self::cast_dupif(sub.ty)),
842 Terminal::Verify(ref sub) => wrap_err(Self::cast_verify(sub.ty)),
843 Terminal::NonZero(ref sub) => wrap_err(Self::cast_nonzero(sub.ty)),
844 Terminal::ZeroNotEqual(ref sub) => wrap_err(Self::cast_zeronotequal(sub.ty)),
845 Terminal::AndB(ref l, ref r) => {
846 let ltype = l.ty;
847 let rtype = r.ty;
848 wrap_err(Self::and_b(ltype, rtype))
849 }
850 Terminal::AndV(ref l, ref r) => {
851 let ltype = l.ty;
852 let rtype = r.ty;
853 wrap_err(Self::and_v(ltype, rtype))
854 }
855 Terminal::OrB(ref l, ref r) => {
856 let ltype = l.ty;
857 let rtype = r.ty;
858 wrap_err(Self::or_b(ltype, rtype))
859 }
860 Terminal::OrD(ref l, ref r) => {
861 let ltype = l.ty;
862 let rtype = r.ty;
863 wrap_err(Self::or_d(ltype, rtype))
864 }
865 Terminal::OrC(ref l, ref r) => {
866 let ltype = l.ty;
867 let rtype = r.ty;
868 wrap_err(Self::or_c(ltype, rtype))
869 }
870 Terminal::OrI(ref l, ref r) => {
871 let ltype = l.ty;
872 let rtype = r.ty;
873 wrap_err(Self::or_i(ltype, rtype))
874 }
875 Terminal::AndOr(ref a, ref b, ref c) => {
876 let atype = a.ty;
877 let btype = b.ty;
878 let ctype = c.ty;
879 wrap_err(Self::and_or(atype, btype, ctype))
880 }
881 Terminal::Thresh(k, ref subs) => {
882 if k == 0 {
883 return Err(Error {
884 fragment: fragment.clone(),
885 error: ErrorKind::ZeroThreshold,
886 });
887 }
888 if k > subs.len() {
889 return Err(Error {
890 fragment: fragment.clone(),
891 error: ErrorKind::OverThreshold(k, subs.len()),
892 });
893 }
894
895 let res = Self::threshold(k, subs.len(), |n| Ok(subs[n].ty));
896
897 res.map_err(|kind| Error {
898 fragment: fragment.clone(),
899 error: kind,
900 })
901 }
902 };
903 if let Ok(ref ret) = ret {
904 ret.sanity_checks()
905 }
906 ret
907 }
908}