1#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
77#![cfg_attr(bench, feature(test))]
79#![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#![allow(clippy::iter_kv_map)] #![allow(clippy::manual_range_contains)] #![allow(unexpected_cfgs)] #[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
159pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
161 fn is_uncompressed(&self) -> bool { false }
163
164 fn is_x_only_key(&self) -> bool { false }
168
169 fn num_der_paths(&self) -> usize { 0 }
172
173 type Sha256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
176
177 type Hash256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
180
181 type Ripemd160: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
184
185 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 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; type Hash256 = String;
219 type Ripemd160 = String;
220 type Hash160 = String;
221}
222
223pub trait ToPublicKey: MiniscriptKey {
225 fn to_public_key(&self) -> bitcoin::PublicKey;
227
228 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 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 fn to_sha256(hash: &<Self as MiniscriptKey>::Sha256) -> sha256::Hash;
247
248 fn to_hash256(hash: &<Self as MiniscriptKey>::Hash256) -> hash256::Hash;
250
251 fn to_ripemd160(hash: &<Self as MiniscriptKey>::Ripemd160) -> ripemd160::Hash;
253
254 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 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
303pub trait Translator<P, Q, E>
306where
307 P: MiniscriptKey,
308 Q: MiniscriptKey,
309{
310 fn pk(&mut self, pk: &P) -> Result<Q, E>;
312
313 fn sha256(&mut self, sha256: &P::Sha256) -> Result<Q::Sha256, E>;
315
316 fn hash256(&mut self, hash256: &P::Hash256) -> Result<Q::Hash256, E>;
318
319 fn ripemd160(&mut self, ripemd160: &P::Ripemd160) -> Result<Q::Ripemd160, E>;
321
322 fn hash160(&mut self, hash160: &P::Hash160) -> Result<Q::Hash160, E>;
324}
325
326pub enum TranslateErr<E> {
328 TranslatorErr(E),
330 OuterError(Error),
334}
335
336impl<E> TranslateErr<E> {
337 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 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
377impl<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
387pub trait TranslatePk<P, Q>
390where
391 P: MiniscriptKey,
392 Q: MiniscriptKey,
393{
394 type Output;
396
397 fn translate_pk<T, E>(&self, translator: &mut T) -> Result<Self::Output, TranslateErr<E>>
400 where
401 T: Translator<P, Q, E>;
402}
403
404pub trait ForEachKey<Pk: MiniscriptKey> {
406 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
409 where
410 Pk: 'a;
411
412 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#[derive(Debug, PartialEq)]
425pub enum Error {
426 InvalidOpcode(Opcode),
428 NonMinimalVerify(String),
431 InvalidPush(Vec<u8>),
433 Script(script::Error),
435 AddrError(bitcoin::address::ParseError),
437 AddrP2shError(bitcoin::address::P2shError),
439 CmsTooManyKeys(u32),
441 MultiATooManyKeys(u64),
443 Unprintable(u8),
445 ExpectedChar(char),
447 UnexpectedStart,
449 Unexpected(String),
451 MultiColon(String),
453 AtOutsideOr(String),
455 UnknownWrapper(char),
457 NonTopLevel(String),
459 Trailing(String),
461 MissingSig(bitcoin::PublicKey),
463 CouldNotSatisfy,
465 TypeCheck(String),
467 BadDescriptor(String),
469 Secp(bitcoin::secp256k1::Error),
471 #[cfg(feature = "compiler")]
472 CompilerError(crate::policy::compiler::CompilerError),
474 PolicyError(policy::concrete::PolicyError),
476 LiftError(policy::LiftError),
478 ContextError(miniscript::context::ScriptContextError),
480 MaxRecursiveDepthExceeded,
482 NonStandardBareScript,
485 AnalysisError(miniscript::analyzable::AnalysisError),
487 ImpossibleSatisfaction,
489 BareDescriptorAddr,
491 PubKeyCtxError(miniscript::decode::KeyParseError, &'static str),
493 TrNoScriptCode,
495 MultipathDescLenMismatch,
498 AbsoluteLockTime(AbsLockTimeError),
500 RelativeLockTime(RelLockTimeError),
502 Threshold(ThresholdError),
504 ParseThreshold(ParseThresholdError),
506}
507
508const 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
667pub fn script_num_size(n: usize) -> usize {
669 match n {
670 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, }
677}
678
679fn 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#[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 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 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)] mod prelude {
755 #[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 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}