1use std::collections::HashMap;
16use std::fmt;
17use std::ops::Range;
18use std::str::{self, FromStr};
19use std::sync::Arc;
20
21pub mod pegin;
22
23use bitcoin::hashes::{hash160, ripemd160, sha256};
24use bitcoin::WitnessVersion;
25use elements::{secp256k1_zkp as secp256k1, secp256k1_zkp, Script, TxIn};
26use {bitcoin, elements};
27
28use self::checksum::verify_checksum;
29use crate::extensions::{CovExtArgs, ExtParam, ParseableExt};
30use crate::miniscript::{Legacy, Miniscript, Segwitv0};
31use crate::{
32 expression, hash256, miniscript, BareCtx, CovenantExt, Error, ExtTranslator, Extension,
33 ForEachKey, MiniscriptKey, NoExt, Satisfier, ToPublicKey, TranslateExt, TranslatePk,
34 Translator,
35};
36
37mod bare;
38mod csfs_cov;
39mod segwitv0;
40mod sh;
41mod sortedmulti;
42mod tr;
43
44pub use self::bare::{Bare, Pkh};
46pub use self::segwitv0::{Wpkh, Wsh, WshInner};
47pub use self::sh::{Sh, ShInner};
48pub use self::sortedmulti::SortedMultiVec;
49
50pub mod checksum;
51mod key;
52pub use self::csfs_cov::{CovError, CovOperations, LegacyCSFSCov, LegacyCovSatisfier};
53pub(crate) use self::key::maybe_fmt_master_id;
54pub use self::key::{
55 ConversionError, DefiniteDescriptorKey, DerivPaths, DescriptorKeyParseError,
56 DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, InnerXKey,
57 SinglePriv, SinglePub, SinglePubKey, Wildcard,
58};
59pub use self::tr::{TapLeafScript, TapTree, Tr};
60pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey>;
67
68pub const ELMTS_STR: &str = "el";
70
71#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
73pub enum DescriptorType {
74 Bare,
76 Sh,
78 Pkh,
80 Wpkh,
82 Wsh,
84 ShWsh,
86 ShWpkh,
88 ShSortedMulti,
90 WshSortedMulti,
92 ShWshSortedMulti,
94 LegacyPegin,
96 Pegin,
98 Cov,
100 Tr,
102}
103
104impl fmt::Display for DescriptorType {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 match *self {
107 DescriptorType::Bare => write!(f, "bare"),
108 DescriptorType::Sh => write!(f, "sh"),
109 DescriptorType::Pkh => write!(f, "pkh"),
110 DescriptorType::Wpkh => write!(f, "wpkh"),
111 DescriptorType::Wsh => write!(f, "wsh"),
112 DescriptorType::ShWsh => write!(f, "shwsh"),
113 DescriptorType::ShWpkh => write!(f, "shwpkh"),
114 DescriptorType::ShSortedMulti => write!(f, "shsortedmulti"),
115 DescriptorType::WshSortedMulti => write!(f, "wshsortedmulti"),
116 DescriptorType::ShWshSortedMulti => write!(f, "shwshsortedmulti"),
117 DescriptorType::LegacyPegin => write!(f, "legacy_pegin"),
118 DescriptorType::Pegin => write!(f, "pegin"),
119 DescriptorType::Cov => write!(f, "elcovwsh"),
120 DescriptorType::Tr => write!(f, "tr"),
121 }
122 }
123}
124impl FromStr for DescriptorType {
125 type Err = Error;
126
127 fn from_str(s: &str) -> Result<Self, Self::Err> {
130 if s.len() >= 12 && &s[0..12] == "legacy_pegin" {
131 Ok(DescriptorType::LegacyPegin)
132 } else if s.len() >= 5 && &s[0..5] == "pegin" {
133 Ok(DescriptorType::Pegin)
134 } else if s.len() >= 3 && &s[0..3] == "pkh" {
135 Ok(DescriptorType::Pkh)
136 } else if s.len() >= 4 && &s[0..4] == "wpkh" {
137 Ok(DescriptorType::Wpkh)
138 } else if s.len() >= 6 && &s[0..6] == "sh(wsh" {
139 Ok(DescriptorType::ShWsh)
140 } else if s.len() >= 7 && &s[0..7] == "sh(wpkh" {
141 Ok(DescriptorType::ShWpkh)
142 } else if s.len() >= 14 && &s[0..14] == "sh(sortedmulti" {
143 Ok(DescriptorType::ShSortedMulti)
144 } else if s.len() >= 18 && &s[0..18] == "sh(wsh(sortedmulti" {
145 Ok(DescriptorType::ShWshSortedMulti)
146 } else if s.len() >= 2 && &s[0..2] == "sh" {
147 Ok(DescriptorType::Sh)
148 } else if s.len() >= 15 && &s[0..15] == "wsh(sortedmulti" {
149 Ok(DescriptorType::WshSortedMulti)
150 } else if s.len() >= 3 && &s[0..3] == "wsh" {
151 Ok(DescriptorType::Wsh)
152 } else if s.len() >= 8 && &s[0..8] == "elcovwsh" {
153 Ok(DescriptorType::Cov)
154 } else {
155 Ok(DescriptorType::Bare)
156 }
157 }
158}
159pub enum DescriptorInfo {
161 Btc {
163 has_secret: bool,
165 ty: DescriptorType,
167 },
168 Elements {
170 has_secret: bool,
172 ty: DescriptorType,
174 },
175 Pegin {
182 has_secret: bool,
184 ty: DescriptorType,
186 },
187}
188
189impl DescriptorInfo {
190 pub fn from_desc_str<T: Extension>(s: &str) -> Result<Self, Error> {
198 let descriptor = Descriptor::<String, T>::from_str(s)?;
200 let has_secret = descriptor.for_any_key(|pk| DescriptorSecretKey::from_str(pk).is_ok());
201 let ty = DescriptorType::from_str(s)?;
202 let is_pegin = matches!(ty, DescriptorType::Pegin | DescriptorType::LegacyPegin);
203 if is_pegin {
205 Ok(DescriptorInfo::Pegin { has_secret, ty })
206 } else {
207 Ok(DescriptorInfo::Btc { has_secret, ty })
208 }
209 }
210}
211
212#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
214pub enum Descriptor<Pk: MiniscriptKey, T: Extension = CovenantExt<CovExtArgs>> {
215 Bare(Bare<Pk>),
217 Pkh(Pkh<Pk>),
219 Wpkh(Wpkh<Pk>),
221 Sh(Sh<Pk>),
223 Wsh(Wsh<Pk>),
225 Tr(Tr<Pk, NoExt>),
227 TrExt(Tr<Pk, T>),
229 LegacyCSFSCov(LegacyCSFSCov<Pk, T>),
232}
233
234impl<Pk: MiniscriptKey, Ext: Extension> From<Bare<Pk>> for Descriptor<Pk, Ext> {
235 #[inline]
236 fn from(inner: Bare<Pk>) -> Self {
237 Descriptor::Bare(inner)
238 }
239}
240
241impl<Pk: MiniscriptKey, Ext: Extension> From<Pkh<Pk>> for Descriptor<Pk, Ext> {
242 #[inline]
243 fn from(inner: Pkh<Pk>) -> Self {
244 Descriptor::Pkh(inner)
245 }
246}
247
248impl<Pk: MiniscriptKey, Ext: Extension> From<Wpkh<Pk>> for Descriptor<Pk, Ext> {
249 #[inline]
250 fn from(inner: Wpkh<Pk>) -> Self {
251 Descriptor::Wpkh(inner)
252 }
253}
254
255impl<Pk: MiniscriptKey, Ext: Extension> From<Sh<Pk>> for Descriptor<Pk, Ext> {
256 #[inline]
257 fn from(inner: Sh<Pk>) -> Self {
258 Descriptor::Sh(inner)
259 }
260}
261
262impl<Pk: MiniscriptKey, Ext: Extension> From<Wsh<Pk>> for Descriptor<Pk, Ext> {
263 #[inline]
264 fn from(inner: Wsh<Pk>) -> Self {
265 Descriptor::Wsh(inner)
266 }
267}
268
269impl<Pk: MiniscriptKey, Ext: Extension> From<Tr<Pk, NoExt>> for Descriptor<Pk, Ext> {
270 #[inline]
271 fn from(inner: Tr<Pk, NoExt>) -> Self {
272 Descriptor::Tr(inner)
273 }
274}
275
276impl<Pk: MiniscriptKey, Arg: ExtParam> From<LegacyCSFSCov<Pk, CovenantExt<Arg>>>
277 for Descriptor<Pk, CovenantExt<Arg>>
278{
279 #[inline]
280 fn from(inner: LegacyCSFSCov<Pk, CovenantExt<Arg>>) -> Self {
281 Descriptor::LegacyCSFSCov(inner)
282 }
283}
284
285impl DescriptorType {
286 pub fn segwit_version(&self) -> Option<WitnessVersion> {
290 use self::DescriptorType::*;
291 match self {
292 Tr => Some(WitnessVersion::V1),
293 Wpkh | ShWpkh | Wsh | ShWsh | ShWshSortedMulti | WshSortedMulti => {
294 Some(WitnessVersion::V0)
295 }
296 Bare | Sh | Pkh | ShSortedMulti => None,
297 LegacyPegin => Some(WitnessVersion::V1),
298 Pegin => None, Cov => None, }
301 }
302}
303
304impl<Pk: MiniscriptKey, Ext: Extension> Descriptor<Pk, Ext> {
305 pub fn new_pk(pk: Pk) -> Self {
309 let ms: Miniscript<Pk, BareCtx> =
311 Miniscript::from_ast(miniscript::decode::Terminal::Check(Arc::new(
312 Miniscript::from_ast(miniscript::decode::Terminal::PkK(pk))
313 .expect("Type check cannot fail"),
314 )))
315 .expect("Type check cannot fail");
316 Descriptor::Bare(Bare::new(ms).expect("Context checks cannot fail for p2pk"))
317 }
318
319 pub fn new_pkh(pk: Pk) -> Self {
321 Descriptor::Pkh(Pkh::new(pk))
322 }
323
324 pub fn new_wpkh(pk: Pk) -> Result<Self, Error> {
327 Ok(Descriptor::Wpkh(Wpkh::new(pk)?))
328 }
329
330 pub fn new_sh_wpkh(pk: Pk) -> Result<Self, Error> {
333 Ok(Descriptor::Sh(Sh::new_wpkh(pk)?))
334 }
335
336 pub fn new_sh(ms: Miniscript<Pk, Legacy>) -> Result<Self, Error> {
342 Ok(Descriptor::Sh(Sh::new(ms)?))
343 }
344
345 pub fn new_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
349 Ok(Descriptor::Wsh(Wsh::new(ms)?))
350 }
351
352 pub fn new_sh_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
356 Ok(Descriptor::Sh(Sh::new_wsh(ms)?))
357 }
358
359 pub fn new_bare(ms: Miniscript<Pk, BareCtx>) -> Result<Self, Error> {
363 Ok(Descriptor::Bare(Bare::new(ms)?))
364 }
365
366 pub fn new_sh_with_wpkh(wpkh: Wpkh<Pk>) -> Self {
370 Descriptor::Sh(Sh::new_with_wpkh(wpkh))
371 }
372
373 pub fn new_sh_with_wsh(wsh: Wsh<Pk>) -> Self {
375 Descriptor::Sh(Sh::new_with_wsh(wsh))
376 }
377
378 pub fn new_sh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
384 Ok(Descriptor::Sh(Sh::new_sortedmulti(k, pks)?))
385 }
386
387 pub fn new_sh_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
391 Ok(Descriptor::Sh(Sh::new_wsh_sortedmulti(k, pks)?))
392 }
393
394 pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
397 Ok(Descriptor::Wsh(Wsh::new_sortedmulti(k, pks)?))
398 }
399
400 pub fn new_tr(key: Pk, script: Option<tr::TapTree<Pk, NoExt>>) -> Result<Self, Error> {
403 Ok(Descriptor::Tr(Tr::new(key, script)?))
404 }
405
406 pub fn new_tr_ext(key: Pk, script: Option<tr::TapTree<Pk, Ext>>) -> Result<Self, Error> {
409 Ok(Descriptor::TrExt(Tr::new(key, script)?))
410 }
411
412 pub fn desc_type(&self) -> DescriptorType {
414 match *self {
415 Descriptor::Bare(ref _bare) => DescriptorType::Bare,
416 Descriptor::Pkh(ref _pkh) => DescriptorType::Pkh,
417 Descriptor::Wpkh(ref _wpkh) => DescriptorType::Wpkh,
418 Descriptor::Sh(ref sh) => match sh.as_inner() {
419 ShInner::Wsh(ref wsh) => match wsh.as_inner() {
420 WshInner::SortedMulti(ref _smv) => DescriptorType::ShWshSortedMulti,
421 WshInner::Ms(ref _ms) => DescriptorType::ShWsh,
422 },
423 ShInner::Wpkh(ref _wpkh) => DescriptorType::ShWpkh,
424 ShInner::SortedMulti(ref _smv) => DescriptorType::ShSortedMulti,
425 ShInner::Ms(ref _ms) => DescriptorType::Sh,
426 },
427 Descriptor::Wsh(ref wsh) => match wsh.as_inner() {
428 WshInner::SortedMulti(ref _smv) => DescriptorType::WshSortedMulti,
429 WshInner::Ms(ref _ms) => DescriptorType::Wsh,
430 },
431 Descriptor::LegacyCSFSCov(ref _cov) => DescriptorType::Cov,
432 Descriptor::Tr(ref _tr) => DescriptorType::Tr,
433 Descriptor::TrExt(ref _tr) => DescriptorType::Tr,
434 }
435 }
436
437 pub fn sanity_check(&self) -> Result<(), Error> {
447 match *self {
448 Descriptor::Bare(ref bare) => bare.sanity_check(),
449 Descriptor::Pkh(_) => Ok(()),
450 Descriptor::Wpkh(ref wpkh) => wpkh.sanity_check(),
451 Descriptor::Wsh(ref wsh) => wsh.sanity_check(),
452 Descriptor::Sh(ref sh) => sh.sanity_check(),
453 Descriptor::LegacyCSFSCov(ref cov) => cov.sanity_check(),
454 Descriptor::Tr(ref tr) => tr.sanity_check(),
455 Descriptor::TrExt(ref tr) => tr.sanity_check(),
456 }
457 }
458
459 pub fn max_weight_to_satisfy(&self) -> Result<usize, Error> {
498 let weight = match *self {
499 Descriptor::Bare(ref bare) => bare.max_weight_to_satisfy()?,
500 Descriptor::Pkh(ref pkh) => pkh.max_weight_to_satisfy(),
501 Descriptor::Wpkh(ref wpkh) => wpkh.max_weight_to_satisfy(),
502 Descriptor::Wsh(ref wsh) => wsh.max_weight_to_satisfy()?,
503 Descriptor::Sh(ref sh) => sh.max_weight_to_satisfy()?,
504 Descriptor::Tr(ref tr) => tr.max_weight_to_satisfy()?,
505 Descriptor::TrExt(ref tr) => tr.max_weight_to_satisfy()?,
506 Descriptor::LegacyCSFSCov(ref csfs) => csfs.max_satisfaction_weight()?,
507 };
508 Ok(weight)
509 }
510
511 #[deprecated(note = "use max_weight_to_satisfy instead")]
521 #[allow(deprecated)]
522 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
523 let weight = match *self {
524 Descriptor::Bare(ref bare) => bare.max_satisfaction_weight()?,
525 Descriptor::Pkh(ref pkh) => pkh.max_satisfaction_weight(),
526 Descriptor::Wpkh(ref wpkh) => wpkh.max_satisfaction_weight(),
527 Descriptor::Wsh(ref wsh) => wsh.max_satisfaction_weight()?,
528 Descriptor::Sh(ref sh) => sh.max_satisfaction_weight()?,
529 Descriptor::LegacyCSFSCov(ref cov) => cov.max_satisfaction_weight()?,
530 Descriptor::Tr(ref tr) => tr.max_satisfaction_weight()?,
531 Descriptor::TrExt(ref tr) => tr.max_satisfaction_weight()?,
532 };
533 Ok(weight)
534 }
535}
536
537impl<Pk: MiniscriptKey, Arg: ExtParam> Descriptor<Pk, CovenantExt<Arg>> {
538 pub fn new_cov_wsh(
541 pk: Pk,
542 ms: Miniscript<Pk, Segwitv0, CovenantExt<Arg>>,
543 ) -> Result<Self, Error> {
544 let cov = LegacyCSFSCov::new(pk, ms)?;
545 Ok(Descriptor::LegacyCSFSCov(cov))
546 }
547
548 pub fn as_cov(&self) -> Result<&LegacyCSFSCov<Pk, CovenantExt<Arg>>, Error> {
550 if let Descriptor::LegacyCSFSCov(cov) = self {
551 Ok(cov)
552 } else {
553 Err(Error::CovError(CovError::BadCovDescriptor))
554 }
555 }
556}
557
558impl<Pk: MiniscriptKey + ToPublicKey, Ext: Extension + ParseableExt> Descriptor<Pk, Ext> {
559 pub fn blinded_address(
567 &self,
568 blinder: secp256k1_zkp::PublicKey,
569 params: &'static elements::AddressParams,
570 ) -> Result<elements::Address, Error>
571 where
572 Pk: ToPublicKey,
573 {
574 match *self {
575 Descriptor::Bare(_) => Err(Error::BareDescriptorAddr),
576 Descriptor::Pkh(ref pkh) => Ok(pkh.address(Some(blinder), params)),
577 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.address(Some(blinder), params)),
578 Descriptor::Wsh(ref wsh) => Ok(wsh.address(Some(blinder), params)),
579 Descriptor::Sh(ref sh) => Ok(sh.address(Some(blinder), params)),
580 Descriptor::LegacyCSFSCov(ref cov) => Ok(cov.address(Some(blinder), params)),
581 Descriptor::Tr(ref tr) => Ok(tr.address(Some(blinder), params)),
582 Descriptor::TrExt(ref tr) => Ok(tr.address(Some(blinder), params)),
583 }
584 }
585
586 pub fn address(
588 &self,
589 params: &'static elements::AddressParams,
590 ) -> Result<elements::Address, Error>
591 where
592 Pk: ToPublicKey,
593 {
594 match *self {
595 Descriptor::Bare(_) => Err(Error::BareDescriptorAddr),
596 Descriptor::Pkh(ref pkh) => Ok(pkh.address(None, params)),
597 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.address(None, params)),
598 Descriptor::Wsh(ref wsh) => Ok(wsh.address(None, params)),
599 Descriptor::Sh(ref sh) => Ok(sh.address(None, params)),
600 Descriptor::LegacyCSFSCov(ref cov) => Ok(cov.address(None, params)),
601 Descriptor::Tr(ref tr) => Ok(tr.address(None, params)),
602 Descriptor::TrExt(ref tr) => Ok(tr.address(None, params)),
603 }
604 }
605
606 pub fn script_pubkey(&self) -> Script {
608 match *self {
609 Descriptor::Bare(ref bare) => bare.script_pubkey(),
610 Descriptor::Pkh(ref pkh) => pkh.script_pubkey(),
611 Descriptor::Wpkh(ref wpkh) => wpkh.script_pubkey(),
612 Descriptor::Wsh(ref wsh) => wsh.script_pubkey(),
613 Descriptor::Sh(ref sh) => sh.script_pubkey(),
614 Descriptor::LegacyCSFSCov(ref cov) => cov.script_pubkey(),
615 Descriptor::Tr(ref tr) => tr.script_pubkey(),
616 Descriptor::TrExt(ref tr) => tr.script_pubkey(),
617 }
618 }
619
620 pub fn unsigned_script_sig(&self) -> Script {
628 match *self {
629 Descriptor::Bare(_) => Script::new(),
630 Descriptor::Pkh(_) => Script::new(),
631 Descriptor::Wpkh(_) => Script::new(),
632 Descriptor::Wsh(_) => Script::new(),
633 Descriptor::Sh(ref sh) => sh.unsigned_script_sig(),
634 Descriptor::LegacyCSFSCov(_) => Script::new(),
635 Descriptor::Tr(_) => Script::new(),
636 Descriptor::TrExt(_) => Script::new(),
637 }
638 }
639
640 pub fn explicit_script(&self) -> Result<Script, Error> {
647 match *self {
648 Descriptor::Bare(ref bare) => Ok(bare.script_pubkey()),
649 Descriptor::Pkh(ref pkh) => Ok(pkh.script_pubkey()),
650 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.script_pubkey()),
651 Descriptor::Wsh(ref wsh) => Ok(wsh.inner_script()),
652 Descriptor::Sh(ref sh) => Ok(sh.inner_script()),
653 Descriptor::Tr(_) => Err(Error::TrNoScriptCode),
654 Descriptor::TrExt(_) => Err(Error::TrNoScriptCode),
655 Descriptor::LegacyCSFSCov(ref cov) => Ok(cov.inner_script()),
656 }
657 }
658
659 pub fn script_code(&self) -> Result<Script, Error> {
667 match *self {
668 Descriptor::Bare(ref bare) => Ok(bare.ecdsa_sighash_script_code()),
669 Descriptor::Pkh(ref pkh) => Ok(pkh.ecdsa_sighash_script_code()),
670 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.ecdsa_sighash_script_code()),
671 Descriptor::Wsh(ref wsh) => Ok(wsh.ecdsa_sighash_script_code()),
672 Descriptor::Sh(ref sh) => Ok(sh.ecdsa_sighash_script_code()),
673 Descriptor::LegacyCSFSCov(ref cov) => Ok(cov.ecdsa_sighash_script_code()),
674 Descriptor::Tr(_) => Err(Error::TrNoScriptCode),
675 Descriptor::TrExt(_) => Err(Error::TrNoScriptCode),
676 }
677 }
678
679 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
683 where
684 S: Satisfier<Pk>,
685 {
686 match *self {
687 Descriptor::Bare(ref bare) => bare.get_satisfaction(satisfier),
688 Descriptor::Pkh(ref pkh) => pkh.get_satisfaction(satisfier),
689 Descriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction(satisfier),
690 Descriptor::Wsh(ref wsh) => wsh.get_satisfaction(satisfier),
691 Descriptor::Sh(ref sh) => sh.get_satisfaction(satisfier),
692 Descriptor::LegacyCSFSCov(ref cov) => cov.get_satisfaction(satisfier),
693 Descriptor::Tr(ref tr) => tr.get_satisfaction(satisfier),
694 Descriptor::TrExt(ref tr) => tr.get_satisfaction(satisfier),
695 }
696 }
697
698 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
702 where
703 S: Satisfier<Pk>,
704 {
705 match *self {
706 Descriptor::Bare(ref bare) => bare.get_satisfaction_mall(satisfier),
707 Descriptor::Pkh(ref pkh) => pkh.get_satisfaction_mall(satisfier),
708 Descriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction_mall(satisfier),
709 Descriptor::Wsh(ref wsh) => wsh.get_satisfaction_mall(satisfier),
710 Descriptor::Sh(ref sh) => sh.get_satisfaction_mall(satisfier),
711 Descriptor::LegacyCSFSCov(ref cov) => cov.get_satisfaction_mall(satisfier),
712 Descriptor::Tr(ref tr) => tr.get_satisfaction_mall(satisfier),
713 Descriptor::TrExt(ref tr) => tr.get_satisfaction_mall(satisfier),
714 }
715 }
716
717 pub fn satisfy<S>(&self, txin: &mut TxIn, satisfier: S) -> Result<(), Error>
721 where
722 S: Satisfier<Pk>,
723 {
724 let (witness, script_sig) = self.get_satisfaction(satisfier)?;
725 txin.witness.script_witness = witness.into();
726 txin.script_sig = script_sig;
727 Ok(())
728 }
729}
730
731impl<P, Q, Ext> TranslatePk<P, Q> for Descriptor<P, Ext>
732where
733 P: MiniscriptKey,
734 Q: MiniscriptKey,
735 Ext: Extension,
736{
737 type Output = Descriptor<Q, Ext>;
738
739 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
741 where
742 T: Translator<P, Q, E>,
743 {
744 let desc = match *self {
745 Descriptor::Bare(ref bare) => Descriptor::Bare(bare.translate_pk(t)?),
746 Descriptor::Pkh(ref pk) => Descriptor::Pkh(pk.translate_pk(t)?),
747 Descriptor::Wpkh(ref pk) => Descriptor::Wpkh(pk.translate_pk(t)?),
748 Descriptor::Sh(ref sh) => Descriptor::Sh(sh.translate_pk(t)?),
749 Descriptor::Wsh(ref wsh) => Descriptor::Wsh(wsh.translate_pk(t)?),
750 Descriptor::Tr(ref tr) => Descriptor::Tr(tr.translate_pk(t)?),
751 Descriptor::TrExt(ref tr) => Descriptor::TrExt(tr.translate_pk(t)?),
752 Descriptor::LegacyCSFSCov(ref cov) => Descriptor::LegacyCSFSCov(cov.translate_pk(t)?),
753 };
754 Ok(desc)
755 }
756}
757
758impl<PExt, QExt, Pk> TranslateExt<PExt, QExt> for Descriptor<Pk, PExt>
759where
760 PExt: Extension + TranslateExt<PExt, QExt, Output = QExt>,
761 QExt: Extension,
762 Pk: MiniscriptKey,
763{
764 type Output = Descriptor<Pk, QExt>;
765
766 #[rustfmt::skip]
768 fn translate_ext<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
769 where
770 T: ExtTranslator<PExt, QExt, E>,
771 {
772 let desc = match *self {
773 Descriptor::Bare(ref bare) => Descriptor::Bare(bare.clone()),
774 Descriptor::Pkh(ref pk) => Descriptor::Pkh(pk.clone()),
775 Descriptor::Wpkh(ref pk) => Descriptor::Wpkh(pk.clone()),
776 Descriptor::Sh(ref sh) => Descriptor::Sh(sh.clone()),
777 Descriptor::Wsh(ref wsh) => Descriptor::Wsh(wsh.clone()),
778 Descriptor::Tr(ref tr) => Descriptor::Tr(tr.clone()),
779 Descriptor::TrExt(ref tr) => Descriptor::TrExt(
780 TranslateExt::<PExt, QExt>::translate_ext(tr, t)?,
781 ),
782 Descriptor::LegacyCSFSCov(ref cov) => {
783 Descriptor::LegacyCSFSCov(TranslateExt::<PExt, QExt>::translate_ext(
784 cov, t,
785 )?)
786 }
787 };
788 Ok(desc)
789 }
790}
791
792impl<Pk: MiniscriptKey, T: Extension> ForEachKey<Pk> for Descriptor<Pk, T> {
793 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
794 where
795 Pk: 'a,
796 {
797 match *self {
798 Descriptor::Bare(ref bare) => bare.for_each_key(pred),
799 Descriptor::Pkh(ref pkh) => pkh.for_each_key(pred),
800 Descriptor::Wpkh(ref wpkh) => wpkh.for_each_key(pred),
801 Descriptor::Wsh(ref wsh) => wsh.for_each_key(pred),
802 Descriptor::Sh(ref sh) => sh.for_each_key(pred),
803 Descriptor::LegacyCSFSCov(ref cov) => cov.for_any_key(pred),
804 Descriptor::Tr(ref tr) => tr.for_each_key(pred),
805 Descriptor::TrExt(ref tr) => tr.for_each_key(pred),
806 }
807 }
808}
809
810impl<Ext: Extension + ParseableExt> Descriptor<DescriptorPublicKey, Ext> {
811 #[deprecated(note = "use has_wildcards instead")]
813 pub fn is_deriveable(&self) -> bool {
814 self.has_wildcard()
815 }
816
817 pub fn has_wildcard(&self) -> bool {
819 self.for_any_key(|key| key.has_wildcard())
820 }
821
822 pub fn at_derivation_index(
828 &self,
829 index: u32,
830 ) -> Result<Descriptor<DefiniteDescriptorKey, Ext>, ConversionError> {
831 struct Derivator(u32);
832
833 impl Translator<DescriptorPublicKey, DefiniteDescriptorKey, ConversionError> for Derivator {
834 fn pk(
835 &mut self,
836 pk: &DescriptorPublicKey,
837 ) -> Result<DefiniteDescriptorKey, ConversionError> {
838 pk.clone().at_derivation_index(self.0)
839 }
840
841 translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, ConversionError);
842 }
843 self.translate_pk(&mut Derivator(index))
844 }
845
846 #[deprecated(note = "use at_derivation_index instead")]
847 pub fn derive(
849 &self,
850 index: u32,
851 ) -> Result<Descriptor<DefiniteDescriptorKey, Ext>, ConversionError> {
852 self.at_derivation_index(index)
853 }
854
855 pub fn derived_descriptor<C: secp256k1_zkp::Verification>(
881 &self,
882 secp: &secp256k1_zkp::Secp256k1<C>,
883 index: u32,
884 ) -> Result<Descriptor<bitcoin::PublicKey, Ext>, ConversionError> {
885 self.at_derivation_index(index)?.derived_descriptor(secp)
886 }
887
888 pub fn parse_descriptor<C: secp256k1_zkp::Signing>(
893 secp: &secp256k1_zkp::Secp256k1<C>,
894 s: &str,
895 ) -> Result<(Descriptor<DescriptorPublicKey, Ext>, KeyMap), Error> {
896 fn parse_key<C: secp256k1::Signing>(
897 s: &str,
898 key_map: &mut KeyMap,
899 secp: &secp256k1::Secp256k1<C>,
900 ) -> Result<DescriptorPublicKey, Error> {
901 let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
902 Ok(sk) => (
903 sk.to_public(secp)
904 .map_err(|e| Error::Unexpected(e.to_string()))?,
905 Some(sk),
906 ),
907 Err(_) => (
908 DescriptorPublicKey::from_str(s)
909 .map_err(|e| Error::Unexpected(e.to_string()))?,
910 None,
911 ),
912 };
913
914 if let Some(secret_key) = secret_key {
915 key_map.insert(public_key.clone(), secret_key);
916 }
917
918 Ok(public_key)
919 }
920
921 let mut keymap_pk = KeyMapWrapper(HashMap::new(), secp);
922
923 struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
924
925 impl<'a, C: secp256k1::Signing> Translator<String, DescriptorPublicKey, Error>
926 for KeyMapWrapper<'a, C>
927 {
928 fn pk(&mut self, pk: &String) -> Result<DescriptorPublicKey, Error> {
929 parse_key(pk, &mut self.0, self.1)
930 }
931
932 fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Error> {
933 let hash =
934 sha256::Hash::from_str(sha256).map_err(|e| Error::Unexpected(e.to_string()))?;
935 Ok(hash)
936 }
937
938 fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, Error> {
939 let hash = hash256::Hash::from_str(hash256)
940 .map_err(|e| Error::Unexpected(e.to_string()))?;
941 Ok(hash)
942 }
943
944 fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, Error> {
945 let hash = ripemd160::Hash::from_str(ripemd160)
946 .map_err(|e| Error::Unexpected(e.to_string()))?;
947 Ok(hash)
948 }
949
950 fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, Error> {
951 let hash = hash160::Hash::from_str(hash160)
952 .map_err(|e| Error::Unexpected(e.to_string()))?;
953 Ok(hash)
954 }
955 }
956
957 let descriptor = Descriptor::<String, Ext>::from_str(s)?;
958 let descriptor = descriptor
959 .translate_pk(&mut keymap_pk)
960 .map_err(|e| Error::Unexpected(e.to_string()))?;
961
962 Ok((descriptor, keymap_pk.0))
963 }
964
965 pub fn to_string_with_secret(&self, key_map: &KeyMap) -> String {
967 struct KeyMapLookUp<'a>(&'a KeyMap);
968
969 impl<'a> Translator<DescriptorPublicKey, String, ()> for KeyMapLookUp<'a> {
970 fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, ()> {
971 Ok(key_to_string(pk, self.0))
972 }
973
974 fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
975 Ok(sha256.to_string())
976 }
977
978 fn hash256(&mut self, hash256: &hash256::Hash) -> Result<String, ()> {
979 Ok(hash256.to_string())
980 }
981
982 fn ripemd160(&mut self, ripemd160: &ripemd160::Hash) -> Result<String, ()> {
983 Ok(ripemd160.to_string())
984 }
985
986 fn hash160(&mut self, hash160: &hash160::Hash) -> Result<String, ()> {
987 Ok(hash160.to_string())
988 }
989 }
990
991 fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> String {
992 match key_map.get(pk) {
993 Some(secret) => secret.to_string(),
994 None => pk.to_string(),
995 }
996 }
997
998 let descriptor = self
999 .translate_pk(&mut KeyMapLookUp(key_map))
1000 .expect("Translation to string cannot fail");
1001
1002 descriptor.to_string()
1003 }
1004
1005 pub fn is_multipath(&self) -> bool {
1007 self.for_any_key(DescriptorPublicKey::is_multipath)
1008 }
1009
1010 pub fn into_single_descriptors(self) -> Result<Vec<Self>, Error> {
1015 let mut descriptors = Vec::new();
1017 if !self.for_any_key(|key| {
1019 if !descriptors.is_empty() {
1022 return true;
1023 }
1024
1025 match key {
1026 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
1027 DescriptorPublicKey::MultiXPub(xpub) => {
1028 for _ in 0..xpub.derivation_paths.paths().len() {
1029 descriptors.push(self.clone());
1030 }
1031 true
1032 }
1033 }
1034 }) {
1035 return Ok(vec![self]);
1037 }
1038 assert!(!descriptors.is_empty());
1039
1040 struct IndexChoser(usize);
1042 impl Translator<DescriptorPublicKey, DescriptorPublicKey, Error> for IndexChoser {
1043 fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DescriptorPublicKey, Error> {
1044 match pk {
1045 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => {
1046 Ok(pk.clone())
1047 }
1048 DescriptorPublicKey::MultiXPub(_) => pk
1049 .clone()
1050 .into_single_keys()
1051 .get(self.0)
1052 .cloned()
1053 .ok_or(Error::MultipathDescLenMismatch),
1054 }
1055 }
1056 translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, Error);
1057 }
1058
1059 for (i, desc) in descriptors.iter_mut().enumerate() {
1060 let mut index_choser = IndexChoser(i);
1061 *desc = desc.translate_pk(&mut index_choser)?;
1062 }
1063
1064 Ok(descriptors)
1065 }
1066}
1067
1068impl<Ext: Extension + ParseableExt> Descriptor<DescriptorPublicKey, Ext> {
1069 pub fn find_derivation_index_for_spk<C: secp256k1_zkp::Verification>(
1077 &self,
1078 secp: &secp256k1_zkp::Secp256k1<C>,
1079 script_pubkey: &Script,
1080 range: Range<u32>,
1081 ) -> Result<Option<(u32, Descriptor<bitcoin::PublicKey, Ext>)>, ConversionError> {
1082 let range = if self.has_wildcard() { range } else { 0..1 };
1083
1084 for i in range {
1085 let concrete = self.derived_descriptor(secp, i)?;
1086 if &concrete.script_pubkey() == script_pubkey {
1087 return Ok(Some((i, concrete)));
1088 }
1089 }
1090
1091 Ok(None)
1092 }
1093}
1094
1095impl<Pk: MiniscriptKey, Ext: Extension> Descriptor<Pk, Ext> {
1096 pub fn multipath_length_mismatch(&self) -> bool {
1100 #[derive(PartialEq)]
1102 enum MultipathLenChecker {
1103 SinglePath,
1104 MultipathLen(usize),
1105 LenMismatch,
1106 }
1107
1108 let mut checker = MultipathLenChecker::SinglePath;
1109 self.for_each_key(|key| {
1110 match key.num_der_paths() {
1111 0 | 1 => {}
1112 n => match checker {
1113 MultipathLenChecker::SinglePath => {
1114 checker = MultipathLenChecker::MultipathLen(n);
1115 }
1116 MultipathLenChecker::MultipathLen(len) => {
1117 if len != n {
1118 checker = MultipathLenChecker::LenMismatch;
1119 }
1120 }
1121 MultipathLenChecker::LenMismatch => {}
1122 },
1123 }
1124 true
1125 });
1126
1127 checker == MultipathLenChecker::LenMismatch
1128 }
1129}
1130
1131impl<Ext: Extension> Descriptor<DefiniteDescriptorKey, Ext> {
1132 pub fn derived_descriptor<C: secp256k1::Verification>(
1156 &self,
1157 secp: &secp256k1::Secp256k1<C>,
1158 ) -> Result<Descriptor<bitcoin::PublicKey, Ext>, ConversionError> {
1159 struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
1160
1161 impl<'a, C: secp256k1::Verification>
1162 Translator<DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError>
1163 for Derivator<'a, C>
1164 {
1165 fn pk(
1166 &mut self,
1167 pk: &DefiniteDescriptorKey,
1168 ) -> Result<bitcoin::PublicKey, ConversionError> {
1169 pk.derive_public_key(self.0)
1170 }
1171
1172 translate_hash_clone!(DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError);
1173 }
1174
1175 let derived = self.translate_pk(&mut Derivator(secp))?;
1176 Ok(derived)
1177 }
1178}
1179
1180impl_from_tree!(
1181 ;T; Extension,
1182 Descriptor<Pk, T>,
1183 fn from_tree(top: &expression::Tree) -> Result<Descriptor<Pk, T>, Error> {
1185 Ok(match (top.name, top.args.len() as u32) {
1186 ("elpkh", 1) => Descriptor::Pkh(Pkh::from_tree(top)?),
1187 ("elwpkh", 1) => Descriptor::Wpkh(Wpkh::from_tree(top)?),
1188 ("elsh", 1) => Descriptor::Sh(Sh::from_tree(top)?),
1189 ("elcovwsh", 2) => Descriptor::LegacyCSFSCov(LegacyCSFSCov::from_tree(top)?),
1190 ("elwsh", 1) => Descriptor::Wsh(Wsh::from_tree(top)?),
1191 ("eltr", _) => Descriptor::Tr(Tr::from_tree(top)?),
1192 _ => Descriptor::Bare(Bare::from_tree(top)?),
1193 })
1194 }
1195);
1196
1197impl_from_str!(
1198 ;T; Extension,
1199 Descriptor<Pk, T>,
1200 type Err = Error;,
1201 fn from_str(s: &str) -> Result<Descriptor<Pk, T>, Error> {
1202 if !s.starts_with(ELMTS_STR) {
1203 return Err(Error::BadDescriptor(String::from(
1204 "Not an Elements Descriptor",
1205 )));
1206 }
1207 let desc = if s.starts_with(&format!("{}tr", ELMTS_STR)) {
1211 match Tr::<Pk, NoExt>::from_str(s) {
1213 Ok(tr) => Descriptor::Tr(tr),
1214 Err(_) => {
1215 let tr = Tr::<Pk, T>::from_str(s)?;
1217 Descriptor::TrExt(tr)
1218 }
1219 }
1220 } else {
1221 let desc_str = verify_checksum(s)?;
1222 let top = expression::Tree::from_str(desc_str)?;
1223 expression::FromTree::from_tree(&top)?
1224 };
1225
1226 if desc.multipath_length_mismatch() {
1227 return Err(Error::MultipathDescLenMismatch);
1228 }
1229
1230 Ok(desc)
1231 }
1232);
1233
1234impl<Pk: MiniscriptKey, T: Extension> fmt::Debug for Descriptor<Pk, T> {
1235 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1236 match *self {
1237 Descriptor::Bare(ref sub) => fmt::Debug::fmt(sub, f),
1238 Descriptor::Pkh(ref pkh) => fmt::Debug::fmt(pkh, f),
1239 Descriptor::Wpkh(ref wpkh) => fmt::Debug::fmt(wpkh, f),
1240 Descriptor::Sh(ref sub) => fmt::Debug::fmt(sub, f),
1241 Descriptor::Wsh(ref sub) => fmt::Debug::fmt(sub, f),
1242 Descriptor::Tr(ref tr) => fmt::Debug::fmt(tr, f),
1243 Descriptor::TrExt(ref tr) => fmt::Debug::fmt(tr, f),
1244 Descriptor::LegacyCSFSCov(ref cov) => fmt::Debug::fmt(cov, f),
1245 }
1246 }
1247}
1248
1249impl<Pk: MiniscriptKey, T: Extension> fmt::Display for Descriptor<Pk, T> {
1250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1251 match *self {
1252 Descriptor::Bare(ref sub) => fmt::Display::fmt(sub, f),
1253 Descriptor::Pkh(ref pkh) => fmt::Display::fmt(pkh, f),
1254 Descriptor::Wpkh(ref wpkh) => fmt::Display::fmt(wpkh, f),
1255 Descriptor::Sh(ref sub) => fmt::Display::fmt(sub, f),
1256 Descriptor::Wsh(ref sub) => fmt::Display::fmt(sub, f),
1257 Descriptor::Tr(ref tr) => fmt::Display::fmt(tr, f),
1258 Descriptor::TrExt(ref tr) => fmt::Display::fmt(tr, f),
1259 Descriptor::LegacyCSFSCov(ref cov) => fmt::Display::fmt(cov, f),
1260 }
1261 }
1262}
1263
1264serde_string_impl_pk!(Descriptor, "a script descriptor", T; Extension);
1265
1266#[cfg(test)]
1267mod tests {
1268 use std::collections::HashMap;
1269 use std::str::FromStr;
1270
1271 use bitcoin;
1272 use bitcoin::hashes::{hash160, sha256};
1273 use bitcoin::hex::{DisplayHex, FromHex};
1274 use bitcoin::{bip32, PublicKey};
1275 use elements::opcodes::all::{OP_CLTV, OP_CSV};
1276 use elements::script::Instruction;
1277 use elements::{opcodes, script, Sequence};
1278
1279 use super::checksum::desc_checksum;
1280 use super::tr::Tr;
1281 use super::*;
1282 use crate::descriptor::key::Wildcard;
1283 use crate::descriptor::{DescriptorPublicKey, DescriptorXKey};
1284 use crate::miniscript::satisfy::ElementsSig;
1285 #[cfg(feature = "compiler")]
1286 use crate::policy;
1287 use crate::{hex_script, Descriptor, Error, Miniscript, NoExt, Satisfier};
1288
1289 type StdDescriptor = Descriptor<PublicKey, CovenantExt<CovExtArgs>>;
1290 const TEST_PK: &str =
1291 "elpk(020000000000000000000000000000000000000000000000000000000000000002)";
1292
1293 fn roundtrip_descriptor(s: &str) {
1294 let desc = Descriptor::<String>::from_str(s).unwrap();
1295 let output = desc.to_string();
1296 let normalize_aliases = s.replace("c:pk_k(", "pk(").replace("c:pk_h(", "pkh(");
1297 assert_eq!(
1298 format!(
1299 "{}#{}",
1300 &normalize_aliases,
1301 desc_checksum(&normalize_aliases).unwrap()
1302 ),
1303 output
1304 );
1305 }
1306
1307 fn elements_txin(script_sig: Script, witness: Vec<Vec<u8>>) -> elements::TxIn {
1309 let txin_witness = elements::TxInWitness {
1310 script_witness: witness.into(),
1311 ..Default::default()
1312 };
1313 elements::TxIn {
1314 previous_output: elements::OutPoint::default(),
1315 script_sig,
1316 sequence: Sequence::from_height(100),
1317 is_pegin: false,
1318 asset_issuance: elements::AssetIssuance::default(),
1319 witness: txin_witness,
1320 }
1321 }
1322
1323 #[test]
1324 fn desc_rtt_tests() {
1325 roundtrip_descriptor("elc:pk_k()");
1326 roundtrip_descriptor("elwsh(pk())");
1327 roundtrip_descriptor("elwsh(c:pk_k())");
1328 roundtrip_descriptor("elc:pk_h()");
1329 }
1330 #[test]
1331 fn parse_descriptor() {
1332 StdDescriptor::from_str("(").unwrap_err();
1333 StdDescriptor::from_str("(x()").unwrap_err();
1334 StdDescriptor::from_str("(\u{7f}()3").unwrap_err();
1335 StdDescriptor::from_str("pk()").unwrap_err();
1336 StdDescriptor::from_str("nl:0").unwrap_err(); let compressed_pk = "02be5645686309c6e6736dbd93940707cc9143d3cf29f1b877ff340e2cb2d259cf";
1338 assert_eq!(
1339 StdDescriptor::from_str("elsh(sortedmulti)")
1340 .unwrap_err()
1341 .to_string(),
1342 "unexpected «no arguments given for sortedmulti»"
1343 ); assert_eq!(
1345 StdDescriptor::from_str(&format!("elsh(sortedmulti(2,{}))", compressed_pk))
1346 .unwrap_err()
1347 .to_string(),
1348 "unexpected «higher threshold than there were keys in sortedmulti»"
1349 ); StdDescriptor::from_str(TEST_PK).unwrap();
1352 StdDescriptor::from_str("slip77").unwrap_err();
1354
1355 let uncompressed_pk =
1356 "0414fc03b8df87cd7b872996810db8458d61da8448e531569c8517b469a119d267be5645686309c6e6736dbd93940707cc9143d3cf29f1b877ff340e2cb2d259cf";
1357
1358 StdDescriptor::from_str(&format!("elpk({})", uncompressed_pk)).unwrap();
1360 StdDescriptor::from_str(&format!("elpkh({})", uncompressed_pk)).unwrap();
1361 StdDescriptor::from_str(&format!("elsh(pk({}))", uncompressed_pk)).unwrap();
1362 StdDescriptor::from_str(&format!("elwpkh({})", uncompressed_pk)).unwrap_err();
1363 StdDescriptor::from_str(&format!("elsh(wpkh({}))", uncompressed_pk)).unwrap_err();
1364 StdDescriptor::from_str(&format!("elwsh(pk{})", uncompressed_pk)).unwrap_err();
1365 StdDescriptor::from_str(&format!("elsh(wsh(pk{}))", uncompressed_pk)).unwrap_err();
1366 StdDescriptor::from_str(&format!(
1367 "elor_i(pk({}),pk({}))",
1368 uncompressed_pk, uncompressed_pk
1369 ))
1370 .unwrap_err();
1371 }
1372
1373 #[test]
1374 pub fn script_pubkey() {
1375 let bare = StdDescriptor::from_str(
1376 "elmulti(1,020000000000000000000000000000000000000000000000000000000000000002)",
1377 )
1378 .unwrap();
1379 assert_eq!(
1380 bare.script_pubkey(),
1381 hex_script(
1382 "512102000000000000000000000000000000000000000000000000000000000000000251ae"
1383 )
1384 );
1385 assert_eq!(
1386 bare.address(&elements::AddressParams::ELEMENTS)
1387 .unwrap_err()
1388 .to_string(),
1389 "Bare descriptors don't have address"
1390 );
1391
1392 let pk = StdDescriptor::from_str(TEST_PK).unwrap();
1393 assert_eq!(
1394 pk.script_pubkey(),
1395 elements::Script::from(vec![
1396 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1398 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xac,
1399 ])
1400 );
1401
1402 let pkh = StdDescriptor::from_str(
1403 "elpkh(\
1404 020000000000000000000000000000000000000000000000000000000000000002\
1405 )",
1406 )
1407 .unwrap();
1408 assert_eq!(
1409 pkh.script_pubkey(),
1410 script::Builder::new()
1411 .push_opcode(opcodes::all::OP_DUP)
1412 .push_opcode(opcodes::all::OP_HASH160)
1413 .push_slice(
1414 &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap()
1415 [..]
1416 )
1417 .push_opcode(opcodes::all::OP_EQUALVERIFY)
1418 .push_opcode(opcodes::all::OP_CHECKSIG)
1419 .into_script()
1420 );
1421 assert_eq!(
1422 pkh.address(&elements::AddressParams::ELEMENTS,)
1423 .unwrap()
1424 .to_string(),
1425 "2dmYXpSu8YP6aLcJYhHfB1C19mdzSx2GPB9"
1426 );
1427
1428 let wpkh = StdDescriptor::from_str(
1429 "elwpkh(\
1430 020000000000000000000000000000000000000000000000000000000000000002\
1431 )",
1432 )
1433 .unwrap();
1434 assert_eq!(
1435 wpkh.script_pubkey(),
1436 script::Builder::new()
1437 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1438 .push_slice(
1439 &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap()
1440 [..]
1441 )
1442 .into_script()
1443 );
1444 assert_eq!(
1445 wpkh.address(&elements::AddressParams::ELEMENTS,)
1446 .unwrap()
1447 .to_string(),
1448 "ert1qsn57m9drscflq5nl76z6ny52hck5w4x57m69k3"
1449 );
1450
1451 let shwpkh = StdDescriptor::from_str(
1452 "elsh(wpkh(\
1453 020000000000000000000000000000000000000000000000000000000000000002\
1454 ))",
1455 )
1456 .unwrap();
1457 assert_eq!(
1458 shwpkh.script_pubkey(),
1459 script::Builder::new()
1460 .push_opcode(opcodes::all::OP_HASH160)
1461 .push_slice(
1462 &hash160::Hash::from_str("f1c3b9a431134cb90a500ec06e0067cfa9b8bba7",).unwrap()
1463 [..]
1464 )
1465 .push_opcode(opcodes::all::OP_EQUAL)
1466 .into_script()
1467 );
1468 assert_eq!(
1469 shwpkh
1470 .address(&elements::AddressParams::ELEMENTS,)
1471 .unwrap()
1472 .to_string(),
1473 "XZPaAbg6M83Fq5NqvbEGZ5kwy9RKSTke2s"
1474 );
1475
1476 let sh = StdDescriptor::from_str(
1477 "elsh(c:pk_k(\
1478 020000000000000000000000000000000000000000000000000000000000000002\
1479 ))",
1480 )
1481 .unwrap();
1482 assert_eq!(
1483 sh.script_pubkey(),
1484 script::Builder::new()
1485 .push_opcode(opcodes::all::OP_HASH160)
1486 .push_slice(
1487 &hash160::Hash::from_str("aa5282151694d3f2f32ace7d00ad38f927a33ac8",).unwrap()
1488 [..]
1489 )
1490 .push_opcode(opcodes::all::OP_EQUAL)
1491 .into_script()
1492 );
1493 assert_eq!(
1494 sh.address(&elements::AddressParams::ELEMENTS,)
1495 .unwrap()
1496 .to_string(),
1497 "XSspZXDJu2XVh8AKC7qF3L7x79Qy67JhQb"
1498 );
1499
1500 let wsh = StdDescriptor::from_str(
1501 "elwsh(c:pk_k(\
1502 020000000000000000000000000000000000000000000000000000000000000002\
1503 ))",
1504 )
1505 .unwrap();
1506 assert_eq!(
1507 wsh.script_pubkey(),
1508 script::Builder::new()
1509 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1510 .push_slice(
1511 &sha256::Hash::from_str(
1512 "\
1513 f9379edc8983152dc781747830075bd5\
1514 3896e4b0ce5bff73777fd77d124ba085\
1515 "
1516 )
1517 .unwrap()[..]
1518 )
1519 .into_script()
1520 );
1521 assert_eq!(
1522 wsh.address(&elements::AddressParams::ELEMENTS,)
1523 .unwrap()
1524 .to_string(),
1525 "ert1qlymeahyfsv2jm3upw3urqp6m65ufde9seedl7umh0lth6yjt5zzsan9u2t"
1526 );
1527
1528 let shwsh = StdDescriptor::from_str(
1529 "elsh(wsh(c:pk_k(\
1530 020000000000000000000000000000000000000000000000000000000000000002\
1531 )))",
1532 )
1533 .unwrap();
1534 assert_eq!(
1535 shwsh.script_pubkey(),
1536 script::Builder::new()
1537 .push_opcode(opcodes::all::OP_HASH160)
1538 .push_slice(
1539 &hash160::Hash::from_str("4bec5d7feeed99e1d0a23fe32a4afe126a7ff07e",).unwrap()
1540 [..]
1541 )
1542 .push_opcode(opcodes::all::OP_EQUAL)
1543 .into_script()
1544 );
1545 assert_eq!(
1546 shwsh
1547 .address(&elements::AddressParams::ELEMENTS,)
1548 .unwrap()
1549 .to_string(),
1550 "XJGggUb965TvGF2VCxp9EQGmZTxMeDjwQQ"
1551 );
1552 }
1553
1554 #[test]
1555 fn satisfy() {
1556 let secp = secp256k1_zkp::Secp256k1::new();
1557 let sk =
1558 secp256k1_zkp::SecretKey::from_slice(&b"sally was a secret key, she said"[..]).unwrap();
1559 let pk = bitcoin::PublicKey {
1560 inner: secp256k1_zkp::PublicKey::from_secret_key(&secp, &sk),
1561 compressed: true,
1562 };
1563 let msg =
1564 secp256k1_zkp::Message::from_digest_slice(&b"michael was a message, amusingly"[..])
1565 .expect("32 bytes");
1566 let sig = secp.sign_ecdsa(&msg, &sk);
1567 let mut sigser = sig.serialize_der().to_vec();
1568 sigser.push(0x01); struct SimpleSat {
1571 sig: secp256k1_zkp::ecdsa::Signature,
1572 pk: bitcoin::PublicKey,
1573 }
1574
1575 impl Satisfier<bitcoin::PublicKey> for SimpleSat {
1576 fn lookup_ecdsa_sig(&self, pk: &bitcoin::PublicKey) -> Option<ElementsSig> {
1577 if *pk == self.pk {
1578 Some((self.sig, elements::EcdsaSighashType::All))
1579 } else {
1580 None
1581 }
1582 }
1583 }
1584
1585 let satisfier = SimpleSat { sig, pk };
1586 let ms = ms_str!("c:pk_k({})", pk);
1587
1588 let mut txin = elements::TxIn {
1589 previous_output: elements::OutPoint::default(),
1590 script_sig: Script::new(),
1591 sequence: Sequence::from_height(100),
1592 is_pegin: false,
1593 asset_issuance: elements::AssetIssuance::default(),
1594 witness: elements::TxInWitness::default(),
1595 };
1596 let bare: Descriptor<_, NoExt> = Descriptor::new_bare(ms).unwrap();
1597
1598 bare.satisfy(&mut txin, &satisfier).expect("satisfaction");
1599 assert_eq!(
1600 txin,
1601 elements_txin(
1602 script::Builder::new().push_slice(&sigser[..]).into_script(),
1603 vec![]
1604 ),
1605 );
1606 assert_eq!(bare.unsigned_script_sig(), elements::Script::new());
1607
1608 let pkh: Descriptor<_, NoExt> = Descriptor::new_pkh(pk);
1609 pkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1610 assert_eq!(
1611 txin,
1612 elements_txin(
1613 script::Builder::new()
1614 .push_slice(&sigser[..])
1615 .push_key(&pk)
1616 .into_script(),
1617 vec![]
1618 )
1619 );
1620 assert_eq!(pkh.unsigned_script_sig(), elements::Script::new());
1621
1622 let wpkh: Descriptor<_, NoExt> = Descriptor::new_wpkh(pk).unwrap();
1623 wpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1624 assert_eq!(
1625 txin,
1626 elements_txin(Script::new(), vec![sigser.clone(), pk.to_bytes(),])
1627 );
1628 assert_eq!(wpkh.unsigned_script_sig(), elements::Script::new());
1629
1630 let shwpkh: Descriptor<_, NoExt> = Descriptor::new_sh_wpkh(pk).unwrap();
1631 shwpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1632 let redeem_script = script::Builder::new()
1633 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1634 .push_slice(
1635 &hash160::Hash::from_str("d1b2a1faf62e73460af885c687dee3b7189cd8ab").unwrap()[..],
1636 )
1637 .into_script();
1638 let expected_ssig = script::Builder::new()
1639 .push_slice(&redeem_script[..])
1640 .into_script();
1641 assert_eq!(
1642 txin,
1643 elements_txin(expected_ssig.clone(), vec![sigser.clone(), pk.to_bytes()])
1644 );
1645 assert_eq!(shwpkh.unsigned_script_sig(), expected_ssig);
1646
1647 let ms = ms_str!("c:pk_k({})", pk);
1648 let sh: Descriptor<_, NoExt> = Descriptor::new_sh(ms.clone()).unwrap();
1649 sh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1650 let expected_ssig = script::Builder::new()
1651 .push_slice(&sigser[..])
1652 .push_slice(&ms.encode()[..])
1653 .into_script();
1654 assert_eq!(txin, elements_txin(expected_ssig, vec![]));
1655 assert_eq!(sh.unsigned_script_sig(), Script::new());
1656
1657 let ms = ms_str!("c:pk_k({})", pk);
1658
1659 let wsh: Descriptor<_, NoExt> = Descriptor::new_wsh(ms.clone()).unwrap();
1660 wsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1661 assert_eq!(
1662 txin,
1663 elements_txin(
1664 Script::new(),
1665 vec![sigser.clone(), ms.encode().into_bytes()]
1666 )
1667 );
1668 assert_eq!(wsh.unsigned_script_sig(), Script::new());
1669
1670 let shwsh: Descriptor<_, NoExt> = Descriptor::new_sh_wsh(ms.clone()).unwrap();
1671 shwsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1672 let expected_ssig = script::Builder::new()
1673 .push_slice(&ms.encode().to_v0_p2wsh()[..])
1674 .into_script();
1675 assert_eq!(
1676 txin,
1677 elements_txin(
1678 expected_ssig.clone(),
1679 vec![sigser.clone(), ms.encode().into_bytes(),]
1680 )
1681 );
1682 assert_eq!(shwsh.unsigned_script_sig(), expected_ssig);
1683 }
1684
1685 #[test]
1686 fn after_is_cltv() {
1687 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("elwsh(after(1000))").unwrap();
1688 let script = descriptor.explicit_script().unwrap();
1689
1690 let actual_instructions: Vec<_> = script.instructions().collect();
1691 let check = actual_instructions.last().unwrap();
1692
1693 assert_eq!(check, &Ok(Instruction::Op(OP_CLTV)))
1694 }
1695
1696 #[test]
1697 fn older_is_csv() {
1698 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("elwsh(older(1000))").unwrap();
1699 let script = descriptor.explicit_script().unwrap();
1700
1701 let actual_instructions: Vec<_> = script.instructions().collect();
1702 let check = actual_instructions.last().unwrap();
1703
1704 assert_eq!(check, &Ok(Instruction::Op(OP_CSV)))
1705 }
1706
1707 #[test]
1708 fn tr_roundtrip_key() {
1709 let script = Tr::<String>::from_str("eltr()").unwrap().to_string();
1710 assert_eq!(script, format!("eltr()#sux3r82e"))
1711 }
1712
1713 #[test]
1714 fn tr_roundtrip_script() {
1715 let descriptor = Tr::<String>::from_str("eltr(,{pk(),pk()})")
1716 .unwrap()
1717 .to_string();
1718
1719 assert_eq!(descriptor, "eltr(,{pk(),pk()})#lxgcxh02");
1720
1721 let descriptor = Descriptor::<String>::from_str("eltr(A,{pk(B),pk(C)})")
1722 .unwrap()
1723 .to_string();
1724 assert_eq!(descriptor, "eltr(A,{pk(B),pk(C)})#cx98s50f");
1725 }
1726
1727 #[test]
1728 fn tr_roundtrip_tree() {
1729 let p1 = "020000000000000000000000000000000000000000000000000000000000000001";
1730 let p2 = "020000000000000000000000000000000000000000000000000000000000000002";
1731 let p3 = "020000000000000000000000000000000000000000000000000000000000000003";
1732 let p4 = "020000000000000000000000000000000000000000000000000000000000000004";
1733 let p5 = "03f8551772d66557da28c1de858124f365a8eb30ce6ad79c10e0f4c546d0ab0f82";
1734 let descriptor = Tr::<PublicKey>::from_str(&format!(
1735 "eltr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})",
1736 p1, p2, p3, p4, p5
1737 ))
1738 .unwrap()
1739 .to_string();
1740
1741 assert_eq!(
1743 descriptor,
1744 format!(
1745 "eltr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})#y9kzzx3w",
1746 p1, p2, p3, p4, p5
1747 )
1748 )
1749 }
1750
1751 #[test]
1752 fn tr_script_pubkey() {
1753 let key = Descriptor::<bitcoin::PublicKey>::from_str(
1754 "eltr(02e20e746af365e86647826397ba1c0e0d5cb685752976fe2f326ab76bdc4d6ee9)",
1755 )
1756 .unwrap();
1757 assert_eq!(
1758 key.script_pubkey().as_bytes().to_lower_hex_string(),
1759 "51203f48e7c6203a75722733e3d9d06638da38d946066159c64684caf1622b2b0e33"
1760 )
1761 }
1762
1763 #[test]
1764 fn roundtrip_tests() {
1765 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("elmulti");
1766 assert_eq!(
1767 descriptor.unwrap_err().to_string(),
1768 "unexpected «no arguments given»"
1769 )
1770 }
1771
1772 #[test]
1773 fn empty_thresh() {
1774 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("elthresh");
1775 assert_eq!(
1776 descriptor.unwrap_err().to_string(),
1777 "unexpected «no arguments given»"
1778 )
1779 }
1780
1781 #[test]
1782 fn witness_stack_for_andv_is_arranged_in_correct_order() {
1783 let a = bitcoin::PublicKey::from_str(
1785 "02937402303919b3a2ee5edd5009f4236f069bf75667b8e6ecf8e5464e20116a0e",
1786 )
1787 .unwrap();
1788 let sig_a = secp256k1_zkp::ecdsa::Signature::from_str("3045022100a7acc3719e9559a59d60d7b2837f9842df30e7edcd754e63227e6168cec72c5d022066c2feba4671c3d99ea75d9976b4da6c86968dbf3bab47b1061e7a1966b1778c").unwrap();
1789
1790 let b = bitcoin::PublicKey::from_str(
1791 "02eb64639a17f7334bb5a1a3aad857d6fec65faef439db3de72f85c88bc2906ad3",
1792 )
1793 .unwrap();
1794 let sig_b = secp256k1_zkp::ecdsa::Signature::from_str("3044022075b7b65a7e6cd386132c5883c9db15f9a849a0f32bc680e9986398879a57c276022056d94d12255a4424f51c700ac75122cb354895c9f2f88f0cbb47ba05c9c589ba").unwrap();
1795
1796 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str(&format!(
1797 "elwsh(and_v(v:pk({A}),pk({B})))",
1798 A = a,
1799 B = b
1800 ))
1801 .unwrap();
1802
1803 let mut txin = elements_txin(Script::new(), vec![]);
1804 let satisfier = {
1805 let mut satisfier = HashMap::with_capacity(2);
1806
1807 satisfier.insert(a, (sig_a, ::elements::EcdsaSighashType::All));
1808 satisfier.insert(b, (sig_b, ::elements::EcdsaSighashType::All));
1809
1810 satisfier
1811 };
1812
1813 descriptor.satisfy(&mut txin, &satisfier).unwrap();
1815
1816 let witness0 = &txin.witness.script_witness[0];
1818 let witness1 = &txin.witness.script_witness[1];
1819
1820 let sig0 =
1821 secp256k1_zkp::ecdsa::Signature::from_der(&witness0[..witness0.len() - 1]).unwrap();
1822 let sig1 =
1823 secp256k1_zkp::ecdsa::Signature::from_der(&witness1[..witness1.len() - 1]).unwrap();
1824
1825 assert_eq!(sig1, sig_a);
1830 assert_eq!(sig0, sig_b);
1831 }
1832
1833 #[test]
1834 fn test_scriptcode() {
1835 let descriptor = Descriptor::<PublicKey>::from_str(
1837 "elwpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
1838 )
1839 .unwrap();
1840 assert_eq!(
1841 *descriptor.script_code().unwrap().as_bytes(),
1842 Vec::<u8>::from_hex("76a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac").unwrap()[..]
1843 );
1844
1845 let descriptor = Descriptor::<PublicKey>::from_str(
1847 "elsh(wpkh(03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873))",
1848 )
1849 .unwrap();
1850 assert_eq!(
1851 *descriptor.script_code().unwrap().as_bytes(),
1852 Vec::<u8>::from_hex("76a91479091972186c449eb1ded22b78e40d009bdf008988ac").unwrap()[..]
1853 );
1854
1855 let descriptor = Descriptor::<PublicKey>::from_str(
1857 "elwsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626))",
1858 )
1859 .unwrap();
1860 assert_eq!(
1861 *descriptor
1862 .script_code().unwrap()
1863 .as_bytes(),
1864 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae").unwrap()[..]
1865 );
1866
1867 let descriptor = Descriptor::<PublicKey>::from_str("elsh(wsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626)))").unwrap();
1869 assert_eq!(
1870 *descriptor
1871 .script_code().unwrap()
1872 .as_bytes(),
1873 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae")
1874 .unwrap()[..]
1875 );
1876 }
1877
1878 #[test]
1879 fn parse_descriptor_key() {
1880 let key = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*";
1882 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1883 origin: Some((
1884 bip32::Fingerprint::from([0x78, 0x41, 0x2e, 0x3a]),
1885 (&[
1886 bip32::ChildNumber::from_hardened_idx(44).unwrap(),
1887 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1888 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1889 ][..])
1890 .into(),
1891 )),
1892 xkey: bip32::Xpub::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1893 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1894 wildcard: Wildcard::Unhardened,
1895 });
1896 assert_eq!(expected, key.parse().unwrap());
1897 assert_eq!(format!("{}", expected), key);
1898
1899 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1";
1901 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1902 origin: None,
1903 xkey: bip32::Xpub::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1904 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1905 wildcard: Wildcard::None,
1906 });
1907 assert_eq!(expected, key.parse().unwrap());
1908 assert_eq!(format!("{}", expected), key);
1909
1910 let key = "tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed/1";
1912 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1913 origin: None,
1914 xkey: bip32::Xpub::from_str("tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed").unwrap(),
1915 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1916 wildcard: Wildcard::None,
1917 });
1918 assert_eq!(expected, key.parse().unwrap());
1919 assert_eq!(format!("{}", expected), key);
1920
1921 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
1923 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1924 origin: None,
1925 xkey: bip32::Xpub::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1926 derivation_path: bip32::DerivationPath::from(&[][..]),
1927 wildcard: Wildcard::None,
1928 });
1929 assert_eq!(expected, key.parse().unwrap());
1930 assert_eq!(format!("{}", expected), key);
1931
1932 let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
1934 let expected = DescriptorPublicKey::Single(SinglePub {
1935 key: SinglePubKey::FullKey(
1936 bitcoin::PublicKey::from_str(
1937 "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8",
1938 )
1939 .unwrap(),
1940 ),
1941 origin: None,
1942 });
1943 assert_eq!(expected, key.parse().unwrap());
1944 assert_eq!(format!("{}", expected), key);
1945
1946 let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a";
1948 let expected = DescriptorPublicKey::Single(SinglePub {
1949 key: SinglePubKey::FullKey(bitcoin::PublicKey::from_str(
1950 "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a",
1951 )
1952 .unwrap()),
1953 origin: None,
1954 });
1955 assert_eq!(expected, key.parse().unwrap());
1956 assert_eq!(format!("{}", expected), key);
1957
1958 let desc =
1960 "[78412e3a/0'/42/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8";
1961 let expected = DescriptorPublicKey::Single(SinglePub {
1962 key: SinglePubKey::FullKey(
1963 bitcoin::PublicKey::from_str(
1964 "0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8",
1965 )
1966 .unwrap(),
1967 ),
1968 origin: Some((
1969 bip32::Fingerprint::from([0x78, 0x41, 0x2e, 0x3a]),
1970 (&[
1971 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1972 bip32::ChildNumber::from_normal_idx(42).unwrap(),
1973 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1974 ][..])
1975 .into(),
1976 )),
1977 });
1978 assert_eq!(expected, desc.parse().expect("Parsing desc"));
1979 assert_eq!(format!("{}", expected), desc);
1980 }
1981
1982 #[test]
1983 fn test_sortedmulti() {
1984 fn _test_sortedmulti(raw_desc_one: &str, raw_desc_two: &str, raw_addr_expected: &str) {
1985 let secp_ctx = secp256k1_zkp::Secp256k1::verification_only();
1986 let index = 5;
1987
1988 let desc_one = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_one).unwrap();
1990 let desc_two = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_two).unwrap();
1991
1992 assert_eq!(desc_one.to_string(), raw_desc_one);
1994 assert_eq!(desc_two.to_string(), raw_desc_two);
1995
1996 let addr_one = desc_one
1998 .at_derivation_index(index)
1999 .unwrap()
2000 .derived_descriptor(&secp_ctx)
2001 .unwrap()
2002 .address(&elements::AddressParams::ELEMENTS)
2003 .unwrap();
2004 let addr_two = desc_two
2005 .at_derivation_index(index)
2006 .unwrap()
2007 .derived_descriptor(&secp_ctx)
2008 .unwrap()
2009 .address(&elements::AddressParams::ELEMENTS)
2010 .unwrap();
2011 let addr_expected = elements::Address::from_str(raw_addr_expected).unwrap();
2012 assert_eq!(addr_one, addr_expected);
2013 assert_eq!(addr_two, addr_expected);
2014 }
2015
2016 _test_sortedmulti(
2018 "elsh(sortedmulti(1,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352))#tse3qz98",
2019 "elsh(sortedmulti(1,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))#ptnf05qc",
2020 "XUDXJZnP2GXsKRKdxSLKzJM1iZ4gbbyrGh",
2021 );
2022
2023 _test_sortedmulti(
2025 "elwsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH))#a8h2v83d",
2026 "elwsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB))#qfcn7ujk",
2027 "ert1qpq2cfgz5lktxzr5zqv7nrzz46hsvq3492ump9pz8rzcl8wqtwqcs2yqnuv",
2028 );
2029
2030 _test_sortedmulti(
2032 "elsh(wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*)))#l7qy253t",
2033 "elsh(wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*)))#0gpee5cl",
2034 "XBkDY63XnRTz6BbwzJi3ifGhBwLTomEzkq",
2035 );
2036 }
2037
2038 #[test]
2039 fn test_parse_descriptor() {
2040 let secp = &secp256k1_zkp::Secp256k1::signing_only();
2041 let (descriptor, key_map) = Descriptor::<_, NoExt>::parse_descriptor(secp, "elwpkh(tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/44'/0'/0'/0/*)").unwrap();
2042 assert_eq!(descriptor.to_string(), "elwpkh([2cbe2a6d/44'/0'/0']tpubDCvNhURocXGZsLNqWcqD3syHTqPXrMSTwi8feKVwAcpi29oYKsDD3Vex7x2TDneKMVN23RbLprfxB69v94iYqdaYHsVz3kPR37NQXeqouVz/0/*)#pznhhta9");
2043 assert_eq!(key_map.len(), 1);
2044
2045 macro_rules! check_invalid_checksum {
2047 ($secp: ident,$($desc: expr),*) => {
2048 $(
2049 match Descriptor::<_, NoExt>::parse_descriptor($secp, $desc) {
2050 Err(Error::BadDescriptor(_)) => {},
2051 Err(e) => panic!("Expected bad checksum for {}, got '{}'", $desc, e),
2052 _ => panic!("Invalid checksum treated as valid: {}", $desc),
2053 };
2054 )*
2055 };
2056 }
2057 check_invalid_checksum!(secp,
2058 "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#",
2059 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#",
2060 "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf",
2061 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq",
2062 "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf",
2063 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5",
2064 "elsh(multi(3,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy",
2065 "elsh(multi(3,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t",
2066 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjq09x4t",
2067 "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))##ggssrxfy",
2068 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))##tjq09x4t"
2069 );
2070
2071 Descriptor::<_, NoExt>::parse_descriptor(secp, "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#9s2ngs7u").expect("Valid descriptor with checksum");
2072 Descriptor::<_, NoExt>::parse_descriptor(secp, "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#uklept69").expect("Valid descriptor with checksum");
2073 }
2074
2075 #[test]
2076 #[cfg(feature = "compiler")]
2077 fn parse_and_derive() {
2078 let descriptor_str = "thresh(2,\
2079pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*),\
2080pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
2081pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
2082 let policy: policy::concrete::Policy<DescriptorPublicKey> = descriptor_str.parse().unwrap();
2083 let descriptor = Descriptor::<_, NoExt>::new_sh(policy.compile().unwrap()).unwrap();
2084 let definite_descriptor = descriptor.at_derivation_index(42).unwrap();
2085
2086 let res_descriptor_str = "thresh(2,\
2087pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42),\
2088pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
2089pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
2090 let res_policy: policy::concrete::Policy<DescriptorPublicKey> =
2091 res_descriptor_str.parse().unwrap();
2092 let res_descriptor =
2093 Descriptor::<DescriptorPublicKey, NoExt>::new_sh(res_policy.compile().unwrap())
2094 .unwrap();
2095
2096 assert_eq!(res_descriptor.to_string(), definite_descriptor.to_string());
2097 }
2098
2099 #[test]
2100 fn parse_with_secrets() {
2101 let secp = &secp256k1_zkp::Secp256k1::signing_only();
2102 let descriptor_str = "elwpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)#xldrpn5u";
2103 let (descriptor, keymap) =
2104 Descriptor::<DescriptorPublicKey>::parse_descriptor(secp, descriptor_str).unwrap();
2105
2106 let expected = "elwpkh([a12b02f4/44'/0'/0']xpub6BzhLAQUDcBUfHRQHZxDF2AbcJqp4Kaeq6bzJpXrjrWuK26ymTFwkEFbxPra2bJ7yeZKbDjfDeFwxe93JMqpo5SsPJH6dZdvV9kMzJkAZ69/0/*)#20ufqv7z";
2107 assert_eq!(expected, descriptor.to_string());
2108 assert_eq!(keymap.len(), 1);
2109
2110 assert_eq!(descriptor_str, descriptor.to_string_with_secret(&keymap));
2112 }
2113
2114 #[test]
2115 fn checksum_for_nested_sh() {
2116 let descriptor_str = "elsh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))";
2117 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
2118 assert_eq!(descriptor.to_string(), "elsh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))#2040pn7l");
2119
2120 let descriptor_str = "elsh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))";
2121 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
2122 assert_eq!(descriptor.to_string(), "elsh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))#pqs0de7e");
2123 }
2124
2125 #[test]
2126 fn test_xonly_keys() {
2127 let comp_key = "0308c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
2128 let x_only_key = "08c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
2129
2130 Descriptor::<DescriptorPublicKey>::from_str(&format!("eltr({})", comp_key)).unwrap();
2132 Descriptor::<DescriptorPublicKey>::from_str(&format!("eltr({})", x_only_key)).unwrap();
2133
2134 Descriptor::<DescriptorPublicKey>::from_str(&format!("elwsh(pk({}))", comp_key)).unwrap();
2136 Descriptor::<DescriptorPublicKey>::from_str(&format!("elwsh(pk({}))", x_only_key))
2137 .unwrap_err();
2138 }
2139
2140 #[test]
2141 fn test_find_derivation_index_for_spk() {
2142 let secp = secp256k1_zkp::Secp256k1::verification_only();
2143 let descriptor = Descriptor::<_, NoExt>::from_str("eltr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)").unwrap();
2144 let script_at_0_1 = Script::from_hex_no_prefix(
2145 "5120c73ac1b7a518499b9642aed8cfa15d5401e5bd85ad760b937b69521c297722f0",
2146 )
2147 .unwrap();
2148 let expected_concrete = Descriptor::from_str(
2149 "eltr(0283dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145)",
2150 )
2151 .unwrap();
2152
2153 assert_eq!(
2154 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..1),
2155 Ok(None)
2156 );
2157 assert_eq!(
2158 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..2),
2159 Ok(Some((1, expected_concrete.clone())))
2160 );
2161 assert_eq!(
2162 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..10),
2163 Ok(Some((1, expected_concrete)))
2164 );
2165 }
2166
2167 #[test]
2168 fn display_alternate() {
2169 let bare = StdDescriptor::from_str(
2170 "elpk(020000000000000000000000000000000000000000000000000000000000000002)",
2171 )
2172 .unwrap();
2173 assert_eq!(
2174 format!("{}", bare),
2175 "elpk(020000000000000000000000000000000000000000000000000000000000000002)#vlpqwfjv",
2176 );
2177 assert_eq!(
2178 format!("{:#}", bare),
2179 "elpk(020000000000000000000000000000000000000000000000000000000000000002)",
2180 );
2181
2182 let pkh = StdDescriptor::from_str(
2183 "elpkh(020000000000000000000000000000000000000000000000000000000000000002)",
2184 )
2185 .unwrap();
2186 assert_eq!(
2187 format!("{}", pkh),
2188 "elpkh(020000000000000000000000000000000000000000000000000000000000000002)#jzq8e832",
2189 );
2190 assert_eq!(
2191 format!("{:#}", pkh),
2192 "elpkh(020000000000000000000000000000000000000000000000000000000000000002)",
2193 );
2194
2195 let wpkh = StdDescriptor::from_str(
2196 "elwpkh(020000000000000000000000000000000000000000000000000000000000000002)",
2197 )
2198 .unwrap();
2199 assert_eq!(
2200 format!("{}", wpkh),
2201 "elwpkh(020000000000000000000000000000000000000000000000000000000000000002)#vxhqdpz9",
2202 );
2203 assert_eq!(
2204 format!("{:#}", wpkh),
2205 "elwpkh(020000000000000000000000000000000000000000000000000000000000000002)",
2206 );
2207
2208 let shwpkh = StdDescriptor::from_str(
2209 "elsh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))",
2210 )
2211 .unwrap();
2212 assert_eq!(
2213 format!("{}", shwpkh),
2214 "elsh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))#h9ajn2ft",
2215 );
2216 assert_eq!(
2217 format!("{:#}", shwpkh),
2218 "elsh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))",
2219 );
2220
2221 let wsh = StdDescriptor::from_str("elwsh(1)").unwrap();
2222 assert_eq!(format!("{}", wsh), "elwsh(1)#s78w5gmj");
2223 assert_eq!(format!("{:#}", wsh), "elwsh(1)");
2224
2225 let sh = StdDescriptor::from_str("elsh(1)").unwrap();
2226 assert_eq!(format!("{}", sh), "elsh(1)#k4aqrx5p");
2227 assert_eq!(format!("{:#}", sh), "elsh(1)");
2228
2229 let shwsh = StdDescriptor::from_str("elsh(wsh(1))").unwrap();
2230 assert_eq!(format!("{}", shwsh), "elsh(wsh(1))#d05z4wjl");
2231 assert_eq!(format!("{:#}", shwsh), "elsh(wsh(1))");
2232
2233 let tr = StdDescriptor::from_str(
2234 "eltr(020000000000000000000000000000000000000000000000000000000000000002)",
2235 )
2236 .unwrap();
2237 assert_eq!(
2238 format!("{}", tr),
2239 "eltr(020000000000000000000000000000000000000000000000000000000000000002)#e874qu8z",
2240 );
2241 assert_eq!(
2242 format!("{:#}", tr),
2243 "eltr(020000000000000000000000000000000000000000000000000000000000000002)",
2244 );
2245 }
2246
2247 #[test]
2248 fn test_regression_29() {
2249 let _ = Descriptor::<String>::from_str("eltr(,thresh(1,spk_eq(,00)))");
2250 }
2251
2252 #[test]
2253 fn multipath_descriptors() {
2254 let desc = Descriptor::<DescriptorPublicKey, NoExt>::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<7';8h;20>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/<0;1;987>/*)))").unwrap();
2256 assert!(desc.is_multipath());
2257 assert!(!desc.multipath_length_mismatch());
2258 assert_eq!(desc.into_single_descriptors().unwrap(), vec![
2259 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/7'/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/0/*)))").unwrap(),
2260 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/8h/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/1/*)))").unwrap(),
2261 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/20/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/987/*)))").unwrap()
2262 ]);
2263
2264 let desc = Descriptor::<DescriptorPublicKey, NoExt>::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<0;1>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap();
2266 assert!(desc.is_multipath());
2267 assert!(!desc.multipath_length_mismatch());
2268 assert_eq!(desc.into_single_descriptors().unwrap(), vec![
2269 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/0/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap(),
2270 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/1/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap(),
2271 ]);
2272
2273 let notmulti_desc = Descriptor::<DescriptorPublicKey, NoExt>::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap();
2275 assert!(!notmulti_desc.is_multipath());
2276 assert!(!notmulti_desc.multipath_length_mismatch());
2277 assert_eq!(
2278 notmulti_desc.clone().into_single_descriptors().unwrap(),
2279 vec![notmulti_desc]
2280 );
2281
2282 Descriptor::<DescriptorPublicKey>::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<0;1>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/<0;1;2;3;4>/*)))").unwrap_err();
2284 Descriptor::<DescriptorPublicKey>::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<0;1;2;3>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/<0;1;2>/*)))").unwrap_err();
2285 }
2286}