Skip to main content

elements_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](http://bitcoin.sipa.be/miniscript/miniscript.html).
29//!
30//! Miniscript also admits a more human-readable encoding.
31//!
32//! ## Elements Miniscript
33//!
34//! Elements Miniscript is a fork of miniscript for [elements](https://github.com/ElementsProject/elements) sidechain.
35//!
36//! ## Output Descriptors
37//!
38//! While spending policies in Bitcoin are entirely defined by Script; there
39//! are multiple ways of embedding these Scripts in transaction outputs; for
40//! example, P2SH or Segwit v0. These different embeddings are expressed by
41//! *Output Descriptors*, [which are described here](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md).
42//! Elements descriptors are extension of bitcoin Output descriptors with support
43//! for blinded descriptors(WIP).
44//! # Examples
45//!
46//! ## Deriving an address from a descriptor
47//!
48//! ```rust
49//! extern crate bitcoin;
50//! extern crate elements;
51//! extern crate elements_miniscript as miniscript;
52//!
53//! use std::str::FromStr;
54//!
55//! fn main() {
56//!     // Elements descriptors are prefixed by string el
57//!     let desc = miniscript::Descriptor::<
58//!         bitcoin::PublicKey,
59//!     >::from_str("\
60//!         elsh(wsh(or_d(\
61//!             c:pk_k(020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b67817261),\
62//!             c:pk_k(0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352)\
63//!         )))\
64//!     ").unwrap();
65//!
66//!     // Derive the P2SH address.
67//!     assert_eq!(
68//!         desc.address(&elements::AddressParams::ELEMENTS).unwrap().to_string(),
69//!         "XMyBX13qCo5Lp65mymgYVdmsYR5bcznWUa"
70//!     );
71//!
72//!     // Check whether the descriptor is safe
73//!     // This checks whether all spend paths are accessible in bitcoin network.
74//!     // It maybe possible that some of the spend require more than 100 elements in Wsh scripts
75//!     // Or they contain a combination of timelock and heightlock.
76//!     assert!(desc.sanity_check().is_ok());
77//!
78//!     // Estimate the satisfaction cost.
79//!     // scriptSig: OP_PUSH34 <OP_0 OP_32 <32-byte-hash>>
80//!     // = (1 + 1 + 1 + 32) * 4 = 140 WU
81//!     // redeemScript: varint <OP_33 <pk1> OP_CHECKSIG OP_IFDUP OP_NOTIF OP_33 <pk2> OP_CHECKSIG OP_ENDIF>
82//!     // = 1 + (1 + 33 + 1 + 1 + 1 + 1 + 33 + 1 + 1) = 74 WU
83//!     // stackItem[Sig]: varint <sig+sighash>
84//!     // = 1 + 73 = 74 WU
85//!     // Expected satisfaction weight: 140 + 74 + 74 = 288
86//!     assert_eq!(desc.max_weight_to_satisfy().unwrap(), 288);
87//! }
88//! ```
89//!
90//!
91
92#![cfg_attr(miniscript_bench, feature(test))]
93#![allow(clippy::manual_range_contains)] // this lint is just stupid
94#![allow(clippy::type_complexity)] // clippy doesn't like how many generics we use
95
96#[cfg(target_pointer_width = "16")]
97compile_error!(
98    "elements-miniscript currently only supports architectures with pointers wider than 16 bits"
99);
100
101#[cfg(feature = "serde")]
102pub use actual_serde as serde;
103pub use {bitcoin, elements};
104#[cfg(miniscript_bench)]
105extern crate test;
106
107// Miniscript imports
108// It can be confusing to code when we have two miniscript libraries
109// As a rule, only import the library here and pub use all the required
110// items. Should help in faster code development in the long run
111use bitcoin_miniscript::expression::{FromTree as BtcFromTree, Tree as BtcTree};
112use bitcoin_miniscript::policy::semantic::Policy as BtcPolicy;
113use bitcoin_miniscript::policy::Liftable as BtcLiftable;
114// re-export imports
115pub use bitcoin_miniscript::{hash256, ForEachKey, MiniscriptKey, SigType, ToPublicKey};
116pub use bitcoin_miniscript::{
117    Descriptor as BtcDescriptor, Error as BtcError, Miniscript as BtcMiniscript,
118    Satisfier as BtcSatisfier, Segwitv0 as BtcSegwitv0, Terminal as BtcTerminal,
119};
120// End imports
121
122#[macro_use]
123mod macros;
124
125#[macro_use]
126mod pub_macros;
127
128pub mod confidential;
129pub mod descriptor;
130pub mod expression;
131pub mod extensions;
132pub mod interpreter;
133pub mod miniscript;
134pub mod policy;
135pub mod psbt;
136
137#[cfg(feature = "simplicity")]
138mod simplicity;
139#[cfg(test)]
140mod test_utils;
141mod util;
142
143use std::{cmp, error, fmt, str};
144
145use bitcoin::hashes::sha256;
146use elements::secp256k1_zkp::Secp256k1;
147use elements::{locktime, opcodes, script, secp256k1_zkp};
148
149pub use crate::confidential::slip77;
150pub use crate::confidential::Descriptor as ConfidentialDescriptor;
151pub use crate::descriptor::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey};
152pub use crate::extensions::{CovenantExt, Extension, NoExt, TxEnv};
153pub use crate::interpreter::Interpreter;
154pub use crate::miniscript::analyzable::{AnalysisError, ExtParams};
155pub use crate::miniscript::context::{BareCtx, Legacy, ScriptContext, Segwitv0, Tap};
156pub use crate::miniscript::decode::Terminal;
157pub use crate::miniscript::satisfy::{
158    elementssig_from_rawsig, elementssig_to_rawsig, ElementsSig, Preimage32, Satisfier,
159};
160pub use crate::miniscript::Miniscript;
161// minimal implementation of contract hash module
162mod contracthash {
163    use bitcoin::hashes::{sha256, Hash, HashEngine, Hmac, HmacEngine};
164    use bitcoin::secp256k1::Scalar;
165    use bitcoin::PublicKey;
166    use elements::secp256k1_zkp::{self, Secp256k1};
167
168    /// Tweak a single key using some arbitrary data
169    pub(super) fn tweak_key<C: secp256k1_zkp::Verification>(
170        secp: &Secp256k1<C>,
171        key: PublicKey,
172        contract: &[u8],
173    ) -> PublicKey {
174        let hmac_result = compute_tweak(&key, contract);
175        let secp_key = key
176            .inner
177            .add_exp_tweak(
178                secp,
179                &Scalar::from_be_bytes(hmac_result.to_byte_array())
180                    .expect("Result of hash must be a valid point"),
181            )
182            .expect("HMAC cannot produce invalid tweak");
183        bitcoin::PublicKey::new(secp_key)
184    }
185
186    /// Compute a tweak from some given data for the given public key
187    fn compute_tweak(pk: &PublicKey, contract: &[u8]) -> Hmac<sha256::Hash> {
188        let mut hmac_engine: HmacEngine<sha256::Hash> = if pk.compressed {
189            HmacEngine::new(&pk.inner.serialize())
190        } else {
191            HmacEngine::new(&pk.inner.serialize_uncompressed())
192        };
193        hmac_engine.input(contract);
194        Hmac::from_engine(hmac_engine)
195    }
196}
197
198/// Tweak a MiniscriptKey to obtain the tweaked key
199// Ideally, we want this in a trait, but doing so we cannot
200// use it in the implementation of DescriptorTrait from
201// rust-miniscript because it would require stricter bounds.
202pub fn tweak_key<Pk, C: secp256k1_zkp::Verification>(
203    pk: &Pk,
204    secp: &Secp256k1<C>,
205    contract: &[u8],
206) -> bitcoin::PublicKey
207where
208    Pk: MiniscriptKey + ToPublicKey,
209{
210    let pk = pk.to_public_key();
211    contracthash::tweak_key(secp, pk, contract)
212}
213
214/// Describes an object that can translate various keys and hashes from one key to the type
215/// associated with the other key. Used by the [`TranslatePk`] trait to do the actual translations.
216pub trait Translator<P, Q, E>
217where
218    P: MiniscriptKey,
219    Q: MiniscriptKey,
220{
221    /// Translates public keys P -> Q.
222    fn pk(&mut self, pk: &P) -> Result<Q, E>;
223
224    /// Provides the translation from P::Sha256 -> Q::Sha256
225    fn sha256(&mut self, sha256: &P::Sha256) -> Result<Q::Sha256, E>;
226
227    /// Provides the translation from P::Hash256 -> Q::Hash256
228    fn hash256(&mut self, hash256: &P::Hash256) -> Result<Q::Hash256, E>;
229
230    /// Translates ripemd160 hashes from P::Ripemd160 -> Q::Ripemd160
231    fn ripemd160(&mut self, ripemd160: &P::Ripemd160) -> Result<Q::Ripemd160, E>;
232
233    /// Translates hash160 hashes from P::Hash160 -> Q::Hash160
234    fn hash160(&mut self, hash160: &P::Hash160) -> Result<Q::Hash160, E>;
235}
236
237/// Trait for translation Extensions
238pub trait ExtTranslator<PExt, QExt, E>
239where
240    PExt: Extension,
241    QExt: Extension,
242{
243    /// Translates one extension to another
244    fn ext(&mut self, e: &PExt) -> Result<QExt, E>;
245}
246
247/// Converts a descriptor using abstract keys to one using specific keys. Uses translator `t` to do
248/// the actual translation function calls.
249pub trait TranslatePk<P, Q>
250where
251    P: MiniscriptKey,
252    Q: MiniscriptKey,
253{
254    /// The associated output type. This must be `Self<Q>`.
255    type Output;
256
257    /// Translates a struct from one generic to another where the translations
258    /// for Pk are provided by the given [`Translator`].
259    fn translate_pk<T, E>(&self, translator: &mut T) -> Result<Self::Output, E>
260    where
261        T: Translator<P, Q, E>;
262}
263
264/// Converts a descriptor using abstract keys to one using specific keys. Uses translator `t` to do
265/// the actual translation function calls.
266pub trait TranslateExt<PExt, QExt>
267where
268    PExt: Extension,
269    QExt: Extension,
270{
271    /// The associated output type.
272    type Output;
273
274    /// Translates a struct from one generic to another where the translations
275    /// for Pk are provided by the given [`Translator`].
276    fn translate_ext<T, E>(&self, translator: &mut T) -> Result<Self::Output, E>
277    where
278        T: ExtTranslator<PExt, QExt, E>;
279}
280
281/// Miniscript Error
282#[derive(Debug, PartialEq)]
283pub enum Error {
284    /// Opcode appeared which is not part of the script subset
285    InvalidOpcode(opcodes::All),
286    /// Some opcode occurred followed by `OP_VERIFY` when it had
287    /// a `VERIFY` version that should have been used instead
288    NonMinimalVerify(String),
289    /// Push was illegal in some context
290    InvalidPush(Vec<u8>),
291    /// rust-bitcoin script error
292    Script(script::Error),
293    /// rust-bitcoin address error
294    AddrError(bitcoin::address::ParseError),
295    /// A `CHECKMULTISIG` opcode was preceded by a number > 20
296    CmsTooManyKeys(u32),
297    /// A tapscript multi_a cannot support more than MAX_BLOCK_WEIGHT/32 keys
298    MultiATooManyKeys(u32),
299    /// expected character while parsing descriptor; didn't find one
300    ExpectedChar(char),
301    /// While parsing backward, hit beginning of script
302    UnexpectedStart,
303    /// Got something we were not expecting
304    Unexpected(String),
305    /// Name of a fragment contained `:` multiple times
306    MultiColon(String),
307    /// Name of a fragment contained `@` multiple times
308    MultiAt(String),
309    /// Name of a fragment contained `@` but we were not parsing an OR
310    AtOutsideOr(String),
311    /// Encountered a `l:0` which is syntactically equal to `u:0` except stupid
312    LikelyFalse,
313    /// Encountered a wrapping character that we don't recognize
314    UnknownWrapper(char),
315    /// Parsed a miniscript and the result was not of type T
316    NonTopLevel(String),
317    /// Parsed a miniscript but there were more script opcodes after it
318    Trailing(String),
319    /// Failed to parse a push as a public key
320    BadPubkey(bitcoin::key::ParsePublicKeyError),
321    /// Failed to parse a slice as public key
322    BadPubkeySlice(bitcoin::key::FromSliceError),
323    /// Could not satisfy a script (fragment) because of a missing hash preimage
324    MissingHash(sha256::Hash),
325    /// Could not satisfy a script (fragment) because of a missing signature
326    MissingSig(bitcoin::PublicKey),
327    /// Could not satisfy, relative locktime not met
328    RelativeLocktimeNotMet(u32),
329    /// Could not satisfy, absolute locktime not met
330    AbsoluteLocktimeNotMet(u32),
331    /// General failure to satisfy
332    CouldNotSatisfy,
333    /// Typechecking failed
334    TypeCheck(String),
335    /// General error in creating descriptor
336    BadDescriptor(String),
337    /// Forward-secp related errors
338    Secp(elements::secp256k1_zkp::Error),
339    #[cfg(feature = "compiler")]
340    /// Compiler related errors
341    CompilerError(policy::compiler::CompilerError),
342    /// Errors related to policy
343    PolicyError(policy::concrete::PolicyError),
344    /// Errors related to lifting
345    LiftError(policy::LiftError),
346    /// Forward script context related errors
347    ContextError(miniscript::context::ScriptContextError),
348    /// Recursion depth exceeded when parsing policy/miniscript from string
349    MaxRecursiveDepthExceeded,
350    /// Script size too large
351    ScriptSizeTooLarge,
352    /// Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...)
353    /// up to n=3 is invalid by standardness (bare)
354    NonStandardBareScript,
355    /// Analysis Error
356    AnalysisError(miniscript::analyzable::AnalysisError),
357    /// Miniscript is equivalent to false. No possible satisfaction
358    ImpossibleSatisfaction,
359    /// Bare descriptors don't have any addresses
360    BareDescriptorAddr,
361    /// Upstream Miniscript Errors
362    BtcError(bitcoin_miniscript::Error),
363    /// Covenant Error
364    CovError(descriptor::CovError),
365    /// PubKey invalid under current context
366    PubKeyCtxError(miniscript::decode::KeyParseError, &'static str),
367    /// Attempted to call function that requires PreComputed taproot info
368    TaprootSpendInfoUnavialable,
369    /// No script code for Tr descriptors
370    TrNoScriptCode,
371    /// No explicit script for Tr descriptors
372    TrNoExplicitScript,
373    /// At least two BIP389 key expressions in the descriptor contain tuples of
374    /// derivation indexes of different lengths.
375    MultipathDescLenMismatch,
376
377    /// The federation descriptor has a type not supported
378    UnsupportedAddressForPegin,
379
380    /// Conversion error in descriptor
381    Conversion(descriptor::ConversionError),
382}
383
384#[doc(hidden)]
385impl<Pk, Ctx, Ext> From<miniscript::types::Error<Pk, Ctx, Ext>> for Error
386where
387    Pk: MiniscriptKey,
388    Ctx: ScriptContext,
389    Ext: Extension,
390{
391    fn from(e: miniscript::types::Error<Pk, Ctx, Ext>) -> Error {
392        Error::TypeCheck(e.to_string())
393    }
394}
395
396#[doc(hidden)]
397impl From<bitcoin_miniscript::Error> for Error {
398    fn from(e: bitcoin_miniscript::Error) -> Error {
399        Error::BtcError(e)
400    }
401}
402
403#[doc(hidden)]
404impl From<policy::LiftError> for Error {
405    fn from(e: policy::LiftError) -> Error {
406        Error::LiftError(e)
407    }
408}
409
410#[doc(hidden)]
411impl From<miniscript::context::ScriptContextError> for Error {
412    fn from(e: miniscript::context::ScriptContextError) -> Error {
413        Error::ContextError(e)
414    }
415}
416
417#[doc(hidden)]
418impl From<miniscript::analyzable::AnalysisError> for Error {
419    fn from(e: miniscript::analyzable::AnalysisError) -> Error {
420        Error::AnalysisError(e)
421    }
422}
423
424#[doc(hidden)]
425impl From<elements::secp256k1_zkp::Error> for Error {
426    fn from(e: elements::secp256k1_zkp::Error) -> Error {
427        Error::Secp(e)
428    }
429}
430
431#[doc(hidden)]
432impl From<elements::secp256k1_zkp::UpstreamError> for Error {
433    fn from(e: elements::secp256k1_zkp::UpstreamError) -> Error {
434        Error::Secp(elements::secp256k1_zkp::Error::Upstream(e))
435    }
436}
437
438#[doc(hidden)]
439impl From<bitcoin::key::ParsePublicKeyError> for Error {
440    fn from(e: bitcoin::key::ParsePublicKeyError) -> Error {
441        Error::BadPubkey(e)
442    }
443}
444
445#[doc(hidden)]
446impl From<bitcoin::key::FromSliceError> for Error {
447    fn from(e: bitcoin::key::FromSliceError) -> Error {
448        Error::BadPubkeySlice(e)
449    }
450}
451
452impl From<bitcoin::address::ParseError> for Error {
453    fn from(e: bitcoin::address::ParseError) -> Error {
454        Error::AddrError(e)
455    }
456}
457
458impl From<descriptor::ConversionError> for Error {
459    fn from(e: descriptor::ConversionError) -> Error {
460        Error::Conversion(e)
461    }
462}
463
464fn errstr(s: &str) -> Error {
465    Error::Unexpected(s.to_owned())
466}
467
468// https://github.com/sipa/miniscript/pull/5 for discussion on this number
469const MAX_RECURSION_DEPTH: u32 = 402;
470// https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki
471const MAX_SCRIPT_SIZE: u32 = 10000;
472
473impl fmt::Display for Error {
474    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
475        match *self {
476            Error::InvalidOpcode(op) => write!(f, "invalid opcode {}", op),
477            Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok),
478            Error::InvalidPush(ref push) => {
479                write!(f, "invalid push ")?;
480                fmt::LowerHex::fmt(&bitcoin::hex::DisplayHex::as_hex(push), f)
481            },
482            Error::Script(ref e) => fmt::Display::fmt(e, f),
483            Error::AddrError(ref e) => fmt::Display::fmt(e, f),
484            Error::CmsTooManyKeys(n) => write!(f, "checkmultisig with {} keys", n),
485            Error::ExpectedChar(c) => write!(f, "expected {}", c),
486            Error::UnexpectedStart => f.write_str("unexpected start of script"),
487            Error::Unexpected(ref s) => write!(f, "unexpected «{}»", s),
488            Error::MultiColon(ref s) => write!(f, "«{}» has multiple instances of «:»", s),
489            Error::MultiAt(ref s) => write!(f, "«{}» has multiple instances of «@»", s),
490            Error::AtOutsideOr(ref s) => write!(f, "«{}» contains «@» in non-or() context", s),
491            Error::LikelyFalse => write!(f, "0 is not very likely (use «u:0»)"),
492            Error::UnknownWrapper(ch) => write!(f, "unknown wrapper «{}:»", ch),
493            Error::NonTopLevel(ref s) => write!(f, "non-T miniscript: {}", s),
494            Error::Trailing(ref s) => write!(f, "trailing tokens: {}", s),
495            Error::MissingHash(ref h) => write!(f, "missing preimage of hash {}", h),
496            Error::MissingSig(ref pk) => write!(f, "missing signature for key {:?}", pk),
497            Error::RelativeLocktimeNotMet(n) => {
498                write!(f, "required relative locktime CSV of {} blocks, not met", n)
499            }
500            Error::AbsoluteLocktimeNotMet(n) => write!(
501                f,
502                "required absolute locktime CLTV of {} blocks, not met",
503                n
504            ),
505            Error::CouldNotSatisfy => f.write_str("could not satisfy"),
506            Error::BadPubkey(ref e) => fmt::Display::fmt(e, f),
507            Error::BadPubkeySlice(ref e) => fmt::Display::fmt(e, f),
508            Error::TypeCheck(ref e) => write!(f, "typecheck: {}", e),
509            Error::BadDescriptor(ref e) => write!(f, "Invalid descriptor: {}", e),
510            Error::Secp(ref e) => fmt::Display::fmt(e, f),
511            Error::ContextError(ref e) => fmt::Display::fmt(e, f),
512            #[cfg(feature = "compiler")]
513            Error::CompilerError(ref e) => fmt::Display::fmt(e, f),
514            Error::PolicyError(ref e) => fmt::Display::fmt(e, f),
515            Error::LiftError(ref e) => fmt::Display::fmt(e, f),
516            Error::MaxRecursiveDepthExceeded => write!(
517                f,
518                "Recursive depth over {} not permitted",
519                MAX_RECURSION_DEPTH
520            ),
521            Error::ScriptSizeTooLarge => write!(
522                f,
523                "Standardness rules imply bitcoin than {} bytes",
524                MAX_SCRIPT_SIZE
525            ),
526            Error::NonStandardBareScript => write!(
527                f,
528                "Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) \
529                up to n=3 is invalid by standardness (bare).
530                "
531            ),
532            Error::AnalysisError(ref e) => e.fmt(f),
533            Error::ImpossibleSatisfaction => write!(f, "Impossible to satisfy Miniscript"),
534            Error::BareDescriptorAddr => write!(f, "Bare descriptors don't have address"),
535            Error::BtcError(ref e) => write!(f, " Bitcoin Miniscript Error {}", e),
536            Error::CovError(ref e) => write!(f, "Covenant Error: {}", e),
537            Error::PubKeyCtxError(ref pk, ctx) => {
538                write!(f, "Pubkey error: {} under {} scriptcontext", pk, ctx)
539            }
540            Error::MultiATooManyKeys(k) => write!(f, "MultiA too many keys {}", k),
541            Error::TaprootSpendInfoUnavialable => write!(f, "Taproot Spend Info not computed."),
542            Error::TrNoScriptCode => write!(f, "No script code for Tr descriptors"),
543            Error::TrNoExplicitScript => write!(f, "No script code for Tr descriptors"),
544            Error::MultipathDescLenMismatch => write!(f, "At least two BIP389 key expressions in the descriptor contain tuples of derivation indexes of different lengths"),
545            Error::Conversion(ref e) => e.fmt(f),
546            Error::UnsupportedAddressForPegin => write!(f, "Cannot create the address from the pegin descriptor, the federation descriptor is of an unsuppported type"),
547
548        }
549    }
550}
551
552impl error::Error for Error {
553    fn cause(&self) -> Option<&dyn error::Error> {
554        use self::Error::*;
555
556        match self {
557            InvalidOpcode(_)
558            | NonMinimalVerify(_)
559            | InvalidPush(_)
560            | CmsTooManyKeys(_)
561            | MultiATooManyKeys(_)
562            | ExpectedChar(_)
563            | UnexpectedStart
564            | Unexpected(_)
565            | MultiColon(_)
566            | MultiAt(_)
567            | AtOutsideOr(_)
568            | LikelyFalse
569            | UnknownWrapper(_)
570            | NonTopLevel(_)
571            | Trailing(_)
572            | MissingHash(_)
573            | MissingSig(_)
574            | RelativeLocktimeNotMet(_)
575            | AbsoluteLocktimeNotMet(_)
576            | CouldNotSatisfy
577            | TypeCheck(_)
578            | BadDescriptor(_)
579            | MaxRecursiveDepthExceeded
580            | ScriptSizeTooLarge
581            | NonStandardBareScript
582            | ImpossibleSatisfaction
583            | BareDescriptorAddr
584            | TaprootSpendInfoUnavialable
585            | TrNoScriptCode
586            | UnsupportedAddressForPegin
587            | TrNoExplicitScript => None,
588            MultipathDescLenMismatch => None,
589            BtcError(e) => Some(e),
590            CovError(e) => Some(e),
591            Script(_e) => None, // should be Some(e), but requires changes upstream
592            AddrError(e) => Some(e),
593            BadPubkey(e) => Some(e),
594            BadPubkeySlice(e) => Some(e),
595            Secp(e) => Some(e),
596            #[cfg(feature = "compiler")]
597            CompilerError(e) => Some(e),
598            PolicyError(e) => Some(e),
599            LiftError(e) => Some(e),
600            ContextError(e) => Some(e),
601            AnalysisError(e) => Some(e),
602            PubKeyCtxError(e, _) => Some(e),
603            Conversion(e) => Some(e),
604        }
605    }
606}
607
608#[doc(hidden)]
609#[cfg(feature = "compiler")]
610impl From<policy::compiler::CompilerError> for Error {
611    fn from(e: policy::compiler::CompilerError) -> Error {
612        Error::CompilerError(e)
613    }
614}
615
616#[doc(hidden)]
617impl From<policy::concrete::PolicyError> for Error {
618    fn from(e: policy::concrete::PolicyError) -> Error {
619        Error::PolicyError(e)
620    }
621}
622
623/// The size of an encoding of a number in Script
624pub fn script_num_size(n: usize) -> usize {
625    match n {
626        n if n <= 0x10 => 1,      // OP_n
627        n if n < 0x80 => 2,       // OP_PUSH1 <n>
628        n if n < 0x8000 => 3,     // OP_PUSH2 <n>
629        n if n < 0x800000 => 4,   // OP_PUSH3 <n>
630        n if n < 0x80000000 => 5, // OP_PUSH4 <n>
631        _ => 6,                   // OP_PUSH5 <n>
632    }
633}
634
635/// Returns the size of the smallest push opcode used to push a given number of bytes onto the stack
636///
637/// For sizes ≤ 75, there are dedicated single-byte opcodes, so the push size is one. Otherwise,
638/// if the size can fit into 1, 2 or 4 bytes, we use the `PUSHDATA{1,2,4}` opcode respectively,
639/// followed by the actual size encoded in that many bytes.
640fn push_opcode_size(script_size: usize) -> usize {
641    if script_size < 76 {
642        1
643    } else if script_size < 0x100 {
644        2
645    } else if script_size < 0x10000 {
646        3
647    } else {
648        5
649    }
650}
651
652/// An absolute locktime that implements `Ord`.
653#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
654pub struct AbsLockTime(locktime::LockTime);
655
656impl AbsLockTime {
657    /// Constructs an `AbsLockTime` from an nLockTime value or the argument to OP_CHEKCLOCKTIMEVERIFY.
658    pub fn from_consensus(n: u32) -> Self {
659        Self(locktime::LockTime::from_consensus(n))
660    }
661
662    /// Returns the inner `u32` value. This is the value used when creating this `LockTime`
663    /// i.e., `n OP_CHECKLOCKTIMEVERIFY` or nLockTime.
664    ///
665    /// This calls through to `locktime::LockTime::to_consensus_u32()` and the same usage warnings
666    /// apply.
667    pub fn to_consensus_u32(self) -> u32 {
668        self.0.to_consensus_u32()
669    }
670
671    /// Returns the inner `u32` value.
672    ///
673    /// Equivalent to `AbsLockTime::to_consensus_u32()`.
674    pub fn to_u32(self) -> u32 {
675        self.to_consensus_u32()
676    }
677}
678
679impl From<locktime::LockTime> for AbsLockTime {
680    fn from(lock_time: locktime::LockTime) -> Self {
681        Self(lock_time)
682    }
683}
684
685impl From<AbsLockTime> for locktime::LockTime {
686    fn from(lock_time: AbsLockTime) -> locktime::LockTime {
687        lock_time.0
688    }
689}
690
691impl cmp::PartialOrd for AbsLockTime {
692    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
693        Some(self.cmp(other))
694    }
695}
696
697impl cmp::Ord for AbsLockTime {
698    fn cmp(&self, other: &Self) -> cmp::Ordering {
699        let this = self.0.to_consensus_u32();
700        let that = other.0.to_consensus_u32();
701        this.cmp(&that)
702    }
703}
704
705impl fmt::Display for AbsLockTime {
706    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
707        fmt::Display::fmt(&self.0, f)
708    }
709}
710
711/// Helper function used by tests
712#[cfg(test)]
713fn hex_script(s: &str) -> elements::Script {
714    let v: Vec<u8> = bitcoin::hex::FromHex::from_hex(s).unwrap();
715    elements::Script::from(v)
716}
717
718#[cfg(test)]
719mod tests {
720    use std::str::FromStr;
721
722    use bitcoin::hashes::hash160;
723
724    use super::*;
725
726    #[test]
727    fn regression_bitcoin_key_hash() {
728        use bitcoin::PublicKey;
729
730        // Uncompressed key.
731        let pk = PublicKey::from_str(
732            "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"
733        ).unwrap();
734
735        let want = hash160::Hash::from_str("ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a").unwrap();
736        let got = pk.to_pubkeyhash(SigType::Ecdsa);
737        assert_eq!(got, want)
738    }
739
740    #[test]
741    fn regression_secp256k1_key_hash() {
742        use bitcoin::secp256k1::PublicKey;
743
744        // Compressed key.
745        let pk = PublicKey::from_str(
746            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
747        )
748        .unwrap();
749
750        let want = hash160::Hash::from_str("9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4").unwrap();
751        let got = pk.to_pubkeyhash(SigType::Ecdsa);
752        assert_eq!(got, want)
753    }
754
755    #[test]
756    fn regression_xonly_key_hash() {
757        use bitcoin::secp256k1::XOnlyPublicKey;
758
759        let pk = XOnlyPublicKey::from_str(
760            "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
761        )
762        .unwrap();
763
764        let want = hash160::Hash::from_str("eb8ac65f971ae688a94aeabf223506865e7e08f2").unwrap();
765        let got = pk.to_pubkeyhash(SigType::Schnorr);
766        assert_eq!(got, want)
767    }
768}