1pub mod correctness;
9pub mod extra_props;
10pub mod malleability;
11
12use std::{error, fmt};
13
14use elements::{LockTime, Sequence};
15
16pub use self::correctness::{Base, Correctness, Input};
17pub use self::extra_props::ExtData;
18pub use self::malleability::{Dissat, Malleability};
19use super::ScriptContext;
20use crate::{Extension, MiniscriptKey, NoExt, Terminal};
21
22#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
24pub enum ErrorKind {
25 InvalidTime,
27 NonZeroDupIf,
29 ZeroThreshold,
31 OverThreshold(usize, usize),
34 NoStrongChild,
40 LeftNotDissatisfiable,
43 RightNotDissatisfiable,
45 SwapNonOne,
48 NonZeroZero,
51 LeftNotUnit,
54 ChildBase1(Base),
57 ChildBase2(Base, Base),
60 ChildBase3(Base, Base, Base),
63 ThresholdBase(usize, Base),
66 ThresholdDissat(usize),
69 ThresholdNonUnit(usize),
71 ThresholdNotStrong {
73 k: usize,
75 n: usize,
77 n_strong: usize,
79 },
80}
81
82#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
84pub struct Error<Pk: MiniscriptKey, Ctx: ScriptContext, Ext: Extension = NoExt> {
85 pub fragment: Terminal<Pk, Ctx, Ext>,
87 pub error: ErrorKind,
89}
90
91impl<Pk, Ctx, Ext> fmt::Display for Error<Pk, Ctx, Ext>
92where
93 Pk: MiniscriptKey,
94 Ctx: ScriptContext,
95 Ext: Extension,
96{
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 match self.error {
99 ErrorKind::InvalidTime => write!(
100 f,
101 "fragment «{}» represents a timelock which value is invalid (time must be in [1; 0x80000000])",
102 self.fragment,
103 ),
104 ErrorKind::NonZeroDupIf => write!(
105 f,
106 "fragment «{}» represents needs to be `z`, needs to consume zero elements from the stack",
107 self.fragment,
108 ),
109 ErrorKind::ZeroThreshold => write!(
110 f,
111 "fragment «{}» has a threshold value of 0",
112 self.fragment,
113 ),
114 ErrorKind::OverThreshold(k, n) => write!(
115 f,
116 "fragment «{}» is a {}-of-{} threshold, which does not
117 make sense",
118 self.fragment, k, n,
119 ),
120 ErrorKind::NoStrongChild => write!(
121 f,
122 "fragment «{}» requires at least one strong child \
123 (a 3rd party cannot create a witness without having \
124 seen one before) to prevent malleability",
125 self.fragment,
126 ),
127 ErrorKind::LeftNotDissatisfiable => write!(
128 f,
129 "fragment «{}» requires its left child be dissatisfiable",
130 self.fragment,
131 ),
132 ErrorKind::RightNotDissatisfiable => write!(
133 f,
134 "fragment «{}» requires its right child be dissatisfiable",
135 self.fragment,
136 ),
137 ErrorKind::SwapNonOne => write!(
138 f,
139 "fragment «{}» attempts to use `SWAP` to prefix something
140 which does not take exactly one input",
141 self.fragment,
142 ),
143 ErrorKind::NonZeroZero => write!(
144 f,
145 "fragment «{}» attempts to use use the `j:` wrapper around a
146 fragment which might be satisfied by an input of size zero",
147 self.fragment,
148 ),
149 ErrorKind::LeftNotUnit => write!(
150 f,
151 "fragment «{}» requires its left child be a unit (outputs
152 exactly 1 given a satisfying input)",
153 self.fragment,
154 ),
155 ErrorKind::ChildBase1(base) => write!(
156 f,
157 "fragment «{}» cannot wrap a fragment of type {:?}",
158 self.fragment, base,
159 ),
160 ErrorKind::ChildBase2(base1, base2) => write!(
161 f,
162 "fragment «{}» cannot accept children of types {:?} and {:?}",
163 self.fragment, base1, base2,
164 ),
165 ErrorKind::ChildBase3(base1, base2, base3) => write!(
166 f,
167 "fragment «{}» cannot accept children of types {:?}, {:?} and {:?}",
168 self.fragment, base1, base2, base3,
169 ),
170 ErrorKind::ThresholdBase(idx, base) => write!(
171 f,
172 "fragment «{}» sub-fragment {} has type {:?} rather than {:?}",
173 self.fragment,
174 idx,
175 base,
176 if idx == 0 { Base::B } else { Base::W },
177 ),
178 ErrorKind::ThresholdDissat(idx) => write!(
179 f,
180 "fragment «{}» sub-fragment {} can not be dissatisfied \
181 and cannot be used in a threshold",
182 self.fragment, idx,
183 ),
184 ErrorKind::ThresholdNonUnit(idx) => write!(
185 f,
186 "fragment «{}» sub-fragment {} is not a unit (does not put \
187 exactly 1 on the stack given a satisfying input)",
188 self.fragment, idx,
189 ),
190 ErrorKind::ThresholdNotStrong { k, n, n_strong } => write!(
191 f,
192 "fragment «{}» is a {}-of-{} threshold, and needs {} of \
193 its children to be strong to prevent malleability; however \
194 only {} children were strong.",
195 self.fragment,
196 k,
197 n,
198 n - k,
199 n_strong,
200 ),
201 }
202 }
203}
204
205impl<Pk: MiniscriptKey, Ctx: ScriptContext> error::Error for Error<Pk, Ctx> {
206 fn cause(&self) -> Option<&dyn error::Error> {
207 None
208 }
209}
210
211#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
214pub struct Type {
215 pub corr: Correctness,
217 pub mall: Malleability,
219}
220
221impl Type {
222 pub fn is_subtype(&self, other: Self) -> bool {
227 self.corr.is_subtype(other.corr) && self.mall.is_subtype(other.mall)
228 }
229}
230pub trait Property: Sized {
233 fn sanity_checks(&self) {
236 }
238
239 fn from_true() -> Self;
241
242 fn from_false() -> Self;
244
245 fn from_pk_k<Ctx: ScriptContext>() -> Self;
247
248 fn from_pk_h<Ctx: ScriptContext>() -> Self;
250
251 fn from_multi(k: usize, n: usize) -> Self;
253
254 fn from_multi_a(k: usize, n: usize) -> Self;
256
257 fn from_hash() -> Self;
259
260 fn from_sha256() -> Self {
263 Self::from_hash()
264 }
265
266 fn from_hash256() -> Self {
269 Self::from_hash()
270 }
271
272 fn from_ripemd160() -> Self {
275 Self::from_hash()
276 }
277
278 fn from_hash160() -> Self {
281 Self::from_hash()
282 }
283
284 fn from_time(t: u32) -> Self;
286
287 fn from_after(t: LockTime) -> Self {
290 Self::from_time(t.to_consensus_u32())
291 }
292
293 fn from_older(t: Sequence) -> Self {
296 Self::from_time(t.to_consensus_u32())
297 }
298
299 fn cast_alt(self) -> Result<Self, ErrorKind>;
301
302 fn cast_swap(self) -> Result<Self, ErrorKind>;
304
305 fn cast_check(self) -> Result<Self, ErrorKind>;
307
308 fn cast_dupif(self) -> Result<Self, ErrorKind>;
310
311 fn cast_verify(self) -> Result<Self, ErrorKind>;
313
314 fn cast_nonzero(self) -> Result<Self, ErrorKind>;
316
317 fn cast_zeronotequal(self) -> Result<Self, ErrorKind>;
319
320 fn cast_true(self) -> Result<Self, ErrorKind> {
322 Self::and_v(self, Self::from_true())
323 }
324
325 fn cast_or_i_false(self) -> Result<Self, ErrorKind>;
327
328 fn cast_unlikely(self) -> Result<Self, ErrorKind> {
331 Self::or_i(self, Self::from_false())
332 }
333
334 fn cast_likely(self) -> Result<Self, ErrorKind> {
337 Self::or_i(Self::from_false(), self)
338 }
339
340 fn and_b(left: Self, right: Self) -> Result<Self, ErrorKind>;
342
343 fn and_v(left: Self, right: Self) -> Result<Self, ErrorKind>;
345
346 fn and_n(left: Self, right: Self) -> Result<Self, ErrorKind> {
348 Self::and_or(left, right, Self::from_false())
349 }
350
351 fn or_b(left: Self, right: Self) -> Result<Self, ErrorKind>;
353
354 fn or_d(left: Self, right: Self) -> Result<Self, ErrorKind>;
356
357 fn or_c(left: Self, right: Self) -> Result<Self, ErrorKind>;
359
360 fn or_i(left: Self, right: Self) -> Result<Self, ErrorKind>;
362
363 fn and_or(a: Self, b: Self, c: Self) -> Result<Self, ErrorKind>;
365
366 fn threshold<S>(k: usize, n: usize, sub_ck: S) -> Result<Self, ErrorKind>
368 where
369 S: FnMut(usize) -> Result<Self, ErrorKind>;
370
371 fn from_ext<E: Extension>(e: &E) -> Self;
375}
376
377impl Property for Type {
378 fn sanity_checks(&self) {
379 debug_assert!(!self.corr.dissatisfiable || self.mall.dissat != Dissat::None);
380 debug_assert!(self.mall.dissat == Dissat::None || self.corr.base != Base::V);
381 debug_assert!(self.mall.safe || self.corr.base != Base::K);
382 debug_assert!(self.mall.non_malleable || self.corr.input != Input::Zero);
383 }
384
385 fn from_true() -> Self {
386 Type {
387 corr: Property::from_true(),
388 mall: Property::from_true(),
389 }
390 }
391
392 fn from_false() -> Self {
393 Type {
394 corr: Property::from_false(),
395 mall: Property::from_false(),
396 }
397 }
398
399 fn from_pk_k<Ctx: ScriptContext>() -> Self {
400 Type {
401 corr: Property::from_pk_k::<Ctx>(),
402 mall: Property::from_pk_k::<Ctx>(),
403 }
404 }
405
406 fn from_pk_h<Ctx: ScriptContext>() -> Self {
407 Type {
408 corr: Property::from_pk_h::<Ctx>(),
409 mall: Property::from_pk_h::<Ctx>(),
410 }
411 }
412
413 fn from_multi(k: usize, n: usize) -> Self {
414 Type {
415 corr: Property::from_multi(k, n),
416 mall: Property::from_multi(k, n),
417 }
418 }
419
420 fn from_multi_a(k: usize, n: usize) -> Self {
421 Type {
422 corr: Property::from_multi_a(k, n),
423 mall: Property::from_multi_a(k, n),
424 }
425 }
426
427 fn from_hash() -> Self {
428 Type {
429 corr: Property::from_hash(),
430 mall: Property::from_hash(),
431 }
432 }
433
434 fn from_sha256() -> Self {
435 Type {
436 corr: Property::from_sha256(),
437 mall: Property::from_sha256(),
438 }
439 }
440
441 fn from_hash256() -> Self {
442 Type {
443 corr: Property::from_hash256(),
444 mall: Property::from_hash256(),
445 }
446 }
447
448 fn from_ripemd160() -> Self {
449 Type {
450 corr: Property::from_ripemd160(),
451 mall: Property::from_ripemd160(),
452 }
453 }
454
455 fn from_hash160() -> Self {
456 Type {
457 corr: Property::from_hash160(),
458 mall: Property::from_hash160(),
459 }
460 }
461
462 fn from_time(t: u32) -> Self {
463 Type {
464 corr: Property::from_time(t),
465 mall: Property::from_time(t),
466 }
467 }
468
469 fn from_after(t: LockTime) -> Self {
470 Type {
471 corr: Property::from_after(t),
472 mall: Property::from_after(t),
473 }
474 }
475
476 fn from_older(t: Sequence) -> Self {
477 Type {
478 corr: Property::from_older(t),
479 mall: Property::from_older(t),
480 }
481 }
482
483 fn cast_alt(self) -> Result<Self, ErrorKind> {
484 Ok(Type {
485 corr: Property::cast_alt(self.corr)?,
486 mall: Property::cast_alt(self.mall)?,
487 })
488 }
489
490 fn cast_swap(self) -> Result<Self, ErrorKind> {
491 Ok(Type {
492 corr: Property::cast_swap(self.corr)?,
493 mall: Property::cast_swap(self.mall)?,
494 })
495 }
496
497 fn cast_check(self) -> Result<Self, ErrorKind> {
498 Ok(Type {
499 corr: Property::cast_check(self.corr)?,
500 mall: Property::cast_check(self.mall)?,
501 })
502 }
503
504 fn cast_dupif(self) -> Result<Self, ErrorKind> {
505 Ok(Type {
506 corr: Property::cast_dupif(self.corr)?,
507 mall: Property::cast_dupif(self.mall)?,
508 })
509 }
510
511 fn cast_verify(self) -> Result<Self, ErrorKind> {
512 Ok(Type {
513 corr: Property::cast_verify(self.corr)?,
514 mall: Property::cast_verify(self.mall)?,
515 })
516 }
517
518 fn cast_nonzero(self) -> Result<Self, ErrorKind> {
519 Ok(Type {
520 corr: Property::cast_nonzero(self.corr)?,
521 mall: Property::cast_nonzero(self.mall)?,
522 })
523 }
524
525 fn cast_zeronotequal(self) -> Result<Self, ErrorKind> {
526 Ok(Type {
527 corr: Property::cast_zeronotequal(self.corr)?,
528 mall: Property::cast_zeronotequal(self.mall)?,
529 })
530 }
531
532 fn cast_true(self) -> Result<Self, ErrorKind> {
533 Ok(Type {
534 corr: Property::cast_true(self.corr)?,
535 mall: Property::cast_true(self.mall)?,
536 })
537 }
538
539 fn cast_or_i_false(self) -> Result<Self, ErrorKind> {
540 Ok(Type {
541 corr: Property::cast_or_i_false(self.corr)?,
542 mall: Property::cast_or_i_false(self.mall)?,
543 })
544 }
545
546 fn cast_unlikely(self) -> Result<Self, ErrorKind> {
547 Ok(Type {
548 corr: Property::cast_unlikely(self.corr)?,
549 mall: Property::cast_unlikely(self.mall)?,
550 })
551 }
552
553 fn cast_likely(self) -> Result<Self, ErrorKind> {
554 Ok(Type {
555 corr: Property::cast_likely(self.corr)?,
556 mall: Property::cast_likely(self.mall)?,
557 })
558 }
559
560 fn and_b(left: Self, right: Self) -> Result<Self, ErrorKind> {
561 Ok(Type {
562 corr: Property::and_b(left.corr, right.corr)?,
563 mall: Property::and_b(left.mall, right.mall)?,
564 })
565 }
566
567 fn and_v(left: Self, right: Self) -> Result<Self, ErrorKind> {
568 Ok(Type {
569 corr: Property::and_v(left.corr, right.corr)?,
570 mall: Property::and_v(left.mall, right.mall)?,
571 })
572 }
573
574 fn or_b(left: Self, right: Self) -> Result<Self, ErrorKind> {
575 Ok(Type {
576 corr: Property::or_b(left.corr, right.corr)?,
577 mall: Property::or_b(left.mall, right.mall)?,
578 })
579 }
580
581 fn or_d(left: Self, right: Self) -> Result<Self, ErrorKind> {
582 Ok(Type {
583 corr: Property::or_d(left.corr, right.corr)?,
584 mall: Property::or_d(left.mall, right.mall)?,
585 })
586 }
587
588 fn or_c(left: Self, right: Self) -> Result<Self, ErrorKind> {
589 Ok(Type {
590 corr: Property::or_c(left.corr, right.corr)?,
591 mall: Property::or_c(left.mall, right.mall)?,
592 })
593 }
594
595 fn or_i(left: Self, right: Self) -> Result<Self, ErrorKind> {
596 Ok(Type {
597 corr: Property::or_i(left.corr, right.corr)?,
598 mall: Property::or_i(left.mall, right.mall)?,
599 })
600 }
601
602 fn and_or(a: Self, b: Self, c: Self) -> Result<Self, ErrorKind> {
603 Ok(Type {
604 corr: Property::and_or(a.corr, b.corr, c.corr)?,
605 mall: Property::and_or(a.mall, b.mall, c.mall)?,
606 })
607 }
608
609 fn threshold<S>(k: usize, n: usize, mut sub_ck: S) -> Result<Self, ErrorKind>
610 where
611 S: FnMut(usize) -> Result<Self, ErrorKind>,
612 {
613 Ok(Type {
614 corr: Property::threshold(k, n, |n| Ok(sub_ck(n)?.corr))?,
615 mall: Property::threshold(k, n, |n| Ok(sub_ck(n)?.mall))?,
616 })
617 }
618
619 fn from_ext<E: Extension>(e: &E) -> Self {
620 Type {
621 corr: Property::from_ext(e),
622 mall: Property::from_ext(e),
623 }
624 }
625}
626impl Type {
627 pub fn type_check<Pk, Ctx, Ext>(
630 fragment: &Terminal<Pk, Ctx, Ext>,
631 ) -> Result<Self, Error<Pk, Ctx, Ext>>
632 where
633 Pk: MiniscriptKey,
634 Ctx: ScriptContext,
635 Ext: Extension,
636 {
637 let wrap_err = |result: Result<Self, ErrorKind>| {
638 result.map_err(|kind| Error {
639 fragment: fragment.clone(),
640 error: kind,
641 })
642 };
643
644 let ret = match *fragment {
645 Terminal::True => Ok(Self::from_true()),
646 Terminal::False => Ok(Self::from_false()),
647 Terminal::PkK(..) => Ok(Self::from_pk_k::<Ctx>()),
648 Terminal::PkH(..) | Terminal::RawPkH(..) => Ok(Self::from_pk_h::<Ctx>()),
649 Terminal::Multi(k, ref pks) | Terminal::MultiA(k, ref pks) => {
650 if k == 0 {
651 return Err(Error {
652 fragment: fragment.clone(),
653 error: ErrorKind::ZeroThreshold,
654 });
655 }
656 if k > pks.len() {
657 return Err(Error {
658 fragment: fragment.clone(),
659 error: ErrorKind::OverThreshold(k, pks.len()),
660 });
661 }
662 match *fragment {
663 Terminal::Multi(..) => Ok(Self::from_multi(k, pks.len())),
664 Terminal::MultiA(..) => Ok(Self::from_multi_a(k, pks.len())),
665 _ => unreachable!(),
666 }
667 }
668 Terminal::After(t) => {
669 if t == LockTime::ZERO.into() {
673 return Err(Error {
674 fragment: fragment.clone(),
675 error: ErrorKind::InvalidTime,
676 });
677 }
678 Ok(Self::from_after(t.into()))
679 }
680 Terminal::Older(t) => {
681 if t == Sequence::ZERO || !t.is_relative_lock_time() {
682 return Err(Error {
683 fragment: fragment.clone(),
684 error: ErrorKind::InvalidTime,
685 });
686 }
687 Ok(Self::from_older(t))
688 }
689 Terminal::Sha256(..) => Ok(Self::from_sha256()),
690 Terminal::Hash256(..) => Ok(Self::from_hash256()),
691 Terminal::Ripemd160(..) => Ok(Self::from_ripemd160()),
692 Terminal::Hash160(..) => Ok(Self::from_hash160()),
693 Terminal::Alt(ref sub) => wrap_err(Self::cast_alt(sub.ty)),
694 Terminal::Swap(ref sub) => wrap_err(Self::cast_swap(sub.ty)),
695 Terminal::Check(ref sub) => wrap_err(Self::cast_check(sub.ty)),
696 Terminal::DupIf(ref sub) => wrap_err(Self::cast_dupif(sub.ty)),
697 Terminal::Verify(ref sub) => wrap_err(Self::cast_verify(sub.ty)),
698 Terminal::NonZero(ref sub) => wrap_err(Self::cast_nonzero(sub.ty)),
699 Terminal::ZeroNotEqual(ref sub) => wrap_err(Self::cast_zeronotequal(sub.ty)),
700 Terminal::AndB(ref l, ref r) => {
701 let ltype = l.ty;
702 let rtype = r.ty;
703 wrap_err(Self::and_b(ltype, rtype))
704 }
705 Terminal::AndV(ref l, ref r) => {
706 let ltype = l.ty;
707 let rtype = r.ty;
708 wrap_err(Self::and_v(ltype, rtype))
709 }
710 Terminal::OrB(ref l, ref r) => {
711 let ltype = l.ty;
712 let rtype = r.ty;
713 wrap_err(Self::or_b(ltype, rtype))
714 }
715 Terminal::OrD(ref l, ref r) => {
716 let ltype = l.ty;
717 let rtype = r.ty;
718 wrap_err(Self::or_d(ltype, rtype))
719 }
720 Terminal::OrC(ref l, ref r) => {
721 let ltype = l.ty;
722 let rtype = r.ty;
723 wrap_err(Self::or_c(ltype, rtype))
724 }
725 Terminal::OrI(ref l, ref r) => {
726 let ltype = l.ty;
727 let rtype = r.ty;
728 wrap_err(Self::or_i(ltype, rtype))
729 }
730 Terminal::AndOr(ref a, ref b, ref c) => {
731 let atype = a.ty;
732 let btype = b.ty;
733 let ctype = c.ty;
734 wrap_err(Self::and_or(atype, btype, ctype))
735 }
736 Terminal::Thresh(k, ref subs) => {
737 if k == 0 {
738 return Err(Error {
739 fragment: fragment.clone(),
740 error: ErrorKind::ZeroThreshold,
741 });
742 }
743 if k > subs.len() {
744 return Err(Error {
745 fragment: fragment.clone(),
746 error: ErrorKind::OverThreshold(k, subs.len()),
747 });
748 }
749
750 let res = Self::threshold(k, subs.len(), |n| Ok(subs[n].ty));
751
752 res.map_err(|kind| Error {
753 fragment: fragment.clone(),
754 error: kind,
755 })
756 }
757 Terminal::Ext(ref e) => Ok(Self::from_ext(e)),
758 };
759 if let Ok(ref ret) = ret {
760 ret.sanity_checks()
761 }
762 ret
763 }
764}