miniscript/
lib.rs

1// Written in 2019 by Andrew Poelstra <apoelstra@wpsoftware.net>
2// SPDX-License-Identifier: CC0-1.0
3
4//! Miniscript and Output Descriptors
5//!
6//! ## Bitcoin Script
7//!
8//! In Bitcoin, spending policies are defined and enforced by means of a
9//! stack-based programming language known as Bitcoin Script. While this
10//! language appears to be designed with tractable analysis in mind (e.g.
11//! there are no looping or jumping constructions), in practice this is
12//! extremely difficult. As a result, typical wallet software supports only
13//! a small set of script templates, cannot interoperate with other similar
14//! software, and each wallet contains independently written ad-hoc manually
15//! verified code to handle these templates. Users who require more complex
16//! spending policies, or who want to combine signing infrastructure which
17//! was not explicitly designed to work together, are simply out of luck.
18//!
19//! ## Miniscript
20//!
21//! Miniscript is an alternative to Bitcoin Script which eliminates these
22//! problems. It can be efficiently and simply encoded as Script to ensure
23//! that it works on the Bitcoin blockchain, but its design is very different.
24//! Essentially, a Miniscript is a monotone function (tree of ANDs, ORs and
25//! thresholds) of signature requirements, hash preimage requirements, and
26//! timelocks.
27//!
28//! A [full description of Miniscript is available here](https://bitcoin.sipa.be/miniscript).
29//!
30//! Miniscript also admits a more human-readable encoding.
31//!
32//! ## Output Descriptors
33//!
34//! While spending policies in Bitcoin are entirely defined by Script; there
35//! are multiple ways of embedding these Scripts in transaction outputs; for
36//! example, P2SH or Segwit v0. These different embeddings are expressed by
37//! *Output Descriptors*, [which are described here](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md).
38//!
39//! # Examples
40//!
41//! ## Deriving an address from a descriptor
42//!
43//! ```rust
44//! use std::str::FromStr;
45//!
46//! let desc = miniscript::Descriptor::<bitcoin::PublicKey>::from_str("\
47//!     sh(wsh(or_d(\
48//!     c:pk_k(020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b67817261),\
49//!     c:pk_k(0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352)\
50//!     )))\
51//!     ").unwrap();
52//!
53//! // Derive the P2SH address.
54//! assert_eq!(
55//!     desc.address(bitcoin::Network::Bitcoin).unwrap().to_string(),
56//!     "3CJxbQBfWAe1ZkKiGQNEYrioV73ZwvBWns"
57//! );
58//!
59//! // Check whether the descriptor is safe. This checks whether all spend paths are accessible in
60//! // the Bitcoin network. It may be possible that some of the spend paths require more than 100
61//! // elements in Wsh scripts or they contain a combination of timelock and heightlock.
62//! assert!(desc.sanity_check().is_ok());
63//!
64//! // Estimate the satisfaction cost.
65//! // scriptSig: OP_PUSH34 <OP_0 OP_32 <32-byte-hash>>
66//! // = (1 + 1 + 1 + 32) * 4 = 140 WU
67//! // redeemScript: varint <OP_33 <pk1> OP_CHECKSIG OP_IFDUP OP_NOTIF OP_33 <pk2> OP_CHECKSIG OP_ENDIF>
68//! // = 1 + (1 + 33 + 1 + 1 + 1 + 1 + 33 + 1 + 1) = 74 WU
69//! // stackItem[Sig]: varint <sig+sighash>
70//! // = 1 + 73 = 74 WU
71//! // Expected satisfaction weight: 140 + 74 + 74 = 288
72//! assert_eq!(desc.max_weight_to_satisfy().unwrap().to_wu(), 288);
73//! ```
74//!
75
76#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
77// Experimental features we need.
78#![cfg_attr(bench, feature(test))]
79// Coding conventions
80#![deny(unsafe_code)]
81#![deny(non_upper_case_globals)]
82#![deny(non_camel_case_types)]
83#![deny(non_snake_case)]
84#![deny(unused_mut)]
85#![deny(dead_code)]
86#![deny(unused_imports)]
87#![deny(missing_docs)]
88// Clippy lints that we have disabled
89#![allow(clippy::iter_kv_map)] // https://github.com/rust-lang/rust-clippy/issues/11752
90#![allow(clippy::manual_range_contains)] // I hate this lint -asp
91#![allow(unexpected_cfgs)] // This one is just batshit.
92
93#[cfg(target_pointer_width = "16")]
94compile_error!(
95    "rust-miniscript currently only supports architectures with pointers wider than 16 bits"
96);
97
98#[cfg(not(any(feature = "std", feature = "no-std")))]
99compile_error!("at least one of the `std` or `no-std` features must be enabled");
100
101pub use bitcoin;
102
103#[cfg(not(feature = "std"))]
104#[macro_use]
105extern crate alloc;
106
107#[cfg(any(feature = "std", test))]
108extern crate core;
109
110#[cfg(feature = "serde")]
111pub use actual_serde as serde;
112
113#[cfg(bench)]
114extern crate test;
115
116#[macro_use]
117mod macros;
118
119#[macro_use]
120mod pub_macros;
121
122mod blanket_traits;
123pub mod descriptor;
124pub mod expression;
125pub mod interpreter;
126pub mod iter;
127pub mod miniscript;
128pub mod plan;
129pub mod policy;
130mod primitives;
131pub mod psbt;
132
133#[cfg(test)]
134mod test_utils;
135mod util;
136
137use core::{fmt, hash, str};
138#[cfg(feature = "std")]
139use std::error;
140
141use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
142use bitcoin::hex::DisplayHex;
143use bitcoin::{script, Opcode};
144
145pub use crate::blanket_traits::FromStrKey;
146pub use crate::descriptor::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey};
147pub use crate::expression::ParseThresholdError;
148pub use crate::interpreter::Interpreter;
149pub use crate::miniscript::analyzable::{AnalysisError, ExtParams};
150pub use crate::miniscript::context::{BareCtx, Legacy, ScriptContext, Segwitv0, SigType, Tap};
151pub use crate::miniscript::decode::Terminal;
152pub use crate::miniscript::satisfy::{Preimage32, Satisfier};
153pub use crate::miniscript::{hash256, Miniscript};
154use crate::prelude::*;
155pub use crate::primitives::absolute_locktime::{AbsLockTime, AbsLockTimeError};
156pub use crate::primitives::relative_locktime::{RelLockTime, RelLockTimeError};
157pub use crate::primitives::threshold::{Threshold, ThresholdError};
158
159/// Public key trait which can be converted to Hash type
160pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
161    /// Returns true if the pubkey is uncompressed. Defaults to `false`.
162    fn is_uncompressed(&self) -> bool { false }
163
164    /// Returns true if the pubkey is an x-only pubkey. Defaults to `false`.
165    // This is required to know what in DescriptorPublicKey to know whether the inner
166    // key in allowed in descriptor context
167    fn is_x_only_key(&self) -> bool { false }
168
169    /// Returns the number of different derivation paths in this key. Only >1 for keys
170    /// in BIP389 multipath descriptors.
171    fn num_der_paths(&self) -> usize { 0 }
172
173    /// The associated [`bitcoin::hashes::sha256::Hash`] for this [`MiniscriptKey`], used in the
174    /// sha256 fragment.
175    type Sha256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
176
177    /// The associated [`miniscript::hash256::Hash`] for this [`MiniscriptKey`], used in the
178    /// hash256 fragment.
179    type Hash256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
180
181    /// The associated [`bitcoin::hashes::ripemd160::Hash`] for this [`MiniscriptKey`] type, used
182    /// in the ripemd160 fragment.
183    type Ripemd160: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
184
185    /// The associated [`bitcoin::hashes::hash160::Hash`] for this [`MiniscriptKey`] type, used in
186    /// the hash160 fragment.
187    type Hash160: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
188}
189
190impl MiniscriptKey for bitcoin::secp256k1::PublicKey {
191    type Sha256 = sha256::Hash;
192    type Hash256 = hash256::Hash;
193    type Ripemd160 = ripemd160::Hash;
194    type Hash160 = hash160::Hash;
195}
196
197impl MiniscriptKey for bitcoin::PublicKey {
198    /// Returns the compressed-ness of the underlying secp256k1 key.
199    fn is_uncompressed(&self) -> bool { !self.compressed }
200
201    type Sha256 = sha256::Hash;
202    type Hash256 = hash256::Hash;
203    type Ripemd160 = ripemd160::Hash;
204    type Hash160 = hash160::Hash;
205}
206
207impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
208    type Sha256 = sha256::Hash;
209    type Hash256 = hash256::Hash;
210    type Ripemd160 = ripemd160::Hash;
211    type Hash160 = hash160::Hash;
212
213    fn is_x_only_key(&self) -> bool { true }
214}
215
216impl MiniscriptKey for String {
217    type Sha256 = String; // specify hashes as string
218    type Hash256 = String;
219    type Ripemd160 = String;
220    type Hash160 = String;
221}
222
223/// Trait describing public key types which can be converted to bitcoin pubkeys
224pub trait ToPublicKey: MiniscriptKey {
225    /// Converts an object to a public key
226    fn to_public_key(&self) -> bitcoin::PublicKey;
227
228    /// Convert an object to x-only pubkey
229    fn to_x_only_pubkey(&self) -> bitcoin::secp256k1::XOnlyPublicKey {
230        let pk = self.to_public_key();
231        bitcoin::secp256k1::XOnlyPublicKey::from(pk.inner)
232    }
233
234    /// Obtain the public key hash for this MiniscriptKey
235    /// Expects an argument to specify the signature type.
236    /// This would determine whether to serialize the key as 32 byte x-only pubkey
237    /// or regular public key when computing the hash160
238    fn to_pubkeyhash(&self, sig_type: SigType) -> hash160::Hash {
239        match sig_type {
240            SigType::Ecdsa => hash160::Hash::hash(&self.to_public_key().to_bytes()),
241            SigType::Schnorr => hash160::Hash::hash(&self.to_x_only_pubkey().serialize()),
242        }
243    }
244
245    /// Converts the generic associated [`MiniscriptKey::Sha256`] to [`sha256::Hash`]
246    fn to_sha256(hash: &<Self as MiniscriptKey>::Sha256) -> sha256::Hash;
247
248    /// Converts the generic associated [`MiniscriptKey::Hash256`] to [`hash256::Hash`]
249    fn to_hash256(hash: &<Self as MiniscriptKey>::Hash256) -> hash256::Hash;
250
251    /// Converts the generic associated [`MiniscriptKey::Ripemd160`] to [`ripemd160::Hash`]
252    fn to_ripemd160(hash: &<Self as MiniscriptKey>::Ripemd160) -> ripemd160::Hash;
253
254    /// Converts the generic associated [`MiniscriptKey::Hash160`] to [`hash160::Hash`]
255    fn to_hash160(hash: &<Self as MiniscriptKey>::Hash160) -> hash160::Hash;
256}
257
258impl ToPublicKey for bitcoin::PublicKey {
259    fn to_public_key(&self) -> bitcoin::PublicKey { *self }
260
261    fn to_sha256(hash: &sha256::Hash) -> sha256::Hash { *hash }
262
263    fn to_hash256(hash: &hash256::Hash) -> hash256::Hash { *hash }
264
265    fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash { *hash }
266
267    fn to_hash160(hash: &hash160::Hash) -> hash160::Hash { *hash }
268}
269
270impl ToPublicKey for bitcoin::secp256k1::PublicKey {
271    fn to_public_key(&self) -> bitcoin::PublicKey { bitcoin::PublicKey::new(*self) }
272
273    fn to_sha256(hash: &sha256::Hash) -> sha256::Hash { *hash }
274
275    fn to_hash256(hash: &hash256::Hash) -> hash256::Hash { *hash }
276
277    fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash { *hash }
278
279    fn to_hash160(hash: &hash160::Hash) -> hash160::Hash { *hash }
280}
281
282impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
283    fn to_public_key(&self) -> bitcoin::PublicKey {
284        // This code should never be used.
285        // But is implemented for completeness
286        let mut data: Vec<u8> = vec![0x02];
287        data.extend(self.serialize().iter());
288        bitcoin::PublicKey::from_slice(&data)
289            .expect("Failed to construct 33 Publickey from 0x02 appended x-only key")
290    }
291
292    fn to_x_only_pubkey(&self) -> bitcoin::secp256k1::XOnlyPublicKey { *self }
293
294    fn to_sha256(hash: &sha256::Hash) -> sha256::Hash { *hash }
295
296    fn to_hash256(hash: &hash256::Hash) -> hash256::Hash { *hash }
297
298    fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash { *hash }
299
300    fn to_hash160(hash: &hash160::Hash) -> hash160::Hash { *hash }
301}
302
303/// Describes an object that can translate various keys and hashes from one key to the type
304/// associated with the other key. Used by the [`TranslatePk`] trait to do the actual translations.
305pub trait Translator<P, Q, E>
306where
307    P: MiniscriptKey,
308    Q: MiniscriptKey,
309{
310    /// Translates public keys P -> Q.
311    fn pk(&mut self, pk: &P) -> Result<Q, E>;
312
313    /// Provides the translation from P::Sha256 -> Q::Sha256
314    fn sha256(&mut self, sha256: &P::Sha256) -> Result<Q::Sha256, E>;
315
316    /// Provides the translation from P::Hash256 -> Q::Hash256
317    fn hash256(&mut self, hash256: &P::Hash256) -> Result<Q::Hash256, E>;
318
319    /// Translates ripemd160 hashes from P::Ripemd160 -> Q::Ripemd160
320    fn ripemd160(&mut self, ripemd160: &P::Ripemd160) -> Result<Q::Ripemd160, E>;
321
322    /// Translates hash160 hashes from P::Hash160 -> Q::Hash160
323    fn hash160(&mut self, hash160: &P::Hash160) -> Result<Q::Hash160, E>;
324}
325
326/// An enum for representing translation errors
327pub enum TranslateErr<E> {
328    /// Error inside in the underlying key translation
329    TranslatorErr(E),
330    /// Error in the final translated structure. In some cases, the translated
331    /// structure might not be valid under the given context. For example, translating
332    /// from string keys to x-only keys in wsh descriptors.
333    OuterError(Error),
334}
335
336impl<E> TranslateErr<E> {
337    /// Enum used to capture errors from the [`Translator`] trait as well as
338    /// context errors from the translated structure.
339    /// The errors occurred in translation are captured in the [`TranslateErr::TranslatorErr`]
340    /// while the errors in the translated structure are captured in the [`TranslateErr::OuterError`]
341    ///
342    /// As of taproot upgrade: The following rules apply to the translation of descriptors:
343    /// - Legacy/Bare does not allow x_only keys
344    /// - SegwitV0 does not allow uncompressed keys and x_only keys
345    /// - Tapscript does not allow uncompressed keys
346    /// - Translating into multi-path descriptors should have same number of path
347    ///   for all the keys in the descriptor
348    ///
349    /// # Panics
350    ///
351    /// This function will panic if the Error is OutError.
352    pub fn expect_translator_err(self, msg: &str) -> E {
353        match self {
354            Self::TranslatorErr(v) => v,
355            Self::OuterError(ref e) => {
356                panic!("Unexpected Miniscript error when translating: {}\nMessage: {}", e, msg)
357            }
358        }
359    }
360}
361
362impl TranslateErr<Error> {
363    /// If we are doing a translation where our "outer error" is the generic
364    /// Miniscript error, eliminate the `TranslateErr` type which is just noise.
365    pub fn flatten(self) -> Error {
366        match self {
367            Self::TranslatorErr(e) => e,
368            Self::OuterError(e) => e,
369        }
370    }
371}
372
373impl<E> From<E> for TranslateErr<E> {
374    fn from(v: E) -> Self { Self::TranslatorErr(v) }
375}
376
377// Required for unwrap
378impl<E: fmt::Debug> fmt::Debug for TranslateErr<E> {
379    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
380        match self {
381            Self::TranslatorErr(e) => write!(f, "TranslatorErr({:?})", e),
382            Self::OuterError(e) => write!(f, "OuterError({:?})", e),
383        }
384    }
385}
386
387/// Converts a descriptor using abstract keys to one using specific keys. Uses translator `t` to do
388/// the actual translation function calls.
389pub trait TranslatePk<P, Q>
390where
391    P: MiniscriptKey,
392    Q: MiniscriptKey,
393{
394    /// The associated output type. This must be `Self<Q>`.
395    type Output;
396
397    /// Translates a struct from one generic to another where the translations
398    /// for Pk are provided by the given [`Translator`].
399    fn translate_pk<T, E>(&self, translator: &mut T) -> Result<Self::Output, TranslateErr<E>>
400    where
401        T: Translator<P, Q, E>;
402}
403
404/// Trait describing the ability to iterate over every key
405pub trait ForEachKey<Pk: MiniscriptKey> {
406    /// Run a predicate on every key in the descriptor, returning whether
407    /// the predicate returned true for every key
408    fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
409    where
410        Pk: 'a;
411
412    /// Run a predicate on every key in the descriptor, returning whether
413    /// the predicate returned true for any key
414    fn for_any_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
415    where
416        Pk: 'a,
417    {
418        !self.for_each_key(|key| !pred(key))
419    }
420}
421
422/// Miniscript
423
424#[derive(Debug, PartialEq)]
425pub enum Error {
426    /// Opcode appeared which is not part of the script subset
427    InvalidOpcode(Opcode),
428    /// Some opcode occurred followed by `OP_VERIFY` when it had
429    /// a `VERIFY` version that should have been used instead
430    NonMinimalVerify(String),
431    /// Push was illegal in some context
432    InvalidPush(Vec<u8>),
433    /// rust-bitcoin script error
434    Script(script::Error),
435    /// rust-bitcoin address error
436    AddrError(bitcoin::address::ParseError),
437    /// rust-bitcoin p2sh address error
438    AddrP2shError(bitcoin::address::P2shError),
439    /// A `CHECKMULTISIG` opcode was preceded by a number > 20
440    CmsTooManyKeys(u32),
441    /// A tapscript multi_a cannot support more than Weight::MAX_BLOCK/32 keys
442    MultiATooManyKeys(u64),
443    /// Encountered unprintable character in descriptor
444    Unprintable(u8),
445    /// expected character while parsing descriptor; didn't find one
446    ExpectedChar(char),
447    /// While parsing backward, hit beginning of script
448    UnexpectedStart,
449    /// Got something we were not expecting
450    Unexpected(String),
451    /// Name of a fragment contained `:` multiple times
452    MultiColon(String),
453    /// Name of a fragment contained `@` but we were not parsing an OR
454    AtOutsideOr(String),
455    /// Encountered a wrapping character that we don't recognize
456    UnknownWrapper(char),
457    /// Parsed a miniscript and the result was not of type T
458    NonTopLevel(String),
459    /// Parsed a miniscript but there were more script opcodes after it
460    Trailing(String),
461    /// Could not satisfy a script (fragment) because of a missing signature
462    MissingSig(bitcoin::PublicKey),
463    /// General failure to satisfy
464    CouldNotSatisfy,
465    /// Typechecking failed
466    TypeCheck(String),
467    /// General error in creating descriptor
468    BadDescriptor(String),
469    /// Forward-secp related errors
470    Secp(bitcoin::secp256k1::Error),
471    #[cfg(feature = "compiler")]
472    /// Compiler related errors
473    CompilerError(crate::policy::compiler::CompilerError),
474    /// Errors related to policy
475    PolicyError(policy::concrete::PolicyError),
476    /// Errors related to lifting
477    LiftError(policy::LiftError),
478    /// Forward script context related errors
479    ContextError(miniscript::context::ScriptContextError),
480    /// Recursion depth exceeded when parsing policy/miniscript from string
481    MaxRecursiveDepthExceeded,
482    /// Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...)
483    /// up to n=3 is invalid by standardness (bare)
484    NonStandardBareScript,
485    /// Analysis Error
486    AnalysisError(miniscript::analyzable::AnalysisError),
487    /// Miniscript is equivalent to false. No possible satisfaction
488    ImpossibleSatisfaction,
489    /// Bare descriptors don't have any addresses
490    BareDescriptorAddr,
491    /// PubKey invalid under current context
492    PubKeyCtxError(miniscript::decode::KeyParseError, &'static str),
493    /// No script code for Tr descriptors
494    TrNoScriptCode,
495    /// At least two BIP389 key expressions in the descriptor contain tuples of
496    /// derivation indexes of different lengths.
497    MultipathDescLenMismatch,
498    /// Invalid absolute locktime
499    AbsoluteLockTime(AbsLockTimeError),
500    /// Invalid absolute locktime
501    RelativeLockTime(RelLockTimeError),
502    /// Invalid threshold.
503    Threshold(ThresholdError),
504    /// Invalid threshold.
505    ParseThreshold(ParseThresholdError),
506}
507
508// https://github.com/sipa/miniscript/pull/5 for discussion on this number
509const MAX_RECURSION_DEPTH: u32 = 402;
510
511impl fmt::Display for Error {
512    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
513        match *self {
514            Error::InvalidOpcode(op) => write!(f, "invalid opcode {}", op),
515            Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok),
516            Error::InvalidPush(ref push) => {
517                write!(f, "invalid push {:x}", push.as_hex())
518            },
519            Error::Script(ref e) => fmt::Display::fmt(e, f),
520            Error::AddrError(ref e) => fmt::Display::fmt(e, f),
521            Error::AddrP2shError(ref e) => fmt::Display::fmt(e, f),
522            Error::CmsTooManyKeys(n) => write!(f, "checkmultisig with {} keys", n),
523            Error::Unprintable(x) => write!(f, "unprintable character 0x{:02x}", x),
524            Error::ExpectedChar(c) => write!(f, "expected {}", c),
525            Error::UnexpectedStart => f.write_str("unexpected start of script"),
526            Error::Unexpected(ref s) => write!(f, "unexpected «{}»", s),
527            Error::MultiColon(ref s) => write!(f, "«{}» has multiple instances of «:»", s),
528            Error::AtOutsideOr(ref s) => write!(f, "«{}» contains «@» in non-or() context", s),
529            Error::UnknownWrapper(ch) => write!(f, "unknown wrapper «{}:»", ch),
530            Error::NonTopLevel(ref s) => write!(f, "non-T miniscript: {}", s),
531            Error::Trailing(ref s) => write!(f, "trailing tokens: {}", s),
532            Error::MissingSig(ref pk) => write!(f, "missing signature for key {:?}", pk),
533            Error::CouldNotSatisfy => f.write_str("could not satisfy"),
534            Error::TypeCheck(ref e) => write!(f, "typecheck: {}", e),
535            Error::BadDescriptor(ref e) => write!(f, "Invalid descriptor: {}", e),
536            Error::Secp(ref e) => fmt::Display::fmt(e, f),
537            Error::ContextError(ref e) => fmt::Display::fmt(e, f),
538            #[cfg(feature = "compiler")]
539            Error::CompilerError(ref e) => fmt::Display::fmt(e, f),
540            Error::PolicyError(ref e) => fmt::Display::fmt(e, f),
541            Error::LiftError(ref e) => fmt::Display::fmt(e, f),
542            Error::MaxRecursiveDepthExceeded => write!(
543                f,
544                "Recursive depth over {} not permitted",
545                MAX_RECURSION_DEPTH
546            ),
547            Error::NonStandardBareScript => write!(
548                f,
549                "Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) \
550                up to n=3 is invalid by standardness (bare).
551                "
552            ),
553            Error::AnalysisError(ref e) => e.fmt(f),
554            Error::ImpossibleSatisfaction => write!(f, "Impossible to satisfy Miniscript"),
555            Error::BareDescriptorAddr => write!(f, "Bare descriptors don't have address"),
556            Error::PubKeyCtxError(ref pk, ref ctx) => {
557                write!(f, "Pubkey error: {} under {} scriptcontext", pk, ctx)
558            }
559            Error::MultiATooManyKeys(k) => write!(f, "MultiA too many keys {}", k),
560            Error::TrNoScriptCode => write!(f, "No script code for Tr descriptors"),
561            Error::MultipathDescLenMismatch => write!(f, "At least two BIP389 key expressions in the descriptor contain tuples of derivation indexes of different lengths"),
562            Error::AbsoluteLockTime(ref e) => e.fmt(f),
563            Error::RelativeLockTime(ref e) => e.fmt(f),
564            Error::Threshold(ref e) => e.fmt(f),
565            Error::ParseThreshold(ref e) => e.fmt(f),
566        }
567    }
568}
569
570#[cfg(feature = "std")]
571impl error::Error for Error {
572    fn cause(&self) -> Option<&dyn error::Error> {
573        use self::Error::*;
574
575        match self {
576            InvalidOpcode(_)
577            | NonMinimalVerify(_)
578            | InvalidPush(_)
579            | CmsTooManyKeys(_)
580            | MultiATooManyKeys(_)
581            | Unprintable(_)
582            | ExpectedChar(_)
583            | UnexpectedStart
584            | Unexpected(_)
585            | MultiColon(_)
586            | AtOutsideOr(_)
587            | UnknownWrapper(_)
588            | NonTopLevel(_)
589            | Trailing(_)
590            | MissingSig(_)
591            | CouldNotSatisfy
592            | TypeCheck(_)
593            | BadDescriptor(_)
594            | MaxRecursiveDepthExceeded
595            | NonStandardBareScript
596            | ImpossibleSatisfaction
597            | BareDescriptorAddr
598            | TrNoScriptCode
599            | MultipathDescLenMismatch => None,
600            Script(e) => Some(e),
601            AddrError(e) => Some(e),
602            AddrP2shError(e) => Some(e),
603            Secp(e) => Some(e),
604            #[cfg(feature = "compiler")]
605            CompilerError(e) => Some(e),
606            PolicyError(e) => Some(e),
607            LiftError(e) => Some(e),
608            ContextError(e) => Some(e),
609            AnalysisError(e) => Some(e),
610            PubKeyCtxError(e, _) => Some(e),
611            AbsoluteLockTime(e) => Some(e),
612            RelativeLockTime(e) => Some(e),
613            Threshold(e) => Some(e),
614            ParseThreshold(e) => Some(e),
615        }
616    }
617}
618
619#[doc(hidden)]
620impl From<miniscript::types::Error> for Error {
621    fn from(e: miniscript::types::Error) -> Error { Error::TypeCheck(e.to_string()) }
622}
623
624#[doc(hidden)]
625impl From<policy::LiftError> for Error {
626    fn from(e: policy::LiftError) -> Error { Error::LiftError(e) }
627}
628
629#[doc(hidden)]
630impl From<miniscript::context::ScriptContextError> for Error {
631    fn from(e: miniscript::context::ScriptContextError) -> Error { Error::ContextError(e) }
632}
633
634#[doc(hidden)]
635impl From<miniscript::analyzable::AnalysisError> for Error {
636    fn from(e: miniscript::analyzable::AnalysisError) -> Error { Error::AnalysisError(e) }
637}
638
639#[doc(hidden)]
640impl From<bitcoin::secp256k1::Error> for Error {
641    fn from(e: bitcoin::secp256k1::Error) -> Error { Error::Secp(e) }
642}
643
644#[doc(hidden)]
645impl From<bitcoin::address::ParseError> for Error {
646    fn from(e: bitcoin::address::ParseError) -> Error { Error::AddrError(e) }
647}
648
649#[doc(hidden)]
650impl From<bitcoin::address::P2shError> for Error {
651    fn from(e: bitcoin::address::P2shError) -> Error { Error::AddrP2shError(e) }
652}
653
654#[doc(hidden)]
655#[cfg(feature = "compiler")]
656impl From<crate::policy::compiler::CompilerError> for Error {
657    fn from(e: crate::policy::compiler::CompilerError) -> Error { Error::CompilerError(e) }
658}
659
660#[doc(hidden)]
661impl From<policy::concrete::PolicyError> for Error {
662    fn from(e: policy::concrete::PolicyError) -> Error { Error::PolicyError(e) }
663}
664
665fn errstr(s: &str) -> Error { Error::Unexpected(s.to_owned()) }
666
667/// The size of an encoding of a number in Script
668pub fn script_num_size(n: usize) -> usize {
669    match n {
670        n if n <= 0x10 => 1,      // OP_n
671        n if n < 0x80 => 2,       // OP_PUSH1 <n>
672        n if n < 0x8000 => 3,     // OP_PUSH2 <n>
673        n if n < 0x800000 => 4,   // OP_PUSH3 <n>
674        n if n < 0x80000000 => 5, // OP_PUSH4 <n>
675        _ => 6,                   // OP_PUSH5 <n>
676    }
677}
678
679/// Returns the size of the smallest push opcode used to push a given number of bytes onto the stack
680///
681/// For sizes ≤ 75, there are dedicated single-byte opcodes, so the push size is one. Otherwise,
682/// if the size can fit into 1, 2 or 4 bytes, we use the `PUSHDATA{1,2,4}` opcode respectively,
683/// followed by the actual size encoded in that many bytes.
684fn push_opcode_size(script_size: usize) -> usize {
685    if script_size < 76 {
686        1
687    } else if script_size < 0x100 {
688        2
689    } else if script_size < 0x10000 {
690        3
691    } else {
692        5
693    }
694}
695
696/// Helper function used by tests
697#[cfg(test)]
698fn hex_script(s: &str) -> bitcoin::ScriptBuf {
699    let v: Vec<u8> = bitcoin::hashes::hex::FromHex::from_hex(s).unwrap();
700    bitcoin::ScriptBuf::from(v)
701}
702
703#[cfg(test)]
704mod tests {
705    use core::str::FromStr;
706
707    use super::*;
708
709    #[test]
710    fn regression_bitcoin_key_hash() {
711        use bitcoin::PublicKey;
712
713        // Uncompressed key.
714        let pk = PublicKey::from_str(
715            "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"
716        ).unwrap();
717
718        let want = hash160::Hash::from_str("ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a").unwrap();
719        let got = pk.to_pubkeyhash(SigType::Ecdsa);
720        assert_eq!(got, want)
721    }
722
723    #[test]
724    fn regression_secp256k1_key_hash() {
725        use bitcoin::secp256k1::PublicKey;
726
727        // Compressed key.
728        let pk = PublicKey::from_str(
729            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
730        )
731        .unwrap();
732
733        let want = hash160::Hash::from_str("9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4").unwrap();
734        let got = pk.to_pubkeyhash(SigType::Ecdsa);
735        assert_eq!(got, want)
736    }
737
738    #[test]
739    fn regression_xonly_key_hash() {
740        use bitcoin::secp256k1::XOnlyPublicKey;
741
742        let pk = XOnlyPublicKey::from_str(
743            "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
744        )
745        .unwrap();
746
747        let want = hash160::Hash::from_str("eb8ac65f971ae688a94aeabf223506865e7e08f2").unwrap();
748        let got = pk.to_pubkeyhash(SigType::Schnorr);
749        assert_eq!(got, want)
750    }
751}
752
753#[allow(unused_imports)] // this is an internal prelude module; not all imports are used with every feature combination
754mod prelude {
755    // Mutex implementation from LDK
756    // https://github.com/lightningdevkit/rust-lightning/blob/9bdce47f0e0516e37c89c09f1975dfc06b5870b1/lightning-invoice/src/sync.rs
757    #[cfg(all(not(feature = "std"), not(test)))]
758    mod mutex {
759        use core::cell::{RefCell, RefMut};
760        use core::ops::{Deref, DerefMut};
761
762        pub type LockResult<Guard> = Result<Guard, ()>;
763
764        /// `Mutex` is not a real mutex as it cannot be used in a multi-threaded
765        /// context. `Mutex` is a dummy implementation of [`std::sync::Mutex`]
766        /// for `no_std` environments.
767        pub struct Mutex<T: ?Sized> {
768            inner: RefCell<T>,
769        }
770
771        #[must_use = "if unused the Mutex will immediately unlock"]
772        pub struct MutexGuard<'a, T: ?Sized + 'a> {
773            lock: RefMut<'a, T>,
774        }
775
776        impl<T: ?Sized> Deref for MutexGuard<'_, T> {
777            type Target = T;
778
779            fn deref(&self) -> &T { self.lock.deref() }
780        }
781
782        impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
783            fn deref_mut(&mut self) -> &mut T { self.lock.deref_mut() }
784        }
785
786        impl<T> Mutex<T> {
787            pub fn new(inner: T) -> Mutex<T> { Mutex { inner: RefCell::new(inner) } }
788
789            pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
790                Ok(MutexGuard { lock: self.inner.borrow_mut() })
791            }
792        }
793    }
794
795    #[cfg(all(not(feature = "std"), not(test)))]
796    pub use alloc::{
797        borrow::{Borrow, Cow, ToOwned},
798        boxed::Box,
799        collections::{vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap},
800        rc, slice,
801        string::{String, ToString},
802        sync,
803        vec::Vec,
804    };
805    #[cfg(any(feature = "std", test))]
806    pub use std::{
807        borrow::{Borrow, Cow, ToOwned},
808        boxed::Box,
809        collections::{vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet},
810        rc, slice,
811        string::{String, ToString},
812        sync,
813        sync::Mutex,
814        vec::Vec,
815    };
816
817    #[cfg(all(not(feature = "std"), not(test)))]
818    pub use self::mutex::Mutex;
819}