1#![cfg_attr(miniscript_bench, feature(test))]
93#![allow(clippy::manual_range_contains)] #![allow(clippy::type_complexity)] #[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
107use bitcoin_miniscript::expression::{FromTree as BtcFromTree, Tree as BtcTree};
112use bitcoin_miniscript::policy::semantic::Policy as BtcPolicy;
113use bitcoin_miniscript::policy::Liftable as BtcLiftable;
114pub 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#[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;
161mod 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 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 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
198pub 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
214pub trait Translator<P, Q, E>
217where
218 P: MiniscriptKey,
219 Q: MiniscriptKey,
220{
221 fn pk(&mut self, pk: &P) -> Result<Q, E>;
223
224 fn sha256(&mut self, sha256: &P::Sha256) -> Result<Q::Sha256, E>;
226
227 fn hash256(&mut self, hash256: &P::Hash256) -> Result<Q::Hash256, E>;
229
230 fn ripemd160(&mut self, ripemd160: &P::Ripemd160) -> Result<Q::Ripemd160, E>;
232
233 fn hash160(&mut self, hash160: &P::Hash160) -> Result<Q::Hash160, E>;
235}
236
237pub trait ExtTranslator<PExt, QExt, E>
239where
240 PExt: Extension,
241 QExt: Extension,
242{
243 fn ext(&mut self, e: &PExt) -> Result<QExt, E>;
245}
246
247pub trait TranslatePk<P, Q>
250where
251 P: MiniscriptKey,
252 Q: MiniscriptKey,
253{
254 type Output;
256
257 fn translate_pk<T, E>(&self, translator: &mut T) -> Result<Self::Output, E>
260 where
261 T: Translator<P, Q, E>;
262}
263
264pub trait TranslateExt<PExt, QExt>
267where
268 PExt: Extension,
269 QExt: Extension,
270{
271 type Output;
273
274 fn translate_ext<T, E>(&self, translator: &mut T) -> Result<Self::Output, E>
277 where
278 T: ExtTranslator<PExt, QExt, E>;
279}
280
281#[derive(Debug, PartialEq)]
283pub enum Error {
284 InvalidOpcode(opcodes::All),
286 NonMinimalVerify(String),
289 InvalidPush(Vec<u8>),
291 Script(script::Error),
293 AddrError(bitcoin::address::ParseError),
295 CmsTooManyKeys(u32),
297 MultiATooManyKeys(u32),
299 ExpectedChar(char),
301 UnexpectedStart,
303 Unexpected(String),
305 MultiColon(String),
307 MultiAt(String),
309 AtOutsideOr(String),
311 LikelyFalse,
313 UnknownWrapper(char),
315 NonTopLevel(String),
317 Trailing(String),
319 BadPubkey(bitcoin::key::ParsePublicKeyError),
321 BadPubkeySlice(bitcoin::key::FromSliceError),
323 MissingHash(sha256::Hash),
325 MissingSig(bitcoin::PublicKey),
327 RelativeLocktimeNotMet(u32),
329 AbsoluteLocktimeNotMet(u32),
331 CouldNotSatisfy,
333 TypeCheck(String),
335 BadDescriptor(String),
337 Secp(elements::secp256k1_zkp::Error),
339 #[cfg(feature = "compiler")]
340 CompilerError(policy::compiler::CompilerError),
342 PolicyError(policy::concrete::PolicyError),
344 LiftError(policy::LiftError),
346 ContextError(miniscript::context::ScriptContextError),
348 MaxRecursiveDepthExceeded,
350 ScriptSizeTooLarge,
352 NonStandardBareScript,
355 AnalysisError(miniscript::analyzable::AnalysisError),
357 ImpossibleSatisfaction,
359 BareDescriptorAddr,
361 BtcError(bitcoin_miniscript::Error),
363 CovError(descriptor::CovError),
365 PubKeyCtxError(miniscript::decode::KeyParseError, &'static str),
367 TaprootSpendInfoUnavialable,
369 TrNoScriptCode,
371 TrNoExplicitScript,
373 MultipathDescLenMismatch,
376
377 UnsupportedAddressForPegin,
379
380 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
468const MAX_RECURSION_DEPTH: u32 = 402;
470const 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, 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
623pub fn script_num_size(n: usize) -> usize {
625 match n {
626 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, }
633}
634
635fn 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#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
654pub struct AbsLockTime(locktime::LockTime);
655
656impl AbsLockTime {
657 pub fn from_consensus(n: u32) -> Self {
659 Self(locktime::LockTime::from_consensus(n))
660 }
661
662 pub fn to_consensus_u32(self) -> u32 {
668 self.0.to_consensus_u32()
669 }
670
671 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#[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 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 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}