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 elements::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::secp256k1::Scalar;
164 use bitcoin::PublicKey;
165 use elements::hashes::{sha256, Hash, HashEngine, Hmac, HmacEngine};
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
378#[doc(hidden)]
379impl<Pk, Ctx, Ext> From<miniscript::types::Error<Pk, Ctx, Ext>> for Error
380where
381 Pk: MiniscriptKey,
382 Ctx: ScriptContext,
383 Ext: Extension,
384{
385 fn from(e: miniscript::types::Error<Pk, Ctx, Ext>) -> Error {
386 Error::TypeCheck(e.to_string())
387 }
388}
389
390#[doc(hidden)]
391impl From<bitcoin_miniscript::Error> for Error {
392 fn from(e: bitcoin_miniscript::Error) -> Error {
393 Error::BtcError(e)
394 }
395}
396
397#[doc(hidden)]
398impl From<policy::LiftError> for Error {
399 fn from(e: policy::LiftError) -> Error {
400 Error::LiftError(e)
401 }
402}
403
404#[doc(hidden)]
405impl From<miniscript::context::ScriptContextError> for Error {
406 fn from(e: miniscript::context::ScriptContextError) -> Error {
407 Error::ContextError(e)
408 }
409}
410
411#[doc(hidden)]
412impl From<miniscript::analyzable::AnalysisError> for Error {
413 fn from(e: miniscript::analyzable::AnalysisError) -> Error {
414 Error::AnalysisError(e)
415 }
416}
417
418#[doc(hidden)]
419impl From<elements::secp256k1_zkp::Error> for Error {
420 fn from(e: elements::secp256k1_zkp::Error) -> Error {
421 Error::Secp(e)
422 }
423}
424
425#[doc(hidden)]
426impl From<elements::secp256k1_zkp::UpstreamError> for Error {
427 fn from(e: elements::secp256k1_zkp::UpstreamError) -> Error {
428 Error::Secp(elements::secp256k1_zkp::Error::Upstream(e))
429 }
430}
431
432#[doc(hidden)]
433impl From<bitcoin::key::ParsePublicKeyError> for Error {
434 fn from(e: bitcoin::key::ParsePublicKeyError) -> Error {
435 Error::BadPubkey(e)
436 }
437}
438
439#[doc(hidden)]
440impl From<bitcoin::key::FromSliceError> for Error {
441 fn from(e: bitcoin::key::FromSliceError) -> Error {
442 Error::BadPubkeySlice(e)
443 }
444}
445
446impl From<bitcoin::address::ParseError> for Error {
447 fn from(e: bitcoin::address::ParseError) -> Error {
448 Error::AddrError(e)
449 }
450}
451
452fn errstr(s: &str) -> Error {
453 Error::Unexpected(s.to_owned())
454}
455
456const MAX_RECURSION_DEPTH: u32 = 402;
458const MAX_SCRIPT_SIZE: u32 = 10000;
460
461impl fmt::Display for Error {
462 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
463 match *self {
464 Error::InvalidOpcode(op) => write!(f, "invalid opcode {}", op),
465 Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok),
466 Error::InvalidPush(ref push) => {
467 write!(f, "invalid push ")?;
468 elements::hex::format_hex(push, f)
469 },
470 Error::Script(ref e) => fmt::Display::fmt(e, f),
471 Error::AddrError(ref e) => fmt::Display::fmt(e, f),
472 Error::CmsTooManyKeys(n) => write!(f, "checkmultisig with {} keys", n),
473 Error::ExpectedChar(c) => write!(f, "expected {}", c),
474 Error::UnexpectedStart => f.write_str("unexpected start of script"),
475 Error::Unexpected(ref s) => write!(f, "unexpected «{}»", s),
476 Error::MultiColon(ref s) => write!(f, "«{}» has multiple instances of «:»", s),
477 Error::MultiAt(ref s) => write!(f, "«{}» has multiple instances of «@»", s),
478 Error::AtOutsideOr(ref s) => write!(f, "«{}» contains «@» in non-or() context", s),
479 Error::LikelyFalse => write!(f, "0 is not very likely (use «u:0»)"),
480 Error::UnknownWrapper(ch) => write!(f, "unknown wrapper «{}:»", ch),
481 Error::NonTopLevel(ref s) => write!(f, "non-T miniscript: {}", s),
482 Error::Trailing(ref s) => write!(f, "trailing tokens: {}", s),
483 Error::MissingHash(ref h) => write!(f, "missing preimage of hash {}", h),
484 Error::MissingSig(ref pk) => write!(f, "missing signature for key {:?}", pk),
485 Error::RelativeLocktimeNotMet(n) => {
486 write!(f, "required relative locktime CSV of {} blocks, not met", n)
487 }
488 Error::AbsoluteLocktimeNotMet(n) => write!(
489 f,
490 "required absolute locktime CLTV of {} blocks, not met",
491 n
492 ),
493 Error::CouldNotSatisfy => f.write_str("could not satisfy"),
494 Error::BadPubkey(ref e) => fmt::Display::fmt(e, f),
495 Error::BadPubkeySlice(ref e) => fmt::Display::fmt(e, f),
496 Error::TypeCheck(ref e) => write!(f, "typecheck: {}", e),
497 Error::BadDescriptor(ref e) => write!(f, "Invalid descriptor: {}", e),
498 Error::Secp(ref e) => fmt::Display::fmt(e, f),
499 Error::ContextError(ref e) => fmt::Display::fmt(e, f),
500 #[cfg(feature = "compiler")]
501 Error::CompilerError(ref e) => fmt::Display::fmt(e, f),
502 Error::PolicyError(ref e) => fmt::Display::fmt(e, f),
503 Error::LiftError(ref e) => fmt::Display::fmt(e, f),
504 Error::MaxRecursiveDepthExceeded => write!(
505 f,
506 "Recursive depth over {} not permitted",
507 MAX_RECURSION_DEPTH
508 ),
509 Error::ScriptSizeTooLarge => write!(
510 f,
511 "Standardness rules imply bitcoin than {} bytes",
512 MAX_SCRIPT_SIZE
513 ),
514 Error::NonStandardBareScript => write!(
515 f,
516 "Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) \
517 up to n=3 is invalid by standardness (bare).
518 "
519 ),
520 Error::AnalysisError(ref e) => e.fmt(f),
521 Error::ImpossibleSatisfaction => write!(f, "Impossible to satisfy Miniscript"),
522 Error::BareDescriptorAddr => write!(f, "Bare descriptors don't have address"),
523 Error::BtcError(ref e) => write!(f, " Bitcoin Miniscript Error {}", e),
524 Error::CovError(ref e) => write!(f, "Covenant Error: {}", e),
525 Error::PubKeyCtxError(ref pk, ref ctx) => {
526 write!(f, "Pubkey error: {} under {} scriptcontext", pk, ctx)
527 }
528 Error::MultiATooManyKeys(k) => write!(f, "MultiA too many keys {}", k),
529 Error::TaprootSpendInfoUnavialable => write!(f, "Taproot Spend Info not computed."),
530 Error::TrNoScriptCode => write!(f, "No script code for Tr descriptors"),
531 Error::TrNoExplicitScript => write!(f, "No script code for Tr descriptors"),
532 Error::MultipathDescLenMismatch => write!(f, "At least two BIP389 key expressions in the descriptor contain tuples of derivation indexes of different lengths"),
533 }
534 }
535}
536
537impl error::Error for Error {
538 fn cause(&self) -> Option<&dyn error::Error> {
539 use self::Error::*;
540
541 match self {
542 InvalidOpcode(_)
543 | NonMinimalVerify(_)
544 | InvalidPush(_)
545 | CmsTooManyKeys(_)
546 | MultiATooManyKeys(_)
547 | ExpectedChar(_)
548 | UnexpectedStart
549 | Unexpected(_)
550 | MultiColon(_)
551 | MultiAt(_)
552 | AtOutsideOr(_)
553 | LikelyFalse
554 | UnknownWrapper(_)
555 | NonTopLevel(_)
556 | Trailing(_)
557 | MissingHash(_)
558 | MissingSig(_)
559 | RelativeLocktimeNotMet(_)
560 | AbsoluteLocktimeNotMet(_)
561 | CouldNotSatisfy
562 | TypeCheck(_)
563 | BadDescriptor(_)
564 | MaxRecursiveDepthExceeded
565 | ScriptSizeTooLarge
566 | NonStandardBareScript
567 | ImpossibleSatisfaction
568 | BareDescriptorAddr
569 | TaprootSpendInfoUnavialable
570 | TrNoScriptCode
571 | TrNoExplicitScript => None,
572 MultipathDescLenMismatch => None,
573 BtcError(e) => Some(e),
574 CovError(e) => Some(e),
575 Script(_e) => None, AddrError(e) => Some(e),
577 BadPubkey(e) => Some(e),
578 BadPubkeySlice(e) => Some(e),
579 Secp(e) => Some(e),
580 #[cfg(feature = "compiler")]
581 CompilerError(e) => Some(e),
582 PolicyError(e) => Some(e),
583 LiftError(e) => Some(e),
584 ContextError(e) => Some(e),
585 AnalysisError(e) => Some(e),
586 PubKeyCtxError(e, _) => Some(e),
587 }
588 }
589}
590
591#[doc(hidden)]
592#[cfg(feature = "compiler")]
593impl From<policy::compiler::CompilerError> for Error {
594 fn from(e: policy::compiler::CompilerError) -> Error {
595 Error::CompilerError(e)
596 }
597}
598
599#[doc(hidden)]
600impl From<policy::concrete::PolicyError> for Error {
601 fn from(e: policy::concrete::PolicyError) -> Error {
602 Error::PolicyError(e)
603 }
604}
605
606pub fn script_num_size(n: usize) -> usize {
608 match n {
609 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, }
616}
617
618fn push_opcode_size(script_size: usize) -> usize {
624 if script_size < 76 {
625 1
626 } else if script_size < 0x100 {
627 2
628 } else if script_size < 0x10000 {
629 3
630 } else {
631 5
632 }
633}
634
635#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
637pub struct AbsLockTime(locktime::LockTime);
638
639impl AbsLockTime {
640 pub fn from_consensus(n: u32) -> Self {
642 Self(locktime::LockTime::from_consensus(n))
643 }
644
645 pub fn to_consensus_u32(self) -> u32 {
651 self.0.to_consensus_u32()
652 }
653
654 pub fn to_u32(self) -> u32 {
658 self.to_consensus_u32()
659 }
660}
661
662impl From<locktime::LockTime> for AbsLockTime {
663 fn from(lock_time: locktime::LockTime) -> Self {
664 Self(lock_time)
665 }
666}
667
668impl From<AbsLockTime> for locktime::LockTime {
669 fn from(lock_time: AbsLockTime) -> locktime::LockTime {
670 lock_time.0
671 }
672}
673
674impl cmp::PartialOrd for AbsLockTime {
675 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
676 Some(self.cmp(other))
677 }
678}
679
680impl cmp::Ord for AbsLockTime {
681 fn cmp(&self, other: &Self) -> cmp::Ordering {
682 let this = self.0.to_consensus_u32();
683 let that = other.0.to_consensus_u32();
684 this.cmp(&that)
685 }
686}
687
688impl fmt::Display for AbsLockTime {
689 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
690 fmt::Display::fmt(&self.0, f)
691 }
692}
693
694#[cfg(test)]
696fn hex_script(s: &str) -> elements::Script {
697 let v: Vec<u8> = elements::hex::FromHex::from_hex(s).unwrap();
698 elements::Script::from(v)
699}
700
701#[cfg(test)]
702mod tests {
703 use std::str::FromStr;
704
705 use bitcoin::hashes::hash160;
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}