1#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
77#![cfg_attr(bench, feature(test))]
79#![warn(missing_docs)]
81#![deny(unsafe_code)]
82#![allow(clippy::iter_kv_map)] #![allow(clippy::manual_range_contains)] #![allow(unexpected_cfgs)] #[cfg(target_pointer_width = "16")]
88compile_error!(
89 "rust-miniscript currently only supports architectures with pointers wider than 16 bits"
90);
91
92pub use {bitcoin, hex};
93
94#[cfg(not(feature = "std"))]
95#[macro_use]
96extern crate alloc;
97
98#[cfg(any(feature = "std", test))]
99extern crate core;
100
101#[cfg(feature = "serde")]
102pub use serde;
103
104#[cfg(bench)]
105extern crate test;
106
107#[macro_use]
108mod macros;
109
110#[macro_use]
111mod pub_macros;
112
113#[cfg(bench)]
114mod benchmarks;
115mod blanket_traits;
116pub mod descriptor;
117mod error;
118pub mod expression;
119pub mod interpreter;
120pub mod iter;
121pub mod miniscript;
122pub mod plan;
123pub mod policy;
124mod primitives;
125pub mod psbt;
126
127#[cfg(test)]
128mod test_utils;
129mod util;
130
131use core::{fmt, hash, str};
132
133use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
134
135pub use crate::blanket_traits::FromStrKey;
136pub use crate::descriptor::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey};
137pub use crate::error::ParseError;
138pub use crate::expression::{ParseNumError, ParseThresholdError, ParseTreeError};
139pub use crate::interpreter::Interpreter;
140pub use crate::miniscript::analyzable::{AnalysisError, ExtParams};
141pub use crate::miniscript::context::{BareCtx, Legacy, ScriptContext, Segwitv0, SigType, Tap};
142pub use crate::miniscript::decode::Terminal;
143pub use crate::miniscript::satisfy::{Preimage32, Satisfier};
144pub use crate::miniscript::{hash256, Miniscript};
145use crate::prelude::*;
146pub use crate::primitives::absolute_locktime::{AbsLockTime, AbsLockTimeError};
147pub use crate::primitives::relative_locktime::{RelLockTime, RelLockTimeError};
148pub use crate::primitives::threshold::{Threshold, ThresholdError};
149
150pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
152 fn is_uncompressed(&self) -> bool { false }
154
155 fn is_x_only_key(&self) -> bool { false }
159
160 fn num_der_paths(&self) -> usize { 0 }
163
164 type Sha256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
167
168 type Hash256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
171
172 type Ripemd160: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
175
176 type Hash160: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
179}
180
181impl MiniscriptKey for bitcoin::secp256k1::PublicKey {
182 type Sha256 = sha256::Hash;
183 type Hash256 = hash256::Hash;
184 type Ripemd160 = ripemd160::Hash;
185 type Hash160 = hash160::Hash;
186}
187
188impl MiniscriptKey for bitcoin::PublicKey {
189 fn is_uncompressed(&self) -> bool { !self.compressed }
191
192 type Sha256 = sha256::Hash;
193 type Hash256 = hash256::Hash;
194 type Ripemd160 = ripemd160::Hash;
195 type Hash160 = hash160::Hash;
196}
197
198impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
199 type Sha256 = sha256::Hash;
200 type Hash256 = hash256::Hash;
201 type Ripemd160 = ripemd160::Hash;
202 type Hash160 = hash160::Hash;
203
204 fn is_x_only_key(&self) -> bool { true }
205}
206
207impl MiniscriptKey for String {
208 type Sha256 = String; type Hash256 = String;
210 type Ripemd160 = String;
211 type Hash160 = String;
212}
213
214pub trait ToPublicKey: MiniscriptKey {
216 fn to_public_key(&self) -> bitcoin::PublicKey;
218
219 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 fn to_pubkeyhash(&self, sig_type: SigType) -> hash160::Hash {
230 match sig_type {
231 SigType::Ecdsa => hash160::Hash::hash(&self.to_public_key().to_bytes()),
232 SigType::Schnorr => hash160::Hash::hash(&self.to_x_only_pubkey().serialize()),
233 }
234 }
235
236 fn to_sha256(hash: &<Self as MiniscriptKey>::Sha256) -> sha256::Hash;
238
239 fn to_hash256(hash: &<Self as MiniscriptKey>::Hash256) -> hash256::Hash;
241
242 fn to_ripemd160(hash: &<Self as MiniscriptKey>::Ripemd160) -> ripemd160::Hash;
244
245 fn to_hash160(hash: &<Self as MiniscriptKey>::Hash160) -> hash160::Hash;
247}
248
249impl ToPublicKey for bitcoin::PublicKey {
250 fn to_public_key(&self) -> bitcoin::PublicKey { *self }
251
252 fn to_sha256(hash: &sha256::Hash) -> sha256::Hash { *hash }
253
254 fn to_hash256(hash: &hash256::Hash) -> hash256::Hash { *hash }
255
256 fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash { *hash }
257
258 fn to_hash160(hash: &hash160::Hash) -> hash160::Hash { *hash }
259}
260
261impl ToPublicKey for bitcoin::secp256k1::PublicKey {
262 fn to_public_key(&self) -> bitcoin::PublicKey { bitcoin::PublicKey::new(*self) }
263
264 fn to_sha256(hash: &sha256::Hash) -> sha256::Hash { *hash }
265
266 fn to_hash256(hash: &hash256::Hash) -> hash256::Hash { *hash }
267
268 fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash { *hash }
269
270 fn to_hash160(hash: &hash160::Hash) -> hash160::Hash { *hash }
271}
272
273impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
274 fn to_public_key(&self) -> bitcoin::PublicKey {
275 let mut data: Vec<u8> = vec![0x02];
278 data.extend(self.serialize().iter());
279 bitcoin::PublicKey::from_slice(&data)
280 .expect("Failed to construct 33 Publickey from 0x02 appended x-only key")
281 }
282
283 fn to_x_only_pubkey(&self) -> bitcoin::secp256k1::XOnlyPublicKey { *self }
284
285 fn to_sha256(hash: &sha256::Hash) -> sha256::Hash { *hash }
286
287 fn to_hash256(hash: &hash256::Hash) -> hash256::Hash { *hash }
288
289 fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash { *hash }
290
291 fn to_hash160(hash: &hash160::Hash) -> hash160::Hash { *hash }
292}
293
294pub trait Translator<P: MiniscriptKey> {
297 type TargetPk: MiniscriptKey;
299 type Error;
301
302 fn pk(&mut self, pk: &P) -> Result<Self::TargetPk, Self::Error>;
304
305 fn sha256(
307 &mut self,
308 sha256: &P::Sha256,
309 ) -> Result<<Self::TargetPk as MiniscriptKey>::Sha256, Self::Error>;
310
311 fn hash256(
313 &mut self,
314 hash256: &P::Hash256,
315 ) -> Result<<Self::TargetPk as MiniscriptKey>::Hash256, Self::Error>;
316
317 fn ripemd160(
319 &mut self,
320 ripemd160: &P::Ripemd160,
321 ) -> Result<<Self::TargetPk as MiniscriptKey>::Ripemd160, Self::Error>;
322
323 fn hash160(
325 &mut self,
326 hash160: &P::Hash160,
327 ) -> Result<<Self::TargetPk as MiniscriptKey>::Hash160, Self::Error>;
328}
329
330pub enum TranslateErr<E> {
332 TranslatorErr(E),
334 OuterError(Error),
338}
339
340impl<E> TranslateErr<E> {
341 pub fn expect_translator_err(self, msg: &str) -> E {
357 match self {
358 Self::TranslatorErr(v) => v,
359 Self::OuterError(ref e) => {
360 panic!("Unexpected Miniscript error when translating: {}\nMessage: {}", e, msg)
361 }
362 }
363 }
364}
365
366impl TranslateErr<core::convert::Infallible> {
367 pub fn into_outer_err(self) -> Error {
373 match self {
374 Self::TranslatorErr(impossible) => match impossible {},
375 Self::OuterError(e) => e,
376 }
377 }
378}
379
380impl TranslateErr<Error> {
381 pub fn flatten(self) -> Error {
384 match self {
385 Self::TranslatorErr(e) => e,
386 Self::OuterError(e) => e,
387 }
388 }
389}
390
391impl<E> From<E> for TranslateErr<E> {
392 fn from(v: E) -> Self { Self::TranslatorErr(v) }
393}
394
395impl<E: fmt::Debug> fmt::Debug for TranslateErr<E> {
397 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
398 match self {
399 Self::TranslatorErr(e) => write!(f, "TranslatorErr({:?})", e),
400 Self::OuterError(e) => write!(f, "OuterError({:?})", e),
401 }
402 }
403}
404
405#[deprecated(since = "TBD", note = "This trait no longer needs to be imported.")]
408pub trait TranslatePk<P, Q>
409where
410 P: MiniscriptKey,
411 Q: MiniscriptKey,
412{
413}
414
415pub trait ForEachKey<Pk: MiniscriptKey> {
417 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
420 where
421 Pk: 'a;
422
423 fn for_any_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
426 where
427 Pk: 'a,
428 {
429 !self.for_each_key(|key| !pred(key))
430 }
431}
432
433#[derive(Debug)]
436pub enum Error {
437 ScriptLexer(crate::miniscript::lex::Error),
439 AddrError(bitcoin::address::ParseError),
441 AddrP2shError(bitcoin::address::P2shError),
443 UnexpectedStart,
445 Unexpected(String),
447 UnknownWrapper(char),
449 NonTopLevel(String),
451 Trailing(String),
453 MissingSig(bitcoin::PublicKey),
455 CouldNotSatisfy,
457 TypeCheck(String),
459 Secp(bitcoin::secp256k1::Error),
461 #[cfg(feature = "compiler")]
462 CompilerError(crate::policy::compiler::CompilerError),
464 ConcretePolicy(policy::concrete::PolicyError),
466 LiftError(policy::LiftError),
468 ContextError(miniscript::context::ScriptContextError),
470 TapTreeDepthError(crate::descriptor::TapTreeDepthError),
472 MaxRecursiveDepthExceeded,
474 NonStandardBareScript,
477 AnalysisError(miniscript::analyzable::AnalysisError),
479 ImpossibleSatisfaction,
481 BareDescriptorAddr,
483 PubKeyCtxError(miniscript::decode::KeyError, &'static str),
485 TrNoScriptCode,
487 MultipathDescLenMismatch,
490 AbsoluteLockTime(AbsLockTimeError),
492 RelativeLockTime(RelLockTimeError),
494 Threshold(ThresholdError),
496 ParseThreshold(ParseThresholdError),
498 Parse(ParseError),
500}
501
502#[doc(hidden)] impl From<ParseThresholdError> for Error {
504 fn from(e: ParseThresholdError) -> Self { Self::ParseThreshold(e) }
505}
506
507const MAX_RECURSION_DEPTH: u32 = 402;
509
510impl fmt::Display for Error {
511 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
512 match *self {
513 Error::ScriptLexer(ref e) => e.fmt(f),
514 Error::AddrError(ref e) => fmt::Display::fmt(e, f),
515 Error::AddrP2shError(ref e) => fmt::Display::fmt(e, f),
516 Error::UnexpectedStart => f.write_str("unexpected start of script"),
517 Error::Unexpected(ref s) => write!(f, "unexpected «{}»", s),
518 Error::UnknownWrapper(ch) => write!(f, "unknown wrapper «{}:»", ch),
519 Error::NonTopLevel(ref s) => write!(f, "non-T miniscript: {}", s),
520 Error::Trailing(ref s) => write!(f, "trailing tokens: {}", s),
521 Error::MissingSig(ref pk) => write!(f, "missing signature for key {:?}", pk),
522 Error::CouldNotSatisfy => f.write_str("could not satisfy"),
523 Error::TypeCheck(ref e) => write!(f, "typecheck: {}", e),
524 Error::Secp(ref e) => fmt::Display::fmt(e, f),
525 Error::ContextError(ref e) => fmt::Display::fmt(e, f),
526 Error::TapTreeDepthError(ref e) => fmt::Display::fmt(e, f),
527 #[cfg(feature = "compiler")]
528 Error::CompilerError(ref e) => fmt::Display::fmt(e, f),
529 Error::ConcretePolicy(ref e) => fmt::Display::fmt(e, f),
530 Error::LiftError(ref e) => fmt::Display::fmt(e, f),
531 Error::MaxRecursiveDepthExceeded => write!(
532 f,
533 "Recursive depth over {} not permitted",
534 MAX_RECURSION_DEPTH
535 ),
536 Error::NonStandardBareScript => write!(
537 f,
538 "Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) \
539 up to n=3 is invalid by standardness (bare).
540 "
541 ),
542 Error::AnalysisError(ref e) => e.fmt(f),
543 Error::ImpossibleSatisfaction => write!(f, "Impossible to satisfy Miniscript"),
544 Error::BareDescriptorAddr => write!(f, "Bare descriptors don't have address"),
545 Error::PubKeyCtxError(ref pk, ref ctx) => {
546 write!(f, "Pubkey error: {} under {} scriptcontext", pk, ctx)
547 }
548 Error::TrNoScriptCode => write!(f, "No script code for Tr descriptors"),
549 Error::MultipathDescLenMismatch => write!(f, "At least two BIP389 key expressions in the descriptor contain tuples of derivation indexes of different lengths"),
550 Error::AbsoluteLockTime(ref e) => e.fmt(f),
551 Error::RelativeLockTime(ref e) => e.fmt(f),
552 Error::Threshold(ref e) => e.fmt(f),
553 Error::ParseThreshold(ref e) => e.fmt(f),
554 Error::Parse(ref e) => e.fmt(f),
555 }
556 }
557}
558
559#[cfg(feature = "std")]
560impl std::error::Error for Error {
561 fn cause(&self) -> Option<&dyn std::error::Error> {
562 use self::Error::*;
563
564 match self {
565 UnexpectedStart
566 | Unexpected(_)
567 | UnknownWrapper(_)
568 | NonTopLevel(_)
569 | Trailing(_)
570 | MissingSig(_)
571 | CouldNotSatisfy
572 | TypeCheck(_)
573 | MaxRecursiveDepthExceeded
574 | NonStandardBareScript
575 | ImpossibleSatisfaction
576 | BareDescriptorAddr
577 | TrNoScriptCode
578 | MultipathDescLenMismatch => None,
579 ScriptLexer(e) => Some(e),
580 AddrError(e) => Some(e),
581 AddrP2shError(e) => Some(e),
582 Secp(e) => Some(e),
583 #[cfg(feature = "compiler")]
584 CompilerError(e) => Some(e),
585 ConcretePolicy(e) => Some(e),
586 LiftError(e) => Some(e),
587 ContextError(e) => Some(e),
588 TapTreeDepthError(e) => Some(e),
589 AnalysisError(e) => Some(e),
590 PubKeyCtxError(e, _) => Some(e),
591 AbsoluteLockTime(e) => Some(e),
592 RelativeLockTime(e) => Some(e),
593 Threshold(e) => Some(e),
594 ParseThreshold(e) => Some(e),
595 Parse(e) => Some(e),
596 }
597 }
598}
599
600#[doc(hidden)]
601impl From<miniscript::lex::Error> for Error {
602 fn from(e: miniscript::lex::Error) -> Error { Error::ScriptLexer(e) }
603}
604
605#[doc(hidden)]
606impl From<miniscript::types::Error> for Error {
607 fn from(e: miniscript::types::Error) -> Error { Error::TypeCheck(e.to_string()) }
608}
609
610#[doc(hidden)]
611impl From<policy::LiftError> for Error {
612 fn from(e: policy::LiftError) -> Error { Error::LiftError(e) }
613}
614
615#[doc(hidden)]
616impl From<crate::descriptor::TapTreeDepthError> for Error {
617 fn from(e: crate::descriptor::TapTreeDepthError) -> Error { Error::TapTreeDepthError(e) }
618}
619
620#[doc(hidden)]
621impl From<miniscript::context::ScriptContextError> for Error {
622 fn from(e: miniscript::context::ScriptContextError) -> Error { Error::ContextError(e) }
623}
624
625#[doc(hidden)]
626impl From<miniscript::analyzable::AnalysisError> for Error {
627 fn from(e: miniscript::analyzable::AnalysisError) -> Error { Error::AnalysisError(e) }
628}
629
630#[doc(hidden)]
631impl From<bitcoin::secp256k1::Error> for Error {
632 fn from(e: bitcoin::secp256k1::Error) -> Error { Error::Secp(e) }
633}
634
635#[doc(hidden)]
636impl From<bitcoin::address::ParseError> for Error {
637 fn from(e: bitcoin::address::ParseError) -> Error { Error::AddrError(e) }
638}
639
640#[doc(hidden)]
641impl From<bitcoin::address::P2shError> for Error {
642 fn from(e: bitcoin::address::P2shError) -> Error { Error::AddrP2shError(e) }
643}
644
645#[doc(hidden)]
646#[cfg(feature = "compiler")]
647impl From<crate::policy::compiler::CompilerError> for Error {
648 fn from(e: crate::policy::compiler::CompilerError) -> Error { Error::CompilerError(e) }
649}
650
651pub fn script_num_size(n: usize) -> usize {
653 match n {
654 n if n <= 0x10 => 1, n if n < 0x80 => 2, n if n < 0x8000 => 3, n if n < 0x800000 => 4, n if n < 0x80000000 => 5, _ => 6, }
661}
662
663fn push_opcode_size(script_size: usize) -> usize {
669 if script_size < 76 {
670 1
671 } else if script_size < 0x100 {
672 2
673 } else if script_size < 0x10000 {
674 3
675 } else {
676 5
677 }
678}
679
680#[cfg(test)]
682fn hex_script(s: &str) -> bitcoin::ScriptBuf { bitcoin::ScriptBuf::from_hex(s).unwrap() }
683
684#[cfg(test)]
685mod tests {
686 use core::str::FromStr;
687
688 use super::*;
689
690 #[test]
691 fn regression_bitcoin_key_hash() {
692 use bitcoin::PublicKey;
693
694 let pk = PublicKey::from_str(
696 "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"
697 ).unwrap();
698
699 let want = hash160::Hash::from_str("ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a").unwrap();
700 let got = pk.to_pubkeyhash(SigType::Ecdsa);
701 assert_eq!(got, want)
702 }
703
704 #[test]
705 fn regression_secp256k1_key_hash() {
706 use bitcoin::secp256k1::PublicKey;
707
708 let pk = PublicKey::from_str(
710 "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
711 )
712 .unwrap();
713
714 let want = hash160::Hash::from_str("9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4").unwrap();
715 let got = pk.to_pubkeyhash(SigType::Ecdsa);
716 assert_eq!(got, want)
717 }
718
719 #[test]
720 fn regression_xonly_key_hash() {
721 use bitcoin::secp256k1::XOnlyPublicKey;
722
723 let pk = XOnlyPublicKey::from_str(
724 "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
725 )
726 .unwrap();
727
728 let want = hash160::Hash::from_str("eb8ac65f971ae688a94aeabf223506865e7e08f2").unwrap();
729 let got = pk.to_pubkeyhash(SigType::Schnorr);
730 assert_eq!(got, want)
731 }
732}
733
734#[allow(unused_imports)] mod prelude {
736 #[cfg(all(not(feature = "std"), not(test)))]
739 mod mutex {
740 use core::cell::{RefCell, RefMut};
741 use core::ops::{Deref, DerefMut};
742
743 pub type LockResult<Guard> = Result<Guard, ()>;
744
745 pub struct Mutex<T: ?Sized> {
749 inner: RefCell<T>,
750 }
751
752 #[must_use = "if unused the Mutex will immediately unlock"]
753 pub struct MutexGuard<'a, T: ?Sized + 'a> {
754 lock: RefMut<'a, T>,
755 }
756
757 impl<T: ?Sized> Deref for MutexGuard<'_, T> {
758 type Target = T;
759
760 fn deref(&self) -> &T { self.lock.deref() }
761 }
762
763 impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
764 fn deref_mut(&mut self) -> &mut T { self.lock.deref_mut() }
765 }
766
767 impl<T> Mutex<T> {
768 pub fn new(inner: T) -> Mutex<T> { Mutex { inner: RefCell::new(inner) } }
769
770 pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
771 Ok(MutexGuard { lock: self.inner.borrow_mut() })
772 }
773 }
774 }
775
776 #[cfg(all(not(feature = "std"), not(test)))]
777 pub use alloc::{
778 borrow::{Borrow, Cow, ToOwned},
779 boxed::Box,
780 collections::{btree_map, vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap},
781 rc, slice,
782 string::{String, ToString},
783 sync,
784 vec::Vec,
785 };
786 #[cfg(any(feature = "std", test))]
787 pub use std::{
788 borrow::{Borrow, Cow, ToOwned},
789 boxed::Box,
790 collections::{
791 btree_map, vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet,
792 },
793 rc, slice,
794 string::{String, ToString},
795 sync,
796 sync::Mutex,
797 vec::Vec,
798 };
799
800 #[cfg(all(not(feature = "std"), not(test)))]
801 pub use self::mutex::Mutex;
802}