1#![cfg_attr(all(test, feature = "unstable"), feature(test))]
91#![deny(unsafe_code)]
93#![deny(non_upper_case_globals)]
94#![deny(non_camel_case_types)]
95#![deny(non_snake_case)]
96#![deny(unused_mut)]
97#![deny(dead_code)]
98#![deny(unused_imports)]
99#![deny(missing_docs)]
100
101pub extern crate bitcoin;
102#[cfg(feature = "schemars")]
103pub extern crate schemars;
104#[cfg(feature = "serde")]
105pub extern crate serde;
106#[cfg(all(test, feature = "unstable"))]
107extern crate test;
108
109#[macro_use]
110mod macros;
111
112pub mod descriptor;
113pub mod expression;
114pub mod interpreter;
115pub mod miniscript;
116pub mod policy;
117pub mod psbt;
118
119mod util;
120
121use std::io::Write;
122use std::str::FromStr;
123use std::{error, fmt, hash, str};
124
125use bitcoin::blockdata::{opcodes, script};
126use bitcoin::hashes::{hash160, sha256, Hash};
127
128pub use descriptor::{Descriptor, DescriptorPublicKey, DescriptorTrait};
129pub use interpreter::Interpreter;
130pub use miniscript::context::{BareCtx, Legacy, ScriptContext, Segwitv0, Tap};
131pub use miniscript::decode::Terminal;
132pub use miniscript::satisfy::{Preimage32, Satisfier};
133pub use miniscript::Miniscript;
134
135pub use descriptor::pretaproot::{traits::PreTaprootDescriptorTrait, PreTaprootDescriptor};
136
137pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
139 fn is_uncompressed(&self) -> bool {
142 false
143 }
144
145 fn is_x_only_key(&self) -> bool {
151 false
152 }
153
154 type Hash: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
156
157 fn to_pubkeyhash(&self) -> Self::Hash;
159}
160
161impl MiniscriptKey for bitcoin::secp256k1::PublicKey {
162 fn is_uncompressed(&self) -> bool {
164 false
165 }
166
167 type Hash = hash160::Hash;
168
169 fn to_pubkeyhash(&self) -> Self::Hash {
170 let mut engine = hash160::Hash::engine();
171 engine
172 .write_all(&self.serialize())
173 .expect("engines don't error");
174 hash160::Hash::from_engine(engine)
175 }
176}
177
178impl MiniscriptKey for bitcoin::PublicKey {
179 fn is_uncompressed(&self) -> bool {
182 !self.compressed
183 }
184
185 type Hash = hash160::Hash;
186
187 fn to_pubkeyhash(&self) -> Self::Hash {
188 let mut engine = hash160::Hash::engine();
189 self.write_into(&mut engine).expect("engines don't error");
190 hash160::Hash::from_engine(engine)
191 }
192}
193
194impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
195 type Hash = hash160::Hash;
196
197 fn to_pubkeyhash(&self) -> Self::Hash {
198 hash160::Hash::hash(&self.serialize())
199 }
200
201 fn is_x_only_key(&self) -> bool {
202 true
203 }
204}
205
206impl MiniscriptKey for String {
207 type Hash = String;
208
209 fn to_pubkeyhash(&self) -> Self::Hash {
210 format!("{}", &self)
211 }
212}
213
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 hash_to_hash160(hash: &<Self as MiniscriptKey>::Hash) -> hash160::Hash;
232}
233
234impl ToPublicKey for bitcoin::PublicKey {
235 fn to_public_key(&self) -> bitcoin::PublicKey {
236 *self
237 }
238
239 fn hash_to_hash160(hash: &hash160::Hash) -> hash160::Hash {
240 *hash
241 }
242}
243
244impl ToPublicKey for bitcoin::secp256k1::PublicKey {
245 fn to_public_key(&self) -> bitcoin::PublicKey {
246 bitcoin::PublicKey::new(*self)
247 }
248
249 fn hash_to_hash160(hash: &hash160::Hash) -> hash160::Hash {
250 *hash
251 }
252}
253
254impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
255 fn to_public_key(&self) -> bitcoin::PublicKey {
256 let mut data: Vec<u8> = vec![0x02];
259 data.extend(self.serialize().iter());
260 bitcoin::PublicKey::from_slice(&data)
261 .expect("Failed to construct 33 Publickey from 0x02 appended x-only key")
262 }
263
264 fn to_x_only_pubkey(&self) -> bitcoin::secp256k1::XOnlyPublicKey {
265 *self
266 }
267
268 fn hash_to_hash160(hash: &hash160::Hash) -> hash160::Hash {
269 *hash
270 }
271}
272
273#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
275pub struct DummyKey;
276
277impl str::FromStr for DummyKey {
278 type Err = &'static str;
279 fn from_str(x: &str) -> Result<DummyKey, &'static str> {
280 if x.is_empty() {
281 Ok(DummyKey)
282 } else {
283 Err("non empty dummy key")
284 }
285 }
286}
287
288impl MiniscriptKey for DummyKey {
289 type Hash = DummyKeyHash;
290
291 fn to_pubkeyhash(&self) -> Self::Hash {
292 DummyKeyHash
293 }
294}
295
296impl hash::Hash for DummyKey {
297 fn hash<H: hash::Hasher>(&self, state: &mut H) {
298 "DummyKey".hash(state);
299 }
300}
301
302impl fmt::Display for DummyKey {
303 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
304 f.write_str("")
305 }
306}
307
308impl ToPublicKey for DummyKey {
309 fn to_public_key(&self) -> bitcoin::PublicKey {
310 bitcoin::PublicKey::from_str(
311 "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352",
312 )
313 .unwrap()
314 }
315
316 fn hash_to_hash160(_: &DummyKeyHash) -> hash160::Hash {
317 hash160::Hash::from_str("f54a5851e9372b87810a8e60cdd2e7cfd80b6e31").unwrap()
318 }
319}
320
321#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
323pub struct DummyKeyHash;
324
325impl str::FromStr for DummyKeyHash {
326 type Err = &'static str;
327 fn from_str(x: &str) -> Result<DummyKeyHash, &'static str> {
328 if x.is_empty() {
329 Ok(DummyKeyHash)
330 } else {
331 Err("non empty dummy key")
332 }
333 }
334}
335
336impl fmt::Display for DummyKeyHash {
337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338 f.write_str("")
339 }
340}
341
342impl hash::Hash for DummyKeyHash {
343 fn hash<H: hash::Hasher>(&self, state: &mut H) {
344 "DummyKeyHash".hash(state);
345 }
346}
347
348pub trait TranslatePk<P: MiniscriptKey, Q: MiniscriptKey> {
353 type Output;
355
356 fn translate_pk<Fpk, Fpkh, E>(
360 &self,
361 translatefpk: Fpk,
362 translatefpkh: Fpkh,
363 ) -> Result<Self::Output, E>
364 where
365 Fpk: FnMut(&P) -> Result<Q, E>,
366 Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>;
367
368 fn translate_pk_infallible<Fpk, Fpkh>(
370 &self,
371 mut translatefpk: Fpk,
372 mut translatefpkh: Fpkh,
373 ) -> Self::Output
374 where
375 Fpk: FnMut(&P) -> Q,
376 Fpkh: FnMut(&P::Hash) -> Q::Hash,
377 {
378 self.translate_pk::<_, _, ()>(|pk| Ok(translatefpk(pk)), |pkh| Ok(translatefpkh(pkh)))
379 .expect("infallible translation function")
380 }
381}
382
383pub trait TranslatePk1<P: MiniscriptKey, Q: MiniscriptKey<Hash = P::Hash>>:
386 TranslatePk<P, Q>
387{
388 fn translate_pk1<Fpk, E>(
391 &self,
392 translatefpk: Fpk,
393 ) -> Result<<Self as TranslatePk<P, Q>>::Output, E>
394 where
395 Fpk: FnMut(&P) -> Result<Q, E>,
396 {
397 self.translate_pk(translatefpk, |h| Ok(h.clone()))
398 }
399
400 fn translate_pk1_infallible<Fpk: FnMut(&P) -> Q>(
403 &self,
404 translatefpk: Fpk,
405 ) -> <Self as TranslatePk<P, Q>>::Output {
406 self.translate_pk_infallible(translatefpk, P::Hash::clone)
407 }
408}
409impl<P: MiniscriptKey, Q: MiniscriptKey<Hash = P::Hash>, T: TranslatePk<P, Q>> TranslatePk1<P, Q>
410 for T
411{
412}
413
414pub trait TranslatePk2<P: MiniscriptKey<Hash = P>, Q: MiniscriptKey>: TranslatePk<P, Q> {
417 fn translate_pk2<Fpk: Fn(&P) -> Result<Q, E>, E>(
420 &self,
421 translatefpk: Fpk,
422 ) -> Result<<Self as TranslatePk<P, Q>>::Output, E> {
423 self.translate_pk(&translatefpk, |h| {
424 translatefpk(h).map(|q| q.to_pubkeyhash())
425 })
426 }
427
428 fn translate_pk2_infallible<Fpk: Fn(&P) -> Q>(
431 &self,
432 translatefpk: Fpk,
433 ) -> <Self as TranslatePk<P, Q>>::Output {
434 self.translate_pk_infallible(&translatefpk, |h| translatefpk(h).to_pubkeyhash())
435 }
436}
437impl<P: MiniscriptKey<Hash = P>, Q: MiniscriptKey, T: TranslatePk<P, Q>> TranslatePk2<P, Q> for T {}
438
439pub trait TranslatePk3<P: MiniscriptKey + ToPublicKey, Q: MiniscriptKey<Hash = hash160::Hash>>:
442 TranslatePk<P, Q>
443{
444 fn translate_pk3<Fpk, E>(
447 &self,
448 translatefpk: Fpk,
449 ) -> Result<<Self as TranslatePk<P, Q>>::Output, E>
450 where
451 Fpk: FnMut(&P) -> Result<Q, E>,
452 {
453 self.translate_pk(translatefpk, |h| Ok(P::hash_to_hash160(h)))
454 }
455
456 fn translate_pk3_infallible<Fpk: FnMut(&P) -> Q>(
459 &self,
460 translatefpk: Fpk,
461 ) -> <Self as TranslatePk<P, Q>>::Output {
462 self.translate_pk_infallible(translatefpk, P::hash_to_hash160)
463 }
464}
465impl<
466 P: MiniscriptKey + ToPublicKey,
467 Q: MiniscriptKey<Hash = hash160::Hash>,
468 T: TranslatePk<P, Q>,
469 > TranslatePk3<P, Q> for T
470{
471}
472
473pub enum ForEach<'a, Pk: MiniscriptKey + 'a> {
475 Key(&'a Pk),
477 Hash(&'a Pk::Hash),
479}
480
481impl<'a, Pk: MiniscriptKey<Hash = Pk>> ForEach<'a, Pk> {
482 pub fn as_key(&self) -> &'a Pk {
484 match *self {
485 ForEach::Key(ref_key) => ref_key,
486 ForEach::Hash(ref_key) => ref_key,
487 }
488 }
489}
490
491pub trait ForEachKey<Pk: MiniscriptKey> {
493 fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, pred: F) -> bool
496 where
497 Pk: 'a,
498 Pk::Hash: 'a;
499
500 fn for_any_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, mut pred: F) -> bool
503 where
504 Pk: 'a,
505 Pk::Hash: 'a,
506 {
507 !self.for_each_key(|key| !pred(key))
508 }
509}
510
511#[derive(Debug)]
514pub enum Error {
515 InvalidOpcode(opcodes::All),
517 NonMinimalVerify(String),
520 InvalidPush(Vec<u8>),
522 Script(script::Error),
524 AddrError(bitcoin::util::address::Error),
526 CmsTooManyKeys(u32),
528 MultiATooManyKeys(u32),
530 Unprintable(u8),
532 ExpectedChar(char),
534 UnexpectedStart,
536 Unexpected(String),
538 MultiColon(String),
540 MultiAt(String),
542 AtOutsideOr(String),
544 LikelyFalse,
546 UnknownWrapper(char),
548 NonTopLevel(String),
550 Trailing(String),
552 BadPubkey(bitcoin::util::key::Error),
554 MissingHash(sha256::Hash),
556 MissingSig(bitcoin::PublicKey),
558 RelativeLocktimeNotMet(u32),
560 AbsoluteLocktimeNotMet(u32),
562 CouldNotSatisfy,
564 TypeCheck(String),
566 BadDescriptor(String),
568 Secp(bitcoin::secp256k1::Error),
570 #[cfg(feature = "compiler")]
571 CompilerError(policy::compiler::CompilerError),
573 PolicyError(policy::concrete::PolicyError),
575 LiftError(policy::LiftError),
577 ContextError(miniscript::context::ScriptContextError),
579 MaxRecursiveDepthExceeded,
581 ScriptSizeTooLarge,
583 NonStandardBareScript,
586 AnalysisError(miniscript::analyzable::AnalysisError),
588 ImpossibleSatisfaction,
590 BareDescriptorAddr,
592 PubKeyCtxError(miniscript::decode::KeyParseError, &'static str),
594 TaprootSpendInfoUnavialable,
596 TrNoScriptCode,
598 TrNoExplicitScript,
600}
601
602#[doc(hidden)]
603impl<Pk, Ctx> From<miniscript::types::Error<Pk, Ctx>> for Error
604where
605 Pk: MiniscriptKey,
606 Ctx: ScriptContext,
607{
608 fn from(e: miniscript::types::Error<Pk, Ctx>) -> Error {
609 Error::TypeCheck(e.to_string())
610 }
611}
612
613#[doc(hidden)]
614impl From<policy::LiftError> for Error {
615 fn from(e: policy::LiftError) -> Error {
616 Error::LiftError(e)
617 }
618}
619
620#[doc(hidden)]
621impl From<miniscript::context::ScriptContextError> for Error {
622 fn from(e: miniscript::context::ScriptContextError) -> Error {
623 Error::ContextError(e)
624 }
625}
626
627#[doc(hidden)]
628impl From<miniscript::analyzable::AnalysisError> for Error {
629 fn from(e: miniscript::analyzable::AnalysisError) -> Error {
630 Error::AnalysisError(e)
631 }
632}
633
634#[doc(hidden)]
635impl From<bitcoin::secp256k1::Error> for Error {
636 fn from(e: bitcoin::secp256k1::Error) -> Error {
637 Error::Secp(e)
638 }
639}
640
641#[doc(hidden)]
642impl From<bitcoin::util::address::Error> for Error {
643 fn from(e: bitcoin::util::address::Error) -> Error {
644 Error::AddrError(e)
645 }
646}
647
648fn errstr(s: &str) -> Error {
649 Error::Unexpected(s.to_owned())
650}
651
652impl error::Error for Error {
653 fn cause(&self) -> Option<&dyn error::Error> {
654 match *self {
655 Error::BadPubkey(ref e) => Some(e),
656 _ => None,
657 }
658 }
659}
660
661const MAX_RECURSION_DEPTH: u32 = 402;
663const MAX_SCRIPT_SIZE: u32 = 10000;
665
666impl fmt::Display for Error {
667 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
668 match *self {
669 Error::InvalidOpcode(op) => write!(f, "invalid opcode {}", op),
670 Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok),
671 Error::InvalidPush(ref push) => write!(f, "invalid push {:?}", push), Error::Script(ref e) => fmt::Display::fmt(e, f),
673 Error::AddrError(ref e) => fmt::Display::fmt(e, f),
674 Error::CmsTooManyKeys(n) => write!(f, "checkmultisig with {} keys", n),
675 Error::Unprintable(x) => write!(f, "unprintable character 0x{:02x}", x),
676 Error::ExpectedChar(c) => write!(f, "expected {}", c),
677 Error::UnexpectedStart => f.write_str("unexpected start of script"),
678 Error::Unexpected(ref s) => write!(f, "unexpected «{}»", s),
679 Error::MultiColon(ref s) => write!(f, "«{}» has multiple instances of «:»", s),
680 Error::MultiAt(ref s) => write!(f, "«{}» has multiple instances of «@»", s),
681 Error::AtOutsideOr(ref s) => write!(f, "«{}» contains «@» in non-or() context", s),
682 Error::LikelyFalse => write!(f, "0 is not very likely (use «u:0»)"),
683 Error::UnknownWrapper(ch) => write!(f, "unknown wrapper «{}:»", ch),
684 Error::NonTopLevel(ref s) => write!(f, "non-T miniscript: {}", s),
685 Error::Trailing(ref s) => write!(f, "trailing tokens: {}", s),
686 Error::MissingHash(ref h) => write!(f, "missing preimage of hash {}", h),
687 Error::MissingSig(ref pk) => write!(f, "missing signature for key {:?}", pk),
688 Error::RelativeLocktimeNotMet(n) => {
689 write!(f, "required relative locktime CSV of {} blocks, not met", n)
690 }
691 Error::AbsoluteLocktimeNotMet(n) => write!(
692 f,
693 "required absolute locktime CLTV of {} blocks, not met",
694 n
695 ),
696 Error::CouldNotSatisfy => f.write_str("could not satisfy"),
697 Error::BadPubkey(ref e) => fmt::Display::fmt(e, f),
698 Error::TypeCheck(ref e) => write!(f, "typecheck: {}", e),
699 Error::BadDescriptor(ref e) => write!(f, "Invalid descriptor: {}", e),
700 Error::Secp(ref e) => fmt::Display::fmt(e, f),
701 Error::ContextError(ref e) => fmt::Display::fmt(e, f),
702 #[cfg(feature = "compiler")]
703 Error::CompilerError(ref e) => fmt::Display::fmt(e, f),
704 Error::PolicyError(ref e) => fmt::Display::fmt(e, f),
705 Error::LiftError(ref e) => fmt::Display::fmt(e, f),
706 Error::MaxRecursiveDepthExceeded => write!(
707 f,
708 "Recursive depth over {} not permitted",
709 MAX_RECURSION_DEPTH
710 ),
711 Error::ScriptSizeTooLarge => write!(
712 f,
713 "Standardness rules imply bitcoin than {} bytes",
714 MAX_SCRIPT_SIZE
715 ),
716 Error::NonStandardBareScript => write!(
717 f,
718 "Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) \
719 up to n=3 is invalid by standardness (bare).
720 "
721 ),
722 Error::AnalysisError(ref e) => e.fmt(f),
723 Error::ImpossibleSatisfaction => write!(f, "Impossible to satisfy Miniscript"),
724 Error::BareDescriptorAddr => write!(f, "Bare descriptors don't have address"),
725 Error::PubKeyCtxError(ref pk, ref ctx) => {
726 write!(f, "Pubkey error: {} under {} scriptcontext", pk, ctx)
727 }
728 Error::MultiATooManyKeys(k) => {
729 write!(f, "MultiA too many keys {}", k)
730 }
731 Error::TaprootSpendInfoUnavialable => {
732 write!(f, "Taproot Spend Info not computed. Hint: Did you call `compute_spend_info` before calling methods from DescriptorTrait")
733 }
734 Error::TrNoScriptCode => {
735 write!(f, "No script code for Tr descriptors")
736 }
737 Error::TrNoExplicitScript => {
738 write!(f, "No script code for Tr descriptors")
739 }
740 }
741 }
742}
743
744#[doc(hidden)]
745#[cfg(feature = "compiler")]
746impl From<policy::compiler::CompilerError> for Error {
747 fn from(e: policy::compiler::CompilerError) -> Error {
748 Error::CompilerError(e)
749 }
750}
751
752#[doc(hidden)]
753impl From<policy::concrete::PolicyError> for Error {
754 fn from(e: policy::concrete::PolicyError) -> Error {
755 Error::PolicyError(e)
756 }
757}
758
759pub fn script_num_size(n: usize) -> usize {
761 match n {
762 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, }
769}
770
771fn push_opcode_size(script_size: usize) -> usize {
777 if script_size < 76 {
778 1
779 } else if script_size < 0x100 {
780 2
781 } else if script_size < 0x10000 {
782 3
783 } else {
784 5
785 }
786}
787
788#[cfg(test)]
790fn hex_script(s: &str) -> bitcoin::Script {
791 let v: Vec<u8> = bitcoin::hashes::hex::FromHex::from_hex(s).unwrap();
792 bitcoin::Script::from(v)
793}