miniscript_qtum/miniscript/types/
mod.rs

1// Written in 2019 by Andrew Poelstra <apoelstra@wpsoftware.net>
2// SPDX-License-Identifier: CC0-1.0
3
4//! Miniscript Types
5//! Contains structures representing Miniscript types and utility functions
6//! Contains all the type checking rules for correctness and malleability
7//! Implemented as per rules on bitcoin.sipa.be/miniscript
8pub 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
24/// None-returning function to help type inference when we need a
25/// closure that simply returns `None`
26fn return_none<T>(_: usize) -> Option<T> {
27    None
28}
29
30/// Detailed type of a typechecker error
31#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
32pub enum ErrorKind {
33    /// Relative or absolute timelock had an invalid time value (either 0, or >=0x80000000)
34    InvalidTime,
35    /// Passed a `z` argument to a `d` wrapper when `z` was expected
36    NonZeroDupIf,
37    /// Multisignature or threshold policy had a `k` value of 0
38    ZeroThreshold,
39    /// Multisignature or threshold policy has a `k` value in
40    /// excess of the number of subfragments
41    OverThreshold(usize, usize),
42    /// Attempted to construct a disjunction (or `andor`) for which
43    /// none of the child nodes were strong. This means that a 3rd
44    /// party could produce a satisfaction for any branch, meaning
45    /// that no matter which one an honest signer chooses, it is
46    /// possible to malleate the transaction.
47    NoStrongChild,
48    /// Many fragments (all disjunctions except `or_i` as well as
49    /// `andor` require their left child be dissatisfiable.
50    LeftNotDissatisfiable,
51    /// `or_b` requires its right child be dissatisfiable
52    RightNotDissatisfiable,
53    /// Tried to use the `s:` modifier on a fragment that takes more
54    /// than one input
55    SwapNonOne,
56    /// Tried to use the `j:` (`SIZE 0NOTEQUAL IF`) wrapper on something
57    /// that may be satisfied by a 0 input
58    NonZeroZero,
59    /// Many fragments require their left child to be a unit. This
60    /// was not the case.
61    LeftNotUnit,
62    /// Attempted to construct a wrapper, but the child had
63    /// an invalid type
64    ChildBase1(Base),
65    /// Attempted to construct a conjunction or disjunction, but
66    /// the fragments' children were of invalid types
67    ChildBase2(Base, Base),
68    /// Attempted to construct an `andor` but the fragments'
69    /// children were of invalid types
70    ChildBase3(Base, Base, Base),
71    /// The nth child of a threshold fragment had an invalid type (the
72    /// first must be `B` and the rest `W`s)
73    ThresholdBase(usize, Base),
74    /// The nth child of a threshold fragment did not have a unique
75    /// satisfaction
76    ThresholdDissat(usize),
77    /// The nth child of a threshold fragment was not a unit
78    ThresholdNonUnit(usize),
79    /// Insufficiently many children of a threshold fragment were strong
80    ThresholdNotStrong {
81        /// Threshold parameter
82        k: usize,
83        /// Number of children
84        n: usize,
85        /// Number of strong children
86        n_strong: usize,
87    },
88}
89
90/// Error type for typechecking
91#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
92pub struct Error<Pk: MiniscriptKey, Ctx: ScriptContext> {
93    /// The fragment that failed typecheck
94    pub fragment: Terminal<Pk, Ctx>,
95    /// The reason that typechecking failed
96    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/// Structure representing the type of a Miniscript fragment, including all
216/// properties relevant to the main codebase
217#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
218pub struct Type {
219    /// Correctness/soundness properties
220    pub corr: Correctness,
221    /// Malleability properties
222    pub mall: Malleability,
223}
224
225impl Type {
226    /// Check whether the `self` is a subtype of `other` argument .
227    /// This checks whether the argument `other` has attributes which are present
228    /// in the given `Type`. This returns `true` on same arguments
229    /// `a.is_subtype(a)` is `true`.
230    pub fn is_subtype(&self, other: Self) -> bool {
231        self.corr.is_subtype(other.corr) && self.mall.is_subtype(other.mall)
232    }
233}
234/// Trait representing a type property, which defines how the property
235/// propagates from terminals to the root of a Miniscript
236pub trait Property: Sized {
237    /// Any extra sanity checks/assertions that should be applied after
238    /// typechecking
239    fn sanity_checks(&self) {
240        // no checks by default
241    }
242
243    /// Type property of the `True` fragment
244    fn from_true() -> Self;
245
246    /// Type property of the `False` fragment
247    fn from_false() -> Self;
248
249    /// Type property of the `PkK` fragment
250    fn from_pk_k<Ctx: ScriptContext>() -> Self;
251
252    /// Type property of the `PkH` fragment
253    fn from_pk_h<Ctx: ScriptContext>() -> Self;
254
255    /// Type property of a `Multi` fragment
256    fn from_multi(k: usize, n: usize) -> Self;
257
258    /// Type property of a `MultiA` fragment
259    fn from_multi_a(k: usize, n: usize) -> Self;
260
261    /// Type property of a hash fragment
262    fn from_hash() -> Self;
263
264    /// Type property of a `Sha256` hash. Default implementation simply
265    /// passes through to `from_hash`
266    fn from_sha256() -> Self {
267        Self::from_hash()
268    }
269
270    /// Type property of a `Hash256` hash. Default implementation simply
271    /// passes through to `from_hash`
272    fn from_hash256() -> Self {
273        Self::from_hash()
274    }
275
276    /// Type property of a `Ripemd160` hash. Default implementation simply
277    /// passes through to `from_hash`
278    fn from_ripemd160() -> Self {
279        Self::from_hash()
280    }
281
282    /// Type property of a `Hash160` hash. Default implementation simply
283    /// passes through to `from_hash`
284    fn from_hash160() -> Self {
285        Self::from_hash()
286    }
287
288    /// Type property of a timelock
289    fn from_time(t: u32) -> Self;
290
291    /// Type property of an absolute timelock. Default implementation simply
292    /// passes through to `from_time`
293    fn from_after(t: absolute::LockTime) -> Self {
294        Self::from_time(t.to_consensus_u32())
295    }
296
297    /// Type property of a relative timelock. Default implementation simply
298    /// passes through to `from_time`
299    fn from_older(t: Sequence) -> Self {
300        Self::from_time(t.to_consensus_u32())
301    }
302
303    /// Cast using the `Alt` wrapper
304    fn cast_alt(self) -> Result<Self, ErrorKind>;
305
306    /// Cast using the `Swap` wrapper
307    fn cast_swap(self) -> Result<Self, ErrorKind>;
308
309    /// Cast using the `Check` wrapper
310    fn cast_check(self) -> Result<Self, ErrorKind>;
311
312    /// Cast using the `DupIf` wrapper
313    fn cast_dupif(self) -> Result<Self, ErrorKind>;
314
315    /// Cast using the `Verify` wrapper
316    fn cast_verify(self) -> Result<Self, ErrorKind>;
317
318    /// Cast using the `NonZero` wrapper
319    fn cast_nonzero(self) -> Result<Self, ErrorKind>;
320
321    /// Cast using the `ZeroNotEqual` wrapper
322    fn cast_zeronotequal(self) -> Result<Self, ErrorKind>;
323
324    /// Cast by changing `[X]` to `AndV([X], True)`
325    fn cast_true(self) -> Result<Self, ErrorKind> {
326        Self::and_v(self, Self::from_true())
327    }
328
329    /// Cast by changing `[X]` to `or_i([X], 0)` or `or_i(0, [X])`
330    fn cast_or_i_false(self) -> Result<Self, ErrorKind>;
331
332    /// Cast by changing `[X]` to `or_i([X], 0)`. Default implementation
333    /// simply passes through to `cast_or_i_false`
334    fn cast_unlikely(self) -> Result<Self, ErrorKind> {
335        Self::or_i(self, Self::from_false())
336    }
337
338    /// Cast by changing `[X]` to `or_i(0, [X])`. Default implementation
339    /// simply passes through to `cast_or_i_false`
340    fn cast_likely(self) -> Result<Self, ErrorKind> {
341        Self::or_i(Self::from_false(), self)
342    }
343
344    /// Computes the type of an `AndB` fragment
345    fn and_b(left: Self, right: Self) -> Result<Self, ErrorKind>;
346
347    /// Computes the type of an `AndV` fragment
348    fn and_v(left: Self, right: Self) -> Result<Self, ErrorKind>;
349
350    /// Computes the type of an `AndN` fragment
351    fn and_n(left: Self, right: Self) -> Result<Self, ErrorKind> {
352        Self::and_or(left, right, Self::from_false())
353    }
354
355    /// Computes the type of an `OrB` fragment
356    fn or_b(left: Self, right: Self) -> Result<Self, ErrorKind>;
357
358    /// Computes the type of an `OrD` fragment
359    fn or_d(left: Self, right: Self) -> Result<Self, ErrorKind>;
360
361    /// Computes the type of an `OrC` fragment
362    fn or_c(left: Self, right: Self) -> Result<Self, ErrorKind>;
363
364    /// Computes the type of an `OrI` fragment
365    fn or_i(left: Self, right: Self) -> Result<Self, ErrorKind>;
366
367    /// Computes the type of an `AndOr` fragment
368    fn and_or(a: Self, b: Self, c: Self) -> Result<Self, ErrorKind>;
369
370    /// Computes the type of an `Thresh` fragment
371    fn threshold<S>(k: usize, n: usize, sub_ck: S) -> Result<Self, ErrorKind>
372    where
373        S: FnMut(usize) -> Result<Self, ErrorKind>;
374
375    /// Compute the type of a fragment, given a function to look up
376    /// the types of its children, if available and relevant for the
377    /// given fragment
378    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                // Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The
425                // number on the stack would be a 5 bytes signed integer but Miniscript's B type
426                // only consumes 4 bytes from the stack.
427                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    /// Compute the type of a fragment assuming all the children of
772    /// Miniscript have been computed already.
773    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                // Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The
815                // number on the stack would be a 5 bytes signed integer but Miniscript's B type
816                // only consumes 4 bytes from the stack.
817                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}