sapio_miniscript/
lib.rs

1// Miniscript
2// Written in 2019 by
3//     Andrew Poelstra <apoelstra@wpsoftware.net>
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15//! Miniscript and Output Descriptors
16//!
17//! # Introduction
18//! ## Bitcoin Script
19//!
20//! In Bitcoin, spending policies are defined and enforced by means of a
21//! stack-based programming language known as Bitcoin Script. While this
22//! language appears to be designed with tractable analysis in mind (e.g.
23//! there are no looping or jumping constructions), in practice this is
24//! extremely difficult. As a result, typical wallet software supports only
25//! a small set of script templates, cannot interoperate with other similar
26//! software, and each wallet contains independently written ad-hoc manually
27//! verified code to handle these templates. Users who require more complex
28//! spending policies, or who want to combine signing infrastructure which
29//! was not explicitly designed to work together, are simply out of luck.
30//!
31//! ## Miniscript
32//!
33//! Miniscript is an alternative to Bitcoin Script which eliminates these
34//! problems. It can be efficiently and simply encoded as Script to ensure
35//! that it works on the Bitcoin blockchain, but its design is very different.
36//! Essentially, a Miniscript is a monotone function (tree of ANDs, ORs and
37//! thresholds) of signature requirements, hash preimage requirements, and
38//! timelocks.
39//!
40//! A [full description of Miniscript is available here](http://bitcoin.sipa.be/miniscript/miniscript.html).
41//!
42//! Miniscript also admits a more human-readable encoding.
43//!
44//! ## Output Descriptors
45//!
46//! While spending policies in Bitcoin are entirely defined by Script; there
47//! are multiple ways of embedding these Scripts in transaction outputs; for
48//! example, P2SH or Segwit v0. These different embeddings are expressed by
49//! *Output Descriptors*, [which are described here](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md)
50//!
51//! # Examples
52//!
53//! ## Deriving an address from a descriptor
54//!
55//! ```rust
56//! extern crate bitcoin;
57//! extern crate sapio_miniscript as miniscript;
58//!
59//! use std::str::FromStr;
60//! use miniscript::{DescriptorTrait};
61//!
62//! fn main() {
63//!     let desc = miniscript::Descriptor::<
64//!         bitcoin::PublicKey,
65//!     >::from_str("\
66//!         sh(wsh(or_d(\
67//!             c:pk_k(020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b67817261),\
68//!             c:pk_k(0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352)\
69//!         )))\
70//!     ").unwrap();
71//!
72//!     // Derive the P2SH address
73//!     assert_eq!(
74//!         desc.address(bitcoin::Network::Bitcoin).unwrap().to_string(),
75//!         "3CJxbQBfWAe1ZkKiGQNEYrioV73ZwvBWns"
76//!     );
77//!
78//!     // Check whether the descriptor is safe
79//!     // This checks whether all spend paths are accessible in bitcoin network.
80//!     // It maybe possible that some of the spend require more than 100 elements in Wsh scripts
81//!     // Or they contain a combination of timelock and heightlock.
82//!     assert!(desc.sanity_check().is_ok());
83//!
84//!     // Estimate the satisfaction cost
85//!     assert_eq!(desc.max_satisfaction_weight().unwrap(), 293);
86//! }
87//! ```
88//!
89//!
90#![cfg_attr(all(test, feature = "unstable"), feature(test))]
91// Coding conventions
92#![deny(unsafe_code)]
93#![deny(non_upper_case_globals)]
94#![deny(non_camel_case_types)]
95#![deny(non_snake_case)]
96#![deny(unused_mut)]
97#![deny(dead_code)]
98#![deny(unused_imports)]
99#![deny(missing_docs)]
100
101pub extern crate bitcoin;
102#[cfg(feature = "schemars")]
103pub extern crate schemars;
104#[cfg(feature = "serde")]
105pub extern crate serde;
106#[cfg(all(test, feature = "unstable"))]
107extern crate test;
108
109#[macro_use]
110mod macros;
111
112pub mod descriptor;
113pub mod expression;
114pub mod interpreter;
115pub mod miniscript;
116pub mod policy;
117pub mod psbt;
118
119mod util;
120
121use std::io::Write;
122use std::str::FromStr;
123use std::{error, fmt, hash, str};
124
125use bitcoin::blockdata::{opcodes, script};
126use bitcoin::hashes::{hash160, sha256, Hash};
127
128pub use descriptor::{Descriptor, DescriptorPublicKey, DescriptorTrait};
129pub use interpreter::Interpreter;
130pub use miniscript::context::{BareCtx, Legacy, ScriptContext, Segwitv0, Tap};
131pub use miniscript::decode::Terminal;
132pub use miniscript::satisfy::{Preimage32, Satisfier};
133pub use miniscript::Miniscript;
134
135pub use descriptor::pretaproot::{traits::PreTaprootDescriptorTrait, PreTaprootDescriptor};
136
137///Public key trait which can be converted to Hash type
138pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
139    /// Check if the publicKey is uncompressed. The default
140    /// implementation returns false
141    fn is_uncompressed(&self) -> bool {
142        false
143    }
144
145    /// Check if the publicKey is x-only. The default
146    /// implementation returns false
147    //
148    // This is required to know what in DescriptorPublicKey to know whether the inner
149    // key in allowed in descriptor context
150    fn is_x_only_key(&self) -> bool {
151        false
152    }
153
154    /// The associated Hash type with the publicKey
155    type Hash: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
156
157    /// Converts an object to PublicHash
158    fn to_pubkeyhash(&self) -> Self::Hash;
159}
160
161impl MiniscriptKey for bitcoin::secp256k1::PublicKey {
162    /// `is_uncompressed` always returns `false`
163    fn is_uncompressed(&self) -> bool {
164        false
165    }
166
167    type Hash = hash160::Hash;
168
169    fn to_pubkeyhash(&self) -> Self::Hash {
170        let mut engine = hash160::Hash::engine();
171        engine
172            .write_all(&self.serialize())
173            .expect("engines don't error");
174        hash160::Hash::from_engine(engine)
175    }
176}
177
178impl MiniscriptKey for bitcoin::PublicKey {
179    /// `is_uncompressed` returns true only for
180    /// bitcoin::Publickey type if the underlying key is uncompressed.
181    fn is_uncompressed(&self) -> bool {
182        !self.compressed
183    }
184
185    type Hash = hash160::Hash;
186
187    fn to_pubkeyhash(&self) -> Self::Hash {
188        let mut engine = hash160::Hash::engine();
189        self.write_into(&mut engine).expect("engines don't error");
190        hash160::Hash::from_engine(engine)
191    }
192}
193
194impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
195    type Hash = hash160::Hash;
196
197    fn to_pubkeyhash(&self) -> Self::Hash {
198        hash160::Hash::hash(&self.serialize())
199    }
200
201    fn is_x_only_key(&self) -> bool {
202        true
203    }
204}
205
206impl MiniscriptKey for String {
207    type Hash = String;
208
209    fn to_pubkeyhash(&self) -> Self::Hash {
210        format!("{}", &self)
211    }
212}
213
214/// Trait describing public key types which can be converted to bitcoin pubkeys
215pub trait ToPublicKey: MiniscriptKey {
216    /// Converts an object to a public key
217    fn to_public_key(&self) -> bitcoin::PublicKey;
218
219    /// Convert an object to x-only pubkey
220    fn to_x_only_pubkey(&self) -> bitcoin::secp256k1::XOnlyPublicKey {
221        let pk = self.to_public_key();
222        bitcoin::secp256k1::XOnlyPublicKey::from(pk.inner)
223    }
224
225    /// Converts a hashed version of the public key to a `hash160` hash.
226    ///
227    /// This method must be consistent with `to_public_key`, in the sense
228    /// that calling `MiniscriptKey::to_pubkeyhash` followed by this function
229    /// should give the same result as calling `to_public_key` and hashing
230    /// the result directly.
231    fn hash_to_hash160(hash: &<Self as MiniscriptKey>::Hash) -> hash160::Hash;
232}
233
234impl ToPublicKey for bitcoin::PublicKey {
235    fn to_public_key(&self) -> bitcoin::PublicKey {
236        *self
237    }
238
239    fn hash_to_hash160(hash: &hash160::Hash) -> hash160::Hash {
240        *hash
241    }
242}
243
244impl ToPublicKey for bitcoin::secp256k1::PublicKey {
245    fn to_public_key(&self) -> bitcoin::PublicKey {
246        bitcoin::PublicKey::new(*self)
247    }
248
249    fn hash_to_hash160(hash: &hash160::Hash) -> hash160::Hash {
250        *hash
251    }
252}
253
254impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
255    fn to_public_key(&self) -> bitcoin::PublicKey {
256        // This code should never be used.
257        // But is implemented for completeness
258        let mut data: Vec<u8> = vec![0x02];
259        data.extend(self.serialize().iter());
260        bitcoin::PublicKey::from_slice(&data)
261            .expect("Failed to construct 33 Publickey from 0x02 appended x-only key")
262    }
263
264    fn to_x_only_pubkey(&self) -> bitcoin::secp256k1::XOnlyPublicKey {
265        *self
266    }
267
268    fn hash_to_hash160(hash: &hash160::Hash) -> hash160::Hash {
269        *hash
270    }
271}
272
273/// Dummy key which de/serializes to the empty string; useful sometimes for testing
274#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
275pub struct DummyKey;
276
277impl str::FromStr for DummyKey {
278    type Err = &'static str;
279    fn from_str(x: &str) -> Result<DummyKey, &'static str> {
280        if x.is_empty() {
281            Ok(DummyKey)
282        } else {
283            Err("non empty dummy key")
284        }
285    }
286}
287
288impl MiniscriptKey for DummyKey {
289    type Hash = DummyKeyHash;
290
291    fn to_pubkeyhash(&self) -> Self::Hash {
292        DummyKeyHash
293    }
294}
295
296impl hash::Hash for DummyKey {
297    fn hash<H: hash::Hasher>(&self, state: &mut H) {
298        "DummyKey".hash(state);
299    }
300}
301
302impl fmt::Display for DummyKey {
303    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
304        f.write_str("")
305    }
306}
307
308impl ToPublicKey for DummyKey {
309    fn to_public_key(&self) -> bitcoin::PublicKey {
310        bitcoin::PublicKey::from_str(
311            "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352",
312        )
313        .unwrap()
314    }
315
316    fn hash_to_hash160(_: &DummyKeyHash) -> hash160::Hash {
317        hash160::Hash::from_str("f54a5851e9372b87810a8e60cdd2e7cfd80b6e31").unwrap()
318    }
319}
320
321/// Dummy keyhash which de/serializes to the empty string; useful sometimes for testing
322#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
323pub struct DummyKeyHash;
324
325impl str::FromStr for DummyKeyHash {
326    type Err = &'static str;
327    fn from_str(x: &str) -> Result<DummyKeyHash, &'static str> {
328        if x.is_empty() {
329            Ok(DummyKeyHash)
330        } else {
331            Err("non empty dummy key")
332        }
333    }
334}
335
336impl fmt::Display for DummyKeyHash {
337    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338        f.write_str("")
339    }
340}
341
342impl hash::Hash for DummyKeyHash {
343    fn hash<H: hash::Hasher>(&self, state: &mut H) {
344        "DummyKeyHash".hash(state);
345    }
346}
347
348/// Convert a descriptor using abstract keys to one using specific keys
349/// This will panic if translatefpk returns an uncompressed key when
350/// converting to a Segwit descriptor. To prevent this panic, ensure
351/// translatefpk returns an error in this case instead.
352pub trait TranslatePk<P: MiniscriptKey, Q: MiniscriptKey> {
353    /// The associated output type. This must be Self<Q>
354    type Output;
355
356    /// Translate a struct from one Generic to another where the
357    /// translation for Pk is provided by translatefpk, and translation for
358    /// PkH is provided by translatefpkh
359    fn translate_pk<Fpk, Fpkh, E>(
360        &self,
361        translatefpk: Fpk,
362        translatefpkh: Fpkh,
363    ) -> Result<Self::Output, E>
364    where
365        Fpk: FnMut(&P) -> Result<Q, E>,
366        Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>;
367
368    /// Calls `translate_pk` with conversion functions that cannot fail
369    fn translate_pk_infallible<Fpk, Fpkh>(
370        &self,
371        mut translatefpk: Fpk,
372        mut translatefpkh: Fpkh,
373    ) -> Self::Output
374    where
375        Fpk: FnMut(&P) -> Q,
376        Fpkh: FnMut(&P::Hash) -> Q::Hash,
377    {
378        self.translate_pk::<_, _, ()>(|pk| Ok(translatefpk(pk)), |pkh| Ok(translatefpkh(pkh)))
379            .expect("infallible translation function")
380    }
381}
382
383/// Variant of `TranslatePk` where P and Q both have the same hash
384/// type, and the hashes can be converted by just cloning them
385pub trait TranslatePk1<P: MiniscriptKey, Q: MiniscriptKey<Hash = P::Hash>>:
386    TranslatePk<P, Q>
387{
388    /// Translate a struct from one generic to another where the
389    /// translation for Pk is provided by translatefpk
390    fn translate_pk1<Fpk, E>(
391        &self,
392        translatefpk: Fpk,
393    ) -> Result<<Self as TranslatePk<P, Q>>::Output, E>
394    where
395        Fpk: FnMut(&P) -> Result<Q, E>,
396    {
397        self.translate_pk(translatefpk, |h| Ok(h.clone()))
398    }
399
400    /// Translate a struct from one generic to another where the
401    /// translation for Pk is provided by translatefpk
402    fn translate_pk1_infallible<Fpk: FnMut(&P) -> Q>(
403        &self,
404        translatefpk: Fpk,
405    ) -> <Self as TranslatePk<P, Q>>::Output {
406        self.translate_pk_infallible(translatefpk, P::Hash::clone)
407    }
408}
409impl<P: MiniscriptKey, Q: MiniscriptKey<Hash = P::Hash>, T: TranslatePk<P, Q>> TranslatePk1<P, Q>
410    for T
411{
412}
413
414/// Variant of `TranslatePk` where P's hash is P, so the hashes
415/// can be converted by reusing the key-conversion function
416pub trait TranslatePk2<P: MiniscriptKey<Hash = P>, Q: MiniscriptKey>: TranslatePk<P, Q> {
417    /// Translate a struct from one generic to another where the
418    /// translation for Pk is provided by translatefpk
419    fn translate_pk2<Fpk: Fn(&P) -> Result<Q, E>, E>(
420        &self,
421        translatefpk: Fpk,
422    ) -> Result<<Self as TranslatePk<P, Q>>::Output, E> {
423        self.translate_pk(&translatefpk, |h| {
424            translatefpk(h).map(|q| q.to_pubkeyhash())
425        })
426    }
427
428    /// Translate a struct from one generic to another where the
429    /// translation for Pk is provided by translatefpk
430    fn translate_pk2_infallible<Fpk: Fn(&P) -> Q>(
431        &self,
432        translatefpk: Fpk,
433    ) -> <Self as TranslatePk<P, Q>>::Output {
434        self.translate_pk_infallible(&translatefpk, |h| translatefpk(h).to_pubkeyhash())
435    }
436}
437impl<P: MiniscriptKey<Hash = P>, Q: MiniscriptKey, T: TranslatePk<P, Q>> TranslatePk2<P, Q> for T {}
438
439/// Variant of `TranslatePk` where Q's hash is `hash160` so we can
440/// derive hashes by calling `hash_to_hash160`
441pub trait TranslatePk3<P: MiniscriptKey + ToPublicKey, Q: MiniscriptKey<Hash = hash160::Hash>>:
442    TranslatePk<P, Q>
443{
444    /// Translate a struct from one generic to another where the
445    /// translation for Pk is provided by translatefpk
446    fn translate_pk3<Fpk, E>(
447        &self,
448        translatefpk: Fpk,
449    ) -> Result<<Self as TranslatePk<P, Q>>::Output, E>
450    where
451        Fpk: FnMut(&P) -> Result<Q, E>,
452    {
453        self.translate_pk(translatefpk, |h| Ok(P::hash_to_hash160(h)))
454    }
455
456    /// Translate a struct from one generic to another where the
457    /// translation for Pk is provided by translatefpk
458    fn translate_pk3_infallible<Fpk: FnMut(&P) -> Q>(
459        &self,
460        translatefpk: Fpk,
461    ) -> <Self as TranslatePk<P, Q>>::Output {
462        self.translate_pk_infallible(translatefpk, P::hash_to_hash160)
463    }
464}
465impl<
466        P: MiniscriptKey + ToPublicKey,
467        Q: MiniscriptKey<Hash = hash160::Hash>,
468        T: TranslatePk<P, Q>,
469    > TranslatePk3<P, Q> for T
470{
471}
472
473/// Either a key or a keyhash
474pub enum ForEach<'a, Pk: MiniscriptKey + 'a> {
475    /// A key
476    Key(&'a Pk),
477    /// A keyhash
478    Hash(&'a Pk::Hash),
479}
480
481impl<'a, Pk: MiniscriptKey<Hash = Pk>> ForEach<'a, Pk> {
482    /// Convenience method to avoid distinguishing between keys and hashes when these are the same type
483    pub fn as_key(&self) -> &'a Pk {
484        match *self {
485            ForEach::Key(ref_key) => ref_key,
486            ForEach::Hash(ref_key) => ref_key,
487        }
488    }
489}
490
491/// Trait describing the ability to iterate over every key
492pub trait ForEachKey<Pk: MiniscriptKey> {
493    /// Run a predicate on every key in the descriptor, returning whether
494    /// the predicate returned true for every key
495    fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, pred: F) -> bool
496    where
497        Pk: 'a,
498        Pk::Hash: 'a;
499
500    /// Run a predicate on every key in the descriptor, returning whether
501    /// the predicate returned true for any key
502    fn for_any_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, mut pred: F) -> bool
503    where
504        Pk: 'a,
505        Pk::Hash: 'a,
506    {
507        !self.for_each_key(|key| !pred(key))
508    }
509}
510
511/// Miniscript
512
513#[derive(Debug)]
514pub enum Error {
515    /// Opcode appeared which is not part of the script subset
516    InvalidOpcode(opcodes::All),
517    /// Some opcode occurred followed by `OP_VERIFY` when it had
518    /// a `VERIFY` version that should have been used instead
519    NonMinimalVerify(String),
520    /// Push was illegal in some context
521    InvalidPush(Vec<u8>),
522    /// rust-bitcoin script error
523    Script(script::Error),
524    /// rust-bitcoin address error
525    AddrError(bitcoin::util::address::Error),
526    /// A `CHECKMULTISIG` opcode was preceded by a number > 20
527    CmsTooManyKeys(u32),
528    /// A tapscript multi_a cannot support more than MAX_BLOCK_WEIGHT/32 keys
529    MultiATooManyKeys(u32),
530    /// Encountered unprintable character in descriptor
531    Unprintable(u8),
532    /// expected character while parsing descriptor; didn't find one
533    ExpectedChar(char),
534    /// While parsing backward, hit beginning of script
535    UnexpectedStart,
536    /// Got something we were not expecting
537    Unexpected(String),
538    /// Name of a fragment contained `:` multiple times
539    MultiColon(String),
540    /// Name of a fragment contained `@` multiple times
541    MultiAt(String),
542    /// Name of a fragment contained `@` but we were not parsing an OR
543    AtOutsideOr(String),
544    /// Encountered a `l:0` which is syntactically equal to `u:0` except stupid
545    LikelyFalse,
546    /// Encountered a wrapping character that we don't recognize
547    UnknownWrapper(char),
548    /// Parsed a miniscript and the result was not of type T
549    NonTopLevel(String),
550    /// Parsed a miniscript but there were more script opcodes after it
551    Trailing(String),
552    /// Failed to parse a push as a public key
553    BadPubkey(bitcoin::util::key::Error),
554    /// Could not satisfy a script (fragment) because of a missing hash preimage
555    MissingHash(sha256::Hash),
556    /// Could not satisfy a script (fragment) because of a missing signature
557    MissingSig(bitcoin::PublicKey),
558    /// Could not satisfy, relative locktime not met
559    RelativeLocktimeNotMet(u32),
560    /// Could not satisfy, absolute locktime not met
561    AbsoluteLocktimeNotMet(u32),
562    /// General failure to satisfy
563    CouldNotSatisfy,
564    /// Typechecking failed
565    TypeCheck(String),
566    /// General error in creating descriptor
567    BadDescriptor(String),
568    /// Forward-secp related errors
569    Secp(bitcoin::secp256k1::Error),
570    #[cfg(feature = "compiler")]
571    /// Compiler related errors
572    CompilerError(policy::compiler::CompilerError),
573    /// Errors related to policy
574    PolicyError(policy::concrete::PolicyError),
575    /// Errors related to lifting
576    LiftError(policy::LiftError),
577    /// Forward script context related errors
578    ContextError(miniscript::context::ScriptContextError),
579    /// Recursion depth exceeded when parsing policy/miniscript from string
580    MaxRecursiveDepthExceeded,
581    /// Script size too large
582    ScriptSizeTooLarge,
583    /// Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...)
584    /// up to n=3 is invalid by standardness (bare)
585    NonStandardBareScript,
586    /// Analysis Error
587    AnalysisError(miniscript::analyzable::AnalysisError),
588    /// Miniscript is equivalent to false. No possible satisfaction
589    ImpossibleSatisfaction,
590    /// Bare descriptors don't have any addresses
591    BareDescriptorAddr,
592    /// PubKey invalid under current context
593    PubKeyCtxError(miniscript::decode::KeyParseError, &'static str),
594    /// Attempted to call function that requires PreComputed taproot info
595    TaprootSpendInfoUnavialable,
596    /// No script code for Tr descriptors
597    TrNoScriptCode,
598    /// No explicit script for Tr descriptors
599    TrNoExplicitScript,
600}
601
602#[doc(hidden)]
603impl<Pk, Ctx> From<miniscript::types::Error<Pk, Ctx>> for Error
604where
605    Pk: MiniscriptKey,
606    Ctx: ScriptContext,
607{
608    fn from(e: miniscript::types::Error<Pk, Ctx>) -> Error {
609        Error::TypeCheck(e.to_string())
610    }
611}
612
613#[doc(hidden)]
614impl From<policy::LiftError> for Error {
615    fn from(e: policy::LiftError) -> Error {
616        Error::LiftError(e)
617    }
618}
619
620#[doc(hidden)]
621impl From<miniscript::context::ScriptContextError> for Error {
622    fn from(e: miniscript::context::ScriptContextError) -> Error {
623        Error::ContextError(e)
624    }
625}
626
627#[doc(hidden)]
628impl From<miniscript::analyzable::AnalysisError> for Error {
629    fn from(e: miniscript::analyzable::AnalysisError) -> Error {
630        Error::AnalysisError(e)
631    }
632}
633
634#[doc(hidden)]
635impl From<bitcoin::secp256k1::Error> for Error {
636    fn from(e: bitcoin::secp256k1::Error) -> Error {
637        Error::Secp(e)
638    }
639}
640
641#[doc(hidden)]
642impl From<bitcoin::util::address::Error> for Error {
643    fn from(e: bitcoin::util::address::Error) -> Error {
644        Error::AddrError(e)
645    }
646}
647
648fn errstr(s: &str) -> Error {
649    Error::Unexpected(s.to_owned())
650}
651
652impl error::Error for Error {
653    fn cause(&self) -> Option<&dyn error::Error> {
654        match *self {
655            Error::BadPubkey(ref e) => Some(e),
656            _ => None,
657        }
658    }
659}
660
661// https://github.com/sipa/miniscript/pull/5 for discussion on this number
662const MAX_RECURSION_DEPTH: u32 = 402;
663// https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki
664const MAX_SCRIPT_SIZE: u32 = 10000;
665
666impl fmt::Display for Error {
667    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
668        match *self {
669            Error::InvalidOpcode(op) => write!(f, "invalid opcode {}", op),
670            Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok),
671            Error::InvalidPush(ref push) => write!(f, "invalid push {:?}", push), // TODO hexify this
672            Error::Script(ref e) => fmt::Display::fmt(e, f),
673            Error::AddrError(ref e) => fmt::Display::fmt(e, f),
674            Error::CmsTooManyKeys(n) => write!(f, "checkmultisig with {} keys", n),
675            Error::Unprintable(x) => write!(f, "unprintable character 0x{:02x}", x),
676            Error::ExpectedChar(c) => write!(f, "expected {}", c),
677            Error::UnexpectedStart => f.write_str("unexpected start of script"),
678            Error::Unexpected(ref s) => write!(f, "unexpected «{}»", s),
679            Error::MultiColon(ref s) => write!(f, "«{}» has multiple instances of «:»", s),
680            Error::MultiAt(ref s) => write!(f, "«{}» has multiple instances of «@»", s),
681            Error::AtOutsideOr(ref s) => write!(f, "«{}» contains «@» in non-or() context", s),
682            Error::LikelyFalse => write!(f, "0 is not very likely (use «u:0»)"),
683            Error::UnknownWrapper(ch) => write!(f, "unknown wrapper «{}:»", ch),
684            Error::NonTopLevel(ref s) => write!(f, "non-T miniscript: {}", s),
685            Error::Trailing(ref s) => write!(f, "trailing tokens: {}", s),
686            Error::MissingHash(ref h) => write!(f, "missing preimage of hash {}", h),
687            Error::MissingSig(ref pk) => write!(f, "missing signature for key {:?}", pk),
688            Error::RelativeLocktimeNotMet(n) => {
689                write!(f, "required relative locktime CSV of {} blocks, not met", n)
690            }
691            Error::AbsoluteLocktimeNotMet(n) => write!(
692                f,
693                "required absolute locktime CLTV of {} blocks, not met",
694                n
695            ),
696            Error::CouldNotSatisfy => f.write_str("could not satisfy"),
697            Error::BadPubkey(ref e) => fmt::Display::fmt(e, f),
698            Error::TypeCheck(ref e) => write!(f, "typecheck: {}", e),
699            Error::BadDescriptor(ref e) => write!(f, "Invalid descriptor: {}", e),
700            Error::Secp(ref e) => fmt::Display::fmt(e, f),
701            Error::ContextError(ref e) => fmt::Display::fmt(e, f),
702            #[cfg(feature = "compiler")]
703            Error::CompilerError(ref e) => fmt::Display::fmt(e, f),
704            Error::PolicyError(ref e) => fmt::Display::fmt(e, f),
705            Error::LiftError(ref e) => fmt::Display::fmt(e, f),
706            Error::MaxRecursiveDepthExceeded => write!(
707                f,
708                "Recursive depth over {} not permitted",
709                MAX_RECURSION_DEPTH
710            ),
711            Error::ScriptSizeTooLarge => write!(
712                f,
713                "Standardness rules imply bitcoin than {} bytes",
714                MAX_SCRIPT_SIZE
715            ),
716            Error::NonStandardBareScript => write!(
717                f,
718                "Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) \
719                up to n=3 is invalid by standardness (bare).
720                "
721            ),
722            Error::AnalysisError(ref e) => e.fmt(f),
723            Error::ImpossibleSatisfaction => write!(f, "Impossible to satisfy Miniscript"),
724            Error::BareDescriptorAddr => write!(f, "Bare descriptors don't have address"),
725            Error::PubKeyCtxError(ref pk, ref ctx) => {
726                write!(f, "Pubkey error: {} under {} scriptcontext", pk, ctx)
727            }
728            Error::MultiATooManyKeys(k) => {
729                write!(f, "MultiA too many keys {}", k)
730            }
731            Error::TaprootSpendInfoUnavialable => {
732                write!(f, "Taproot Spend Info not computed. Hint: Did you call `compute_spend_info` before calling methods from DescriptorTrait")
733            }
734            Error::TrNoScriptCode => {
735                write!(f, "No script code for Tr descriptors")
736            }
737            Error::TrNoExplicitScript => {
738                write!(f, "No script code for Tr descriptors")
739            }
740        }
741    }
742}
743
744#[doc(hidden)]
745#[cfg(feature = "compiler")]
746impl From<policy::compiler::CompilerError> for Error {
747    fn from(e: policy::compiler::CompilerError) -> Error {
748        Error::CompilerError(e)
749    }
750}
751
752#[doc(hidden)]
753impl From<policy::concrete::PolicyError> for Error {
754    fn from(e: policy::concrete::PolicyError) -> Error {
755        Error::PolicyError(e)
756    }
757}
758
759/// The size of an encoding of a number in Script
760pub fn script_num_size(n: usize) -> usize {
761    match n {
762        n if n <= 0x10 => 1,      // OP_n
763        n if n < 0x80 => 2,       // OP_PUSH1 <n>
764        n if n < 0x8000 => 3,     // OP_PUSH2 <n>
765        n if n < 0x800000 => 4,   // OP_PUSH3 <n>
766        n if n < 0x80000000 => 5, // OP_PUSH4 <n>
767        _ => 6,                   // OP_PUSH5 <n>
768    }
769}
770
771/// Returns the size of the smallest push opcode used to push a given number of bytes onto the stack
772///
773/// For sizes ≤ 75, there are dedicated single-byte opcodes, so the push size is one. Otherwise,
774/// if the size can fit into 1, 2 or 4 bytes, we use the `PUSHDATA{1,2,4}` opcode respectively,
775/// followed by the actual size encoded in that many bytes.
776fn push_opcode_size(script_size: usize) -> usize {
777    if script_size < 76 {
778        1
779    } else if script_size < 0x100 {
780        2
781    } else if script_size < 0x10000 {
782        3
783    } else {
784        5
785    }
786}
787
788/// Helper function used by tests
789#[cfg(test)]
790fn hex_script(s: &str) -> bitcoin::Script {
791    let v: Vec<u8> = bitcoin::hashes::hex::FromHex::from_hex(s).unwrap();
792    bitcoin::Script::from(v)
793}