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::WitnessVersion;
24use elements::hashes::{hash160, ripemd160, sha256};
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;
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>(
882 &self,
883 secp: &secp256k1_zkp::Secp256k1<C>,
884 index: u32,
885 ) -> Result<Descriptor<bitcoin::PublicKey, Ext>, ConversionError> {
886 self.at_derivation_index(index)?.derived_descriptor(secp)
887 }
888
889 pub fn parse_descriptor<C: secp256k1_zkp::Signing>(
894 secp: &secp256k1_zkp::Secp256k1<C>,
895 s: &str,
896 ) -> Result<(Descriptor<DescriptorPublicKey, Ext>, KeyMap), Error> {
897 fn parse_key<C: secp256k1::Signing>(
898 s: &str,
899 key_map: &mut KeyMap,
900 secp: &secp256k1::Secp256k1<C>,
901 ) -> Result<DescriptorPublicKey, Error> {
902 let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
903 Ok(sk) => (
904 sk.to_public(secp)
905 .map_err(|e| Error::Unexpected(e.to_string()))?,
906 Some(sk),
907 ),
908 Err(_) => (
909 DescriptorPublicKey::from_str(s)
910 .map_err(|e| Error::Unexpected(e.to_string()))?,
911 None,
912 ),
913 };
914
915 if let Some(secret_key) = secret_key {
916 key_map.insert(public_key.clone(), secret_key);
917 }
918
919 Ok(public_key)
920 }
921
922 let mut keymap_pk = KeyMapWrapper(HashMap::new(), secp);
923
924 struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
925
926 impl<'a, C: secp256k1::Signing> Translator<String, DescriptorPublicKey, Error>
927 for KeyMapWrapper<'a, C>
928 {
929 fn pk(&mut self, pk: &String) -> Result<DescriptorPublicKey, Error> {
930 parse_key(pk, &mut self.0, self.1)
931 }
932
933 fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Error> {
934 let hash =
935 sha256::Hash::from_str(sha256).map_err(|e| Error::Unexpected(e.to_string()))?;
936 Ok(hash)
937 }
938
939 fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, Error> {
940 let hash = hash256::Hash::from_str(hash256)
941 .map_err(|e| Error::Unexpected(e.to_string()))?;
942 Ok(hash)
943 }
944
945 fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, Error> {
946 let hash = ripemd160::Hash::from_str(ripemd160)
947 .map_err(|e| Error::Unexpected(e.to_string()))?;
948 Ok(hash)
949 }
950
951 fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, Error> {
952 let hash = hash160::Hash::from_str(hash160)
953 .map_err(|e| Error::Unexpected(e.to_string()))?;
954 Ok(hash)
955 }
956 }
957
958 let descriptor = Descriptor::<String, Ext>::from_str(s)?;
959 let descriptor = descriptor
960 .translate_pk(&mut keymap_pk)
961 .map_err(|e| Error::Unexpected(e.to_string()))?;
962
963 Ok((descriptor, keymap_pk.0))
964 }
965
966 pub fn to_string_with_secret(&self, key_map: &KeyMap) -> String {
968 struct KeyMapLookUp<'a>(&'a KeyMap);
969
970 impl<'a> Translator<DescriptorPublicKey, String, ()> for KeyMapLookUp<'a> {
971 fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, ()> {
972 key_to_string(pk, self.0)
973 }
974
975 fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
976 Ok(sha256.to_string())
977 }
978
979 fn hash256(&mut self, hash256: &hash256::Hash) -> Result<String, ()> {
980 Ok(hash256.to_string())
981 }
982
983 fn ripemd160(&mut self, ripemd160: &ripemd160::Hash) -> Result<String, ()> {
984 Ok(ripemd160.to_string())
985 }
986
987 fn hash160(&mut self, hash160: &hash160::Hash) -> Result<String, ()> {
988 Ok(hash160.to_string())
989 }
990 }
991
992 fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> Result<String, ()> {
993 Ok(match key_map.get(pk) {
994 Some(secret) => secret.to_string(),
995 None => pk.to_string(),
996 })
997 }
998
999 let descriptor = self
1000 .translate_pk(&mut KeyMapLookUp(key_map))
1001 .expect("Translation to string cannot fail");
1002
1003 descriptor.to_string()
1004 }
1005
1006 pub fn is_multipath(&self) -> bool {
1008 self.for_any_key(DescriptorPublicKey::is_multipath)
1009 }
1010
1011 pub fn into_single_descriptors(self) -> Result<Vec<Self>, Error> {
1016 let mut descriptors = Vec::new();
1018 if !self.for_any_key(|key| {
1020 if !descriptors.is_empty() {
1023 return true;
1024 }
1025
1026 match key {
1027 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
1028 DescriptorPublicKey::MultiXPub(xpub) => {
1029 for _ in 0..xpub.derivation_paths.paths().len() {
1030 descriptors.push(self.clone());
1031 }
1032 true
1033 }
1034 }
1035 }) {
1036 return Ok(vec![self]);
1038 }
1039 assert!(!descriptors.is_empty());
1040
1041 struct IndexChoser(usize);
1043 impl Translator<DescriptorPublicKey, DescriptorPublicKey, Error> for IndexChoser {
1044 fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DescriptorPublicKey, Error> {
1045 match pk {
1046 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => {
1047 Ok(pk.clone())
1048 }
1049 DescriptorPublicKey::MultiXPub(_) => pk
1050 .clone()
1051 .into_single_keys()
1052 .get(self.0)
1053 .cloned()
1054 .ok_or(Error::MultipathDescLenMismatch),
1055 }
1056 }
1057 translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, Error);
1058 }
1059
1060 for (i, desc) in descriptors.iter_mut().enumerate() {
1061 let mut index_choser = IndexChoser(i);
1062 *desc = desc.translate_pk(&mut index_choser)?;
1063 }
1064
1065 Ok(descriptors)
1066 }
1067}
1068
1069impl<Ext: Extension + ParseableExt> Descriptor<DescriptorPublicKey, Ext> {
1070 pub fn find_derivation_index_for_spk<C: secp256k1_zkp::Verification>(
1078 &self,
1079 secp: &secp256k1_zkp::Secp256k1<C>,
1080 script_pubkey: &Script,
1081 range: Range<u32>,
1082 ) -> Result<Option<(u32, Descriptor<bitcoin::PublicKey, Ext>)>, ConversionError> {
1083 let range = if self.has_wildcard() { range } else { 0..1 };
1084
1085 for i in range {
1086 let concrete = self.derived_descriptor(secp, i)?;
1087 if &concrete.script_pubkey() == script_pubkey {
1088 return Ok(Some((i, concrete)));
1089 }
1090 }
1091
1092 Ok(None)
1093 }
1094}
1095
1096impl<Pk: MiniscriptKey, Ext: Extension> Descriptor<Pk, Ext> {
1097 pub fn multipath_length_mismatch(&self) -> bool {
1101 #[derive(PartialEq)]
1103 enum MultipathLenChecker {
1104 SinglePath,
1105 MultipathLen(usize),
1106 LenMismatch,
1107 }
1108
1109 let mut checker = MultipathLenChecker::SinglePath;
1110 self.for_each_key(|key| {
1111 match key.num_der_paths() {
1112 0 | 1 => {}
1113 n => match checker {
1114 MultipathLenChecker::SinglePath => {
1115 checker = MultipathLenChecker::MultipathLen(n);
1116 }
1117 MultipathLenChecker::MultipathLen(len) => {
1118 if len != n {
1119 checker = MultipathLenChecker::LenMismatch;
1120 }
1121 }
1122 MultipathLenChecker::LenMismatch => {}
1123 },
1124 }
1125 true
1126 });
1127
1128 checker == MultipathLenChecker::LenMismatch
1129 }
1130}
1131
1132impl<Ext: Extension> Descriptor<DefiniteDescriptorKey, Ext> {
1133 pub fn derived_descriptor<C: secp256k1::Verification>(
1157 &self,
1158 secp: &secp256k1::Secp256k1<C>,
1159 ) -> Result<Descriptor<bitcoin::PublicKey, Ext>, ConversionError> {
1160 struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
1161
1162 impl<'a, C: secp256k1::Verification>
1163 Translator<DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError>
1164 for Derivator<'a, C>
1165 {
1166 fn pk(
1167 &mut self,
1168 pk: &DefiniteDescriptorKey,
1169 ) -> Result<bitcoin::PublicKey, ConversionError> {
1170 pk.derive_public_key(self.0)
1171 }
1172
1173 translate_hash_clone!(DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError);
1174 }
1175
1176 let derived = self.translate_pk(&mut Derivator(secp))?;
1177 Ok(derived)
1178 }
1179}
1180
1181impl_from_tree!(
1182 ;T; Extension,
1183 Descriptor<Pk, T>,
1184 fn from_tree(top: &expression::Tree) -> Result<Descriptor<Pk, T>, Error> {
1186 Ok(match (top.name, top.args.len() as u32) {
1187 ("elpkh", 1) => Descriptor::Pkh(Pkh::from_tree(top)?),
1188 ("elwpkh", 1) => Descriptor::Wpkh(Wpkh::from_tree(top)?),
1189 ("elsh", 1) => Descriptor::Sh(Sh::from_tree(top)?),
1190 ("elcovwsh", 2) => Descriptor::LegacyCSFSCov(LegacyCSFSCov::from_tree(top)?),
1191 ("elwsh", 1) => Descriptor::Wsh(Wsh::from_tree(top)?),
1192 ("eltr", _) => Descriptor::Tr(Tr::from_tree(top)?),
1193 _ => Descriptor::Bare(Bare::from_tree(top)?),
1194 })
1195 }
1196);
1197
1198impl_from_str!(
1199 ;T; Extension,
1200 Descriptor<Pk, T>,
1201 type Err = Error;,
1202 fn from_str(s: &str) -> Result<Descriptor<Pk, T>, Error> {
1203 if !s.starts_with(ELMTS_STR) {
1204 return Err(Error::BadDescriptor(String::from(
1205 "Not an Elements Descriptor",
1206 )));
1207 }
1208 let desc = if s.starts_with(&format!("{}tr", ELMTS_STR)) {
1212 match Tr::<Pk, NoExt>::from_str(s) {
1214 Ok(tr) => Descriptor::Tr(tr),
1215 Err(_) => {
1216 let tr = Tr::<Pk, T>::from_str(s)?;
1218 Descriptor::TrExt(tr)
1219 }
1220 }
1221 } else {
1222 let desc_str = verify_checksum(s)?;
1223 let top = expression::Tree::from_str(desc_str)?;
1224 expression::FromTree::from_tree(&top)?
1225 };
1226
1227 if desc.multipath_length_mismatch() {
1228 return Err(Error::MultipathDescLenMismatch);
1229 }
1230
1231 Ok(desc)
1232 }
1233);
1234
1235impl<Pk: MiniscriptKey, T: Extension> fmt::Debug for Descriptor<Pk, T> {
1236 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1237 match *self {
1238 Descriptor::Bare(ref sub) => fmt::Debug::fmt(sub, f),
1239 Descriptor::Pkh(ref pkh) => fmt::Debug::fmt(pkh, f),
1240 Descriptor::Wpkh(ref wpkh) => fmt::Debug::fmt(wpkh, f),
1241 Descriptor::Sh(ref sub) => fmt::Debug::fmt(sub, f),
1242 Descriptor::Wsh(ref sub) => fmt::Debug::fmt(sub, f),
1243 Descriptor::Tr(ref tr) => fmt::Debug::fmt(tr, f),
1244 Descriptor::TrExt(ref tr) => fmt::Debug::fmt(tr, f),
1245 Descriptor::LegacyCSFSCov(ref cov) => fmt::Debug::fmt(cov, f),
1246 }
1247 }
1248}
1249
1250impl<Pk: MiniscriptKey, T: Extension> fmt::Display for Descriptor<Pk, T> {
1251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1252 match *self {
1253 Descriptor::Bare(ref sub) => fmt::Display::fmt(sub, f),
1254 Descriptor::Pkh(ref pkh) => fmt::Display::fmt(pkh, f),
1255 Descriptor::Wpkh(ref wpkh) => fmt::Display::fmt(wpkh, f),
1256 Descriptor::Sh(ref sub) => fmt::Display::fmt(sub, f),
1257 Descriptor::Wsh(ref sub) => fmt::Display::fmt(sub, f),
1258 Descriptor::Tr(ref tr) => fmt::Display::fmt(tr, f),
1259 Descriptor::TrExt(ref tr) => fmt::Display::fmt(tr, f),
1260 Descriptor::LegacyCSFSCov(ref cov) => fmt::Display::fmt(cov, f),
1261 }
1262 }
1263}
1264
1265serde_string_impl_pk!(Descriptor, "a script descriptor", T; Extension);
1266
1267#[cfg(test)]
1268mod tests {
1269 use std::collections::HashMap;
1270 use std::str::FromStr;
1271
1272 use bitcoin;
1273 use bitcoin::{bip32, PublicKey};
1274 use elements::hashes::{hash160, sha256};
1275 use elements::hex::{FromHex, ToHex};
1276 use elements::opcodes::all::{OP_CLTV, OP_CSV};
1277 use elements::script::Instruction;
1278 use elements::{opcodes, script, Sequence};
1279
1280 use super::checksum::desc_checksum;
1281 use super::tr::Tr;
1282 use super::*;
1283 use crate::descriptor::key::Wildcard;
1284 use crate::descriptor::{DescriptorPublicKey, DescriptorXKey};
1285 use crate::miniscript::satisfy::ElementsSig;
1286 #[cfg(feature = "compiler")]
1287 use crate::policy;
1288 use crate::{hex_script, Descriptor, Error, Miniscript, NoExt, Satisfier};
1289
1290 type StdDescriptor = Descriptor<PublicKey, CovenantExt<CovExtArgs>>;
1291 const TEST_PK: &str =
1292 "elpk(020000000000000000000000000000000000000000000000000000000000000002)";
1293
1294 fn roundtrip_descriptor(s: &str) {
1295 let desc = Descriptor::<String>::from_str(s).unwrap();
1296 let output = desc.to_string();
1297 let normalize_aliases = s.replace("c:pk_k(", "pk(").replace("c:pk_h(", "pkh(");
1298 assert_eq!(
1299 format!(
1300 "{}#{}",
1301 &normalize_aliases,
1302 desc_checksum(&normalize_aliases).unwrap()
1303 ),
1304 output
1305 );
1306 }
1307
1308 fn elements_txin(script_sig: Script, witness: Vec<Vec<u8>>) -> elements::TxIn {
1310 let txin_witness = elements::TxInWitness {
1311 script_witness: witness,
1312 ..Default::default()
1313 };
1314 elements::TxIn {
1315 previous_output: elements::OutPoint::default(),
1316 script_sig,
1317 sequence: Sequence::from_height(100),
1318 is_pegin: false,
1319 asset_issuance: elements::AssetIssuance::default(),
1320 witness: txin_witness,
1321 }
1322 }
1323
1324 #[test]
1325 fn desc_rtt_tests() {
1326 roundtrip_descriptor("elc:pk_k()");
1327 roundtrip_descriptor("elwsh(pk())");
1328 roundtrip_descriptor("elwsh(c:pk_k())");
1329 roundtrip_descriptor("elc:pk_h()");
1330 }
1331 #[test]
1332 fn parse_descriptor() {
1333 StdDescriptor::from_str("(").unwrap_err();
1334 StdDescriptor::from_str("(x()").unwrap_err();
1335 StdDescriptor::from_str("(\u{7f}()3").unwrap_err();
1336 StdDescriptor::from_str("pk()").unwrap_err();
1337 StdDescriptor::from_str("nl:0").unwrap_err(); let compressed_pk = "02be5645686309c6e6736dbd93940707cc9143d3cf29f1b877ff340e2cb2d259cf";
1339 assert_eq!(
1340 StdDescriptor::from_str("elsh(sortedmulti)")
1341 .unwrap_err()
1342 .to_string(),
1343 "unexpected «no arguments given for sortedmulti»"
1344 ); assert_eq!(
1346 StdDescriptor::from_str(&format!("elsh(sortedmulti(2,{}))", compressed_pk))
1347 .unwrap_err()
1348 .to_string(),
1349 "unexpected «higher threshold than there were keys in sortedmulti»"
1350 ); StdDescriptor::from_str(TEST_PK).unwrap();
1353 StdDescriptor::from_str("slip77").unwrap_err();
1355
1356 let uncompressed_pk =
1357 "0414fc03b8df87cd7b872996810db8458d61da8448e531569c8517b469a119d267be5645686309c6e6736dbd93940707cc9143d3cf29f1b877ff340e2cb2d259cf";
1358
1359 StdDescriptor::from_str(&format!("elpk({})", uncompressed_pk)).unwrap();
1361 StdDescriptor::from_str(&format!("elpkh({})", uncompressed_pk)).unwrap();
1362 StdDescriptor::from_str(&format!("elsh(pk({}))", uncompressed_pk)).unwrap();
1363 StdDescriptor::from_str(&format!("elwpkh({})", uncompressed_pk)).unwrap_err();
1364 StdDescriptor::from_str(&format!("elsh(wpkh({}))", uncompressed_pk)).unwrap_err();
1365 StdDescriptor::from_str(&format!("elwsh(pk{})", uncompressed_pk)).unwrap_err();
1366 StdDescriptor::from_str(&format!("elsh(wsh(pk{}))", uncompressed_pk)).unwrap_err();
1367 StdDescriptor::from_str(&format!(
1368 "elor_i(pk({}),pk({}))",
1369 uncompressed_pk, uncompressed_pk
1370 ))
1371 .unwrap_err();
1372 }
1373
1374 #[test]
1375 pub fn script_pubkey() {
1376 let bare = StdDescriptor::from_str(
1377 "elmulti(1,020000000000000000000000000000000000000000000000000000000000000002)",
1378 )
1379 .unwrap();
1380 assert_eq!(
1381 bare.script_pubkey(),
1382 hex_script(
1383 "512102000000000000000000000000000000000000000000000000000000000000000251ae"
1384 )
1385 );
1386 assert_eq!(
1387 bare.address(&elements::AddressParams::ELEMENTS)
1388 .unwrap_err()
1389 .to_string(),
1390 "Bare descriptors don't have address"
1391 );
1392
1393 let pk = StdDescriptor::from_str(TEST_PK).unwrap();
1394 assert_eq!(
1395 pk.script_pubkey(),
1396 elements::Script::from(vec![
1397 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1399 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xac,
1400 ])
1401 );
1402
1403 let pkh = StdDescriptor::from_str(
1404 "elpkh(\
1405 020000000000000000000000000000000000000000000000000000000000000002\
1406 )",
1407 )
1408 .unwrap();
1409 assert_eq!(
1410 pkh.script_pubkey(),
1411 script::Builder::new()
1412 .push_opcode(opcodes::all::OP_DUP)
1413 .push_opcode(opcodes::all::OP_HASH160)
1414 .push_slice(
1415 &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap()
1416 [..]
1417 )
1418 .push_opcode(opcodes::all::OP_EQUALVERIFY)
1419 .push_opcode(opcodes::all::OP_CHECKSIG)
1420 .into_script()
1421 );
1422 assert_eq!(
1423 pkh.address(&elements::AddressParams::ELEMENTS,)
1424 .unwrap()
1425 .to_string(),
1426 "2dmYXpSu8YP6aLcJYhHfB1C19mdzSx2GPB9"
1427 );
1428
1429 let wpkh = StdDescriptor::from_str(
1430 "elwpkh(\
1431 020000000000000000000000000000000000000000000000000000000000000002\
1432 )",
1433 )
1434 .unwrap();
1435 assert_eq!(
1436 wpkh.script_pubkey(),
1437 script::Builder::new()
1438 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1439 .push_slice(
1440 &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap()
1441 [..]
1442 )
1443 .into_script()
1444 );
1445 assert_eq!(
1446 wpkh.address(&elements::AddressParams::ELEMENTS,)
1447 .unwrap()
1448 .to_string(),
1449 "ert1qsn57m9drscflq5nl76z6ny52hck5w4x57m69k3"
1450 );
1451
1452 let shwpkh = StdDescriptor::from_str(
1453 "elsh(wpkh(\
1454 020000000000000000000000000000000000000000000000000000000000000002\
1455 ))",
1456 )
1457 .unwrap();
1458 assert_eq!(
1459 shwpkh.script_pubkey(),
1460 script::Builder::new()
1461 .push_opcode(opcodes::all::OP_HASH160)
1462 .push_slice(
1463 &hash160::Hash::from_str("f1c3b9a431134cb90a500ec06e0067cfa9b8bba7",).unwrap()
1464 [..]
1465 )
1466 .push_opcode(opcodes::all::OP_EQUAL)
1467 .into_script()
1468 );
1469 assert_eq!(
1470 shwpkh
1471 .address(&elements::AddressParams::ELEMENTS,)
1472 .unwrap()
1473 .to_string(),
1474 "XZPaAbg6M83Fq5NqvbEGZ5kwy9RKSTke2s"
1475 );
1476
1477 let sh = StdDescriptor::from_str(
1478 "elsh(c:pk_k(\
1479 020000000000000000000000000000000000000000000000000000000000000002\
1480 ))",
1481 )
1482 .unwrap();
1483 assert_eq!(
1484 sh.script_pubkey(),
1485 script::Builder::new()
1486 .push_opcode(opcodes::all::OP_HASH160)
1487 .push_slice(
1488 &hash160::Hash::from_str("aa5282151694d3f2f32ace7d00ad38f927a33ac8",).unwrap()
1489 [..]
1490 )
1491 .push_opcode(opcodes::all::OP_EQUAL)
1492 .into_script()
1493 );
1494 assert_eq!(
1495 sh.address(&elements::AddressParams::ELEMENTS,)
1496 .unwrap()
1497 .to_string(),
1498 "XSspZXDJu2XVh8AKC7qF3L7x79Qy67JhQb"
1499 );
1500
1501 let wsh = StdDescriptor::from_str(
1502 "elwsh(c:pk_k(\
1503 020000000000000000000000000000000000000000000000000000000000000002\
1504 ))",
1505 )
1506 .unwrap();
1507 assert_eq!(
1508 wsh.script_pubkey(),
1509 script::Builder::new()
1510 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1511 .push_slice(
1512 &sha256::Hash::from_str(
1513 "\
1514 f9379edc8983152dc781747830075bd5\
1515 3896e4b0ce5bff73777fd77d124ba085\
1516 "
1517 )
1518 .unwrap()[..]
1519 )
1520 .into_script()
1521 );
1522 assert_eq!(
1523 wsh.address(&elements::AddressParams::ELEMENTS,)
1524 .unwrap()
1525 .to_string(),
1526 "ert1qlymeahyfsv2jm3upw3urqp6m65ufde9seedl7umh0lth6yjt5zzsan9u2t"
1527 );
1528
1529 let shwsh = StdDescriptor::from_str(
1530 "elsh(wsh(c:pk_k(\
1531 020000000000000000000000000000000000000000000000000000000000000002\
1532 )))",
1533 )
1534 .unwrap();
1535 assert_eq!(
1536 shwsh.script_pubkey(),
1537 script::Builder::new()
1538 .push_opcode(opcodes::all::OP_HASH160)
1539 .push_slice(
1540 &hash160::Hash::from_str("4bec5d7feeed99e1d0a23fe32a4afe126a7ff07e",).unwrap()
1541 [..]
1542 )
1543 .push_opcode(opcodes::all::OP_EQUAL)
1544 .into_script()
1545 );
1546 assert_eq!(
1547 shwsh
1548 .address(&elements::AddressParams::ELEMENTS,)
1549 .unwrap()
1550 .to_string(),
1551 "XJGggUb965TvGF2VCxp9EQGmZTxMeDjwQQ"
1552 );
1553 }
1554
1555 #[test]
1556 fn satisfy() {
1557 let secp = secp256k1_zkp::Secp256k1::new();
1558 let sk =
1559 secp256k1_zkp::SecretKey::from_slice(&b"sally was a secret key, she said"[..]).unwrap();
1560 let pk = bitcoin::PublicKey {
1561 inner: secp256k1_zkp::PublicKey::from_secret_key(&secp, &sk),
1562 compressed: true,
1563 };
1564 let msg =
1565 secp256k1_zkp::Message::from_digest_slice(&b"michael was a message, amusingly"[..])
1566 .expect("32 bytes");
1567 let sig = secp.sign_ecdsa(&msg, &sk);
1568 let mut sigser = sig.serialize_der().to_vec();
1569 sigser.push(0x01); struct SimpleSat {
1572 sig: secp256k1_zkp::ecdsa::Signature,
1573 pk: bitcoin::PublicKey,
1574 }
1575
1576 impl Satisfier<bitcoin::PublicKey> for SimpleSat {
1577 fn lookup_ecdsa_sig(&self, pk: &bitcoin::PublicKey) -> Option<ElementsSig> {
1578 if *pk == self.pk {
1579 Some((self.sig, elements::EcdsaSighashType::All))
1580 } else {
1581 None
1582 }
1583 }
1584 }
1585
1586 let satisfier = SimpleSat { sig, pk };
1587 let ms = ms_str!("c:pk_k({})", pk);
1588
1589 let mut txin = elements::TxIn {
1590 previous_output: elements::OutPoint::default(),
1591 script_sig: Script::new(),
1592 sequence: Sequence::from_height(100),
1593 is_pegin: false,
1594 asset_issuance: elements::AssetIssuance::default(),
1595 witness: elements::TxInWitness::default(),
1596 };
1597 let bare: Descriptor<_, NoExt> = Descriptor::new_bare(ms).unwrap();
1598
1599 bare.satisfy(&mut txin, &satisfier).expect("satisfaction");
1600 assert_eq!(
1601 txin,
1602 elements_txin(
1603 script::Builder::new().push_slice(&sigser[..]).into_script(),
1604 vec![]
1605 ),
1606 );
1607 assert_eq!(bare.unsigned_script_sig(), elements::Script::new());
1608
1609 let pkh: Descriptor<_, NoExt> = Descriptor::new_pkh(pk);
1610 pkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1611 assert_eq!(
1612 txin,
1613 elements_txin(
1614 script::Builder::new()
1615 .push_slice(&sigser[..])
1616 .push_key(&pk)
1617 .into_script(),
1618 vec![]
1619 )
1620 );
1621 assert_eq!(pkh.unsigned_script_sig(), elements::Script::new());
1622
1623 let wpkh: Descriptor<_, NoExt> = Descriptor::new_wpkh(pk).unwrap();
1624 wpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1625 assert_eq!(
1626 txin,
1627 elements_txin(Script::new(), vec![sigser.clone(), pk.to_bytes(),])
1628 );
1629 assert_eq!(wpkh.unsigned_script_sig(), elements::Script::new());
1630
1631 let shwpkh: Descriptor<_, NoExt> = Descriptor::new_sh_wpkh(pk).unwrap();
1632 shwpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1633 let redeem_script = script::Builder::new()
1634 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1635 .push_slice(
1636 &hash160::Hash::from_str("d1b2a1faf62e73460af885c687dee3b7189cd8ab").unwrap()[..],
1637 )
1638 .into_script();
1639 let expected_ssig = script::Builder::new()
1640 .push_slice(&redeem_script[..])
1641 .into_script();
1642 assert_eq!(
1643 txin,
1644 elements_txin(expected_ssig.clone(), vec![sigser.clone(), pk.to_bytes()])
1645 );
1646 assert_eq!(shwpkh.unsigned_script_sig(), expected_ssig);
1647
1648 let ms = ms_str!("c:pk_k({})", pk);
1649 let sh: Descriptor<_, NoExt> = Descriptor::new_sh(ms.clone()).unwrap();
1650 sh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1651 let expected_ssig = script::Builder::new()
1652 .push_slice(&sigser[..])
1653 .push_slice(&ms.encode()[..])
1654 .into_script();
1655 assert_eq!(txin, elements_txin(expected_ssig, vec![]));
1656 assert_eq!(sh.unsigned_script_sig(), Script::new());
1657
1658 let ms = ms_str!("c:pk_k({})", pk);
1659
1660 let wsh: Descriptor<_, NoExt> = Descriptor::new_wsh(ms.clone()).unwrap();
1661 wsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1662 assert_eq!(
1663 txin,
1664 elements_txin(
1665 Script::new(),
1666 vec![sigser.clone(), ms.encode().into_bytes()]
1667 )
1668 );
1669 assert_eq!(wsh.unsigned_script_sig(), Script::new());
1670
1671 let shwsh: Descriptor<_, NoExt> = Descriptor::new_sh_wsh(ms.clone()).unwrap();
1672 shwsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1673 let expected_ssig = script::Builder::new()
1674 .push_slice(&ms.encode().to_v0_p2wsh()[..])
1675 .into_script();
1676 assert_eq!(
1677 txin,
1678 elements_txin(
1679 expected_ssig.clone(),
1680 vec![sigser.clone(), ms.encode().into_bytes(),]
1681 )
1682 );
1683 assert_eq!(shwsh.unsigned_script_sig(), expected_ssig);
1684 }
1685
1686 #[test]
1687 fn after_is_cltv() {
1688 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("elwsh(after(1000))").unwrap();
1689 let script = descriptor.explicit_script().unwrap();
1690
1691 let actual_instructions: Vec<_> = script.instructions().collect();
1692 let check = actual_instructions.last().unwrap();
1693
1694 assert_eq!(check, &Ok(Instruction::Op(OP_CLTV)))
1695 }
1696
1697 #[test]
1698 fn older_is_csv() {
1699 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("elwsh(older(1000))").unwrap();
1700 let script = descriptor.explicit_script().unwrap();
1701
1702 let actual_instructions: Vec<_> = script.instructions().collect();
1703 let check = actual_instructions.last().unwrap();
1704
1705 assert_eq!(check, &Ok(Instruction::Op(OP_CSV)))
1706 }
1707
1708 #[test]
1709 fn tr_roundtrip_key() {
1710 let script = Tr::<String>::from_str("eltr()").unwrap().to_string();
1711 assert_eq!(script, format!("eltr()#sux3r82e"))
1712 }
1713
1714 #[test]
1715 fn tr_roundtrip_script() {
1716 let descriptor = Tr::<String>::from_str("eltr(,{pk(),pk()})")
1717 .unwrap()
1718 .to_string();
1719
1720 assert_eq!(descriptor, "eltr(,{pk(),pk()})#lxgcxh02");
1721
1722 let descriptor = Descriptor::<String>::from_str("eltr(A,{pk(B),pk(C)})")
1723 .unwrap()
1724 .to_string();
1725 assert_eq!(descriptor, "eltr(A,{pk(B),pk(C)})#cx98s50f");
1726 }
1727
1728 #[test]
1729 fn tr_roundtrip_tree() {
1730 let p1 = "020000000000000000000000000000000000000000000000000000000000000001";
1731 let p2 = "020000000000000000000000000000000000000000000000000000000000000002";
1732 let p3 = "020000000000000000000000000000000000000000000000000000000000000003";
1733 let p4 = "020000000000000000000000000000000000000000000000000000000000000004";
1734 let p5 = "03f8551772d66557da28c1de858124f365a8eb30ce6ad79c10e0f4c546d0ab0f82";
1735 let descriptor = Tr::<PublicKey>::from_str(&format!(
1736 "eltr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})",
1737 p1, p2, p3, p4, p5
1738 ))
1739 .unwrap()
1740 .to_string();
1741
1742 assert_eq!(
1744 descriptor,
1745 format!(
1746 "eltr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})#y9kzzx3w",
1747 p1, p2, p3, p4, p5
1748 )
1749 )
1750 }
1751
1752 #[test]
1753 fn tr_script_pubkey() {
1754 let key = Descriptor::<bitcoin::PublicKey>::from_str(
1755 "eltr(02e20e746af365e86647826397ba1c0e0d5cb685752976fe2f326ab76bdc4d6ee9)",
1756 )
1757 .unwrap();
1758 assert_eq!(
1759 key.script_pubkey().to_hex(),
1760 "51203f48e7c6203a75722733e3d9d06638da38d946066159c64684caf1622b2b0e33"
1761 )
1762 }
1763
1764 #[test]
1765 fn roundtrip_tests() {
1766 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("elmulti");
1767 assert_eq!(
1768 descriptor.unwrap_err().to_string(),
1769 "unexpected «no arguments given»"
1770 )
1771 }
1772
1773 #[test]
1774 fn empty_thresh() {
1775 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("elthresh");
1776 assert_eq!(
1777 descriptor.unwrap_err().to_string(),
1778 "unexpected «no arguments given»"
1779 )
1780 }
1781
1782 #[test]
1783 fn witness_stack_for_andv_is_arranged_in_correct_order() {
1784 let a = bitcoin::PublicKey::from_str(
1786 "02937402303919b3a2ee5edd5009f4236f069bf75667b8e6ecf8e5464e20116a0e",
1787 )
1788 .unwrap();
1789 let sig_a = secp256k1_zkp::ecdsa::Signature::from_str("3045022100a7acc3719e9559a59d60d7b2837f9842df30e7edcd754e63227e6168cec72c5d022066c2feba4671c3d99ea75d9976b4da6c86968dbf3bab47b1061e7a1966b1778c").unwrap();
1790
1791 let b = bitcoin::PublicKey::from_str(
1792 "02eb64639a17f7334bb5a1a3aad857d6fec65faef439db3de72f85c88bc2906ad3",
1793 )
1794 .unwrap();
1795 let sig_b = secp256k1_zkp::ecdsa::Signature::from_str("3044022075b7b65a7e6cd386132c5883c9db15f9a849a0f32bc680e9986398879a57c276022056d94d12255a4424f51c700ac75122cb354895c9f2f88f0cbb47ba05c9c589ba").unwrap();
1796
1797 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str(&format!(
1798 "elwsh(and_v(v:pk({A}),pk({B})))",
1799 A = a,
1800 B = b
1801 ))
1802 .unwrap();
1803
1804 let mut txin = elements_txin(Script::new(), vec![]);
1805 let satisfier = {
1806 let mut satisfier = HashMap::with_capacity(2);
1807
1808 satisfier.insert(a, (sig_a, ::elements::EcdsaSighashType::All));
1809 satisfier.insert(b, (sig_b, ::elements::EcdsaSighashType::All));
1810
1811 satisfier
1812 };
1813
1814 descriptor.satisfy(&mut txin, &satisfier).unwrap();
1816
1817 let witness0 = &txin.witness.script_witness[0];
1819 let witness1 = &txin.witness.script_witness[1];
1820
1821 let sig0 =
1822 secp256k1_zkp::ecdsa::Signature::from_der(&witness0[..witness0.len() - 1]).unwrap();
1823 let sig1 =
1824 secp256k1_zkp::ecdsa::Signature::from_der(&witness1[..witness1.len() - 1]).unwrap();
1825
1826 assert_eq!(sig1, sig_a);
1831 assert_eq!(sig0, sig_b);
1832 }
1833
1834 #[test]
1835 fn test_scriptcode() {
1836 let descriptor = Descriptor::<PublicKey>::from_str(
1838 "elwpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
1839 )
1840 .unwrap();
1841 assert_eq!(
1842 *descriptor.script_code().unwrap().as_bytes(),
1843 Vec::<u8>::from_hex("76a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac").unwrap()[..]
1844 );
1845
1846 let descriptor = Descriptor::<PublicKey>::from_str(
1848 "elsh(wpkh(03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873))",
1849 )
1850 .unwrap();
1851 assert_eq!(
1852 *descriptor.script_code().unwrap().as_bytes(),
1853 Vec::<u8>::from_hex("76a91479091972186c449eb1ded22b78e40d009bdf008988ac").unwrap()[..]
1854 );
1855
1856 let descriptor = Descriptor::<PublicKey>::from_str(
1858 "elwsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626))",
1859 )
1860 .unwrap();
1861 assert_eq!(
1862 *descriptor
1863 .script_code().unwrap()
1864 .as_bytes(),
1865 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae").unwrap()[..]
1866 );
1867
1868 let descriptor = Descriptor::<PublicKey>::from_str("elsh(wsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626)))").unwrap();
1870 assert_eq!(
1871 *descriptor
1872 .script_code().unwrap()
1873 .as_bytes(),
1874 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae")
1875 .unwrap()[..]
1876 );
1877 }
1878
1879 #[test]
1880 fn parse_descriptor_key() {
1881 let key = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*";
1883 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1884 origin: Some((
1885 bip32::Fingerprint::from([0x78, 0x41, 0x2e, 0x3a]),
1886 (&[
1887 bip32::ChildNumber::from_hardened_idx(44).unwrap(),
1888 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1889 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1890 ][..])
1891 .into(),
1892 )),
1893 xkey: bip32::Xpub::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1894 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1895 wildcard: Wildcard::Unhardened,
1896 });
1897 assert_eq!(expected, key.parse().unwrap());
1898 assert_eq!(format!("{}", expected), key);
1899
1900 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1";
1902 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1903 origin: None,
1904 xkey: bip32::Xpub::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1905 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1906 wildcard: Wildcard::None,
1907 });
1908 assert_eq!(expected, key.parse().unwrap());
1909 assert_eq!(format!("{}", expected), key);
1910
1911 let key = "tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed/1";
1913 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1914 origin: None,
1915 xkey: bip32::Xpub::from_str("tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed").unwrap(),
1916 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1917 wildcard: Wildcard::None,
1918 });
1919 assert_eq!(expected, key.parse().unwrap());
1920 assert_eq!(format!("{}", expected), key);
1921
1922 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
1924 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1925 origin: None,
1926 xkey: bip32::Xpub::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1927 derivation_path: bip32::DerivationPath::from(&[][..]),
1928 wildcard: Wildcard::None,
1929 });
1930 assert_eq!(expected, key.parse().unwrap());
1931 assert_eq!(format!("{}", expected), key);
1932
1933 let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
1935 let expected = DescriptorPublicKey::Single(SinglePub {
1936 key: SinglePubKey::FullKey(
1937 bitcoin::PublicKey::from_str(
1938 "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8",
1939 )
1940 .unwrap(),
1941 ),
1942 origin: None,
1943 });
1944 assert_eq!(expected, key.parse().unwrap());
1945 assert_eq!(format!("{}", expected), key);
1946
1947 let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a";
1949 let expected = DescriptorPublicKey::Single(SinglePub {
1950 key: SinglePubKey::FullKey(bitcoin::PublicKey::from_str(
1951 "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a",
1952 )
1953 .unwrap()),
1954 origin: None,
1955 });
1956 assert_eq!(expected, key.parse().unwrap());
1957 assert_eq!(format!("{}", expected), key);
1958
1959 let desc =
1961 "[78412e3a/0'/42/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8";
1962 let expected = DescriptorPublicKey::Single(SinglePub {
1963 key: SinglePubKey::FullKey(
1964 bitcoin::PublicKey::from_str(
1965 "0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8",
1966 )
1967 .unwrap(),
1968 ),
1969 origin: Some((
1970 bip32::Fingerprint::from([0x78, 0x41, 0x2e, 0x3a]),
1971 (&[
1972 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1973 bip32::ChildNumber::from_normal_idx(42).unwrap(),
1974 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1975 ][..])
1976 .into(),
1977 )),
1978 });
1979 assert_eq!(expected, desc.parse().expect("Parsing desc"));
1980 assert_eq!(format!("{}", expected), desc);
1981 }
1982
1983 #[test]
1984 fn test_sortedmulti() {
1985 fn _test_sortedmulti(raw_desc_one: &str, raw_desc_two: &str, raw_addr_expected: &str) {
1986 let secp_ctx = secp256k1_zkp::Secp256k1::verification_only();
1987 let index = 5;
1988
1989 let desc_one = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_one).unwrap();
1991 let desc_two = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_two).unwrap();
1992
1993 assert_eq!(desc_one.to_string(), raw_desc_one);
1995 assert_eq!(desc_two.to_string(), raw_desc_two);
1996
1997 let addr_one = desc_one
1999 .at_derivation_index(index)
2000 .unwrap()
2001 .derived_descriptor(&secp_ctx)
2002 .unwrap()
2003 .address(&elements::AddressParams::ELEMENTS)
2004 .unwrap();
2005 let addr_two = desc_two
2006 .at_derivation_index(index)
2007 .unwrap()
2008 .derived_descriptor(&secp_ctx)
2009 .unwrap()
2010 .address(&elements::AddressParams::ELEMENTS)
2011 .unwrap();
2012 let addr_expected = elements::Address::from_str(raw_addr_expected).unwrap();
2013 assert_eq!(addr_one, addr_expected);
2014 assert_eq!(addr_two, addr_expected);
2015 }
2016
2017 _test_sortedmulti(
2019 "elsh(sortedmulti(1,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352))#tse3qz98",
2020 "elsh(sortedmulti(1,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))#ptnf05qc",
2021 "XUDXJZnP2GXsKRKdxSLKzJM1iZ4gbbyrGh",
2022 );
2023
2024 _test_sortedmulti(
2026 "elwsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH))#a8h2v83d",
2027 "elwsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB))#qfcn7ujk",
2028 "ert1qpq2cfgz5lktxzr5zqv7nrzz46hsvq3492ump9pz8rzcl8wqtwqcs2yqnuv",
2029 );
2030
2031 _test_sortedmulti(
2033 "elsh(wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*)))#l7qy253t",
2034 "elsh(wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*)))#0gpee5cl",
2035 "XBkDY63XnRTz6BbwzJi3ifGhBwLTomEzkq",
2036 );
2037 }
2038
2039 #[test]
2040 fn test_parse_descriptor() {
2041 let secp = &secp256k1_zkp::Secp256k1::signing_only();
2042 let (descriptor, key_map) = Descriptor::<_, NoExt>::parse_descriptor(secp, "elwpkh(tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/44'/0'/0'/0/*)").unwrap();
2043 assert_eq!(descriptor.to_string(), "elwpkh([2cbe2a6d/44'/0'/0']tpubDCvNhURocXGZsLNqWcqD3syHTqPXrMSTwi8feKVwAcpi29oYKsDD3Vex7x2TDneKMVN23RbLprfxB69v94iYqdaYHsVz3kPR37NQXeqouVz/0/*)#pznhhta9");
2044 assert_eq!(key_map.len(), 1);
2045
2046 macro_rules! check_invalid_checksum {
2048 ($secp: ident,$($desc: expr),*) => {
2049 $(
2050 match Descriptor::<_, NoExt>::parse_descriptor($secp, $desc) {
2051 Err(Error::BadDescriptor(_)) => {},
2052 Err(e) => panic!("Expected bad checksum for {}, got '{}'", $desc, e),
2053 _ => panic!("Invalid checksum treated as valid: {}", $desc),
2054 };
2055 )*
2056 };
2057 }
2058 check_invalid_checksum!(secp,
2059 "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#",
2060 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#",
2061 "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf",
2062 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq",
2063 "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf",
2064 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5",
2065 "elsh(multi(3,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy",
2066 "elsh(multi(3,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t",
2067 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjq09x4t",
2068 "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))##ggssrxfy",
2069 "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))##tjq09x4t"
2070 );
2071
2072 Descriptor::<_, NoExt>::parse_descriptor(secp, "elsh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#9s2ngs7u").expect("Valid descriptor with checksum");
2073 Descriptor::<_, NoExt>::parse_descriptor(secp, "elsh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#uklept69").expect("Valid descriptor with checksum");
2074 }
2075
2076 #[test]
2077 #[cfg(feature = "compiler")]
2078 fn parse_and_derive() {
2079 let descriptor_str = "thresh(2,\
2080pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*),\
2081pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
2082pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
2083 let policy: policy::concrete::Policy<DescriptorPublicKey> = descriptor_str.parse().unwrap();
2084 let descriptor = Descriptor::<_, NoExt>::new_sh(policy.compile().unwrap()).unwrap();
2085 let definite_descriptor = descriptor.at_derivation_index(42).unwrap();
2086
2087 let res_descriptor_str = "thresh(2,\
2088pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42),\
2089pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
2090pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
2091 let res_policy: policy::concrete::Policy<DescriptorPublicKey> =
2092 res_descriptor_str.parse().unwrap();
2093 let res_descriptor =
2094 Descriptor::<DescriptorPublicKey, NoExt>::new_sh(res_policy.compile().unwrap())
2095 .unwrap();
2096
2097 assert_eq!(res_descriptor.to_string(), definite_descriptor.to_string());
2098 }
2099
2100 #[test]
2101 fn parse_with_secrets() {
2102 let secp = &secp256k1_zkp::Secp256k1::signing_only();
2103 let descriptor_str = "elwpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)#xldrpn5u";
2104 let (descriptor, keymap) =
2105 Descriptor::<DescriptorPublicKey>::parse_descriptor(secp, descriptor_str).unwrap();
2106
2107 let expected = "elwpkh([a12b02f4/44'/0'/0']xpub6BzhLAQUDcBUfHRQHZxDF2AbcJqp4Kaeq6bzJpXrjrWuK26ymTFwkEFbxPra2bJ7yeZKbDjfDeFwxe93JMqpo5SsPJH6dZdvV9kMzJkAZ69/0/*)#20ufqv7z";
2108 assert_eq!(expected, descriptor.to_string());
2109 assert_eq!(keymap.len(), 1);
2110
2111 assert_eq!(descriptor_str, descriptor.to_string_with_secret(&keymap));
2113 }
2114
2115 #[test]
2116 fn checksum_for_nested_sh() {
2117 let descriptor_str = "elsh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))";
2118 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
2119 assert_eq!(descriptor.to_string(), "elsh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))#2040pn7l");
2120
2121 let descriptor_str = "elsh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))";
2122 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
2123 assert_eq!(descriptor.to_string(), "elsh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))#pqs0de7e");
2124 }
2125
2126 #[test]
2127 fn test_xonly_keys() {
2128 let comp_key = "0308c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
2129 let x_only_key = "08c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
2130
2131 Descriptor::<DescriptorPublicKey>::from_str(&format!("eltr({})", comp_key)).unwrap();
2133 Descriptor::<DescriptorPublicKey>::from_str(&format!("eltr({})", x_only_key)).unwrap();
2134
2135 Descriptor::<DescriptorPublicKey>::from_str(&format!("elwsh(pk({}))", comp_key)).unwrap();
2137 Descriptor::<DescriptorPublicKey>::from_str(&format!("elwsh(pk({}))", x_only_key))
2138 .unwrap_err();
2139 }
2140
2141 #[test]
2142 fn test_find_derivation_index_for_spk() {
2143 let secp = secp256k1_zkp::Secp256k1::verification_only();
2144 let descriptor = Descriptor::<_, NoExt>::from_str("eltr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)").unwrap();
2145 let script_at_0_1 = Script::from_str(
2146 "5120c73ac1b7a518499b9642aed8cfa15d5401e5bd85ad760b937b69521c297722f0",
2147 )
2148 .unwrap();
2149 let expected_concrete = Descriptor::from_str(
2150 "eltr(0283dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145)",
2151 )
2152 .unwrap();
2153
2154 assert_eq!(
2155 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..1),
2156 Ok(None)
2157 );
2158 assert_eq!(
2159 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..2),
2160 Ok(Some((1, expected_concrete.clone())))
2161 );
2162 assert_eq!(
2163 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..10),
2164 Ok(Some((1, expected_concrete)))
2165 );
2166 }
2167
2168 #[test]
2169 fn display_alternate() {
2170 let bare = StdDescriptor::from_str(
2171 "elpk(020000000000000000000000000000000000000000000000000000000000000002)",
2172 )
2173 .unwrap();
2174 assert_eq!(
2175 format!("{}", bare),
2176 "elpk(020000000000000000000000000000000000000000000000000000000000000002)#vlpqwfjv",
2177 );
2178 assert_eq!(
2179 format!("{:#}", bare),
2180 "elpk(020000000000000000000000000000000000000000000000000000000000000002)",
2181 );
2182
2183 let pkh = StdDescriptor::from_str(
2184 "elpkh(020000000000000000000000000000000000000000000000000000000000000002)",
2185 )
2186 .unwrap();
2187 assert_eq!(
2188 format!("{}", pkh),
2189 "elpkh(020000000000000000000000000000000000000000000000000000000000000002)#jzq8e832",
2190 );
2191 assert_eq!(
2192 format!("{:#}", pkh),
2193 "elpkh(020000000000000000000000000000000000000000000000000000000000000002)",
2194 );
2195
2196 let wpkh = StdDescriptor::from_str(
2197 "elwpkh(020000000000000000000000000000000000000000000000000000000000000002)",
2198 )
2199 .unwrap();
2200 assert_eq!(
2201 format!("{}", wpkh),
2202 "elwpkh(020000000000000000000000000000000000000000000000000000000000000002)#vxhqdpz9",
2203 );
2204 assert_eq!(
2205 format!("{:#}", wpkh),
2206 "elwpkh(020000000000000000000000000000000000000000000000000000000000000002)",
2207 );
2208
2209 let shwpkh = StdDescriptor::from_str(
2210 "elsh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))",
2211 )
2212 .unwrap();
2213 assert_eq!(
2214 format!("{}", shwpkh),
2215 "elsh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))#h9ajn2ft",
2216 );
2217 assert_eq!(
2218 format!("{:#}", shwpkh),
2219 "elsh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))",
2220 );
2221
2222 let wsh = StdDescriptor::from_str("elwsh(1)").unwrap();
2223 assert_eq!(format!("{}", wsh), "elwsh(1)#s78w5gmj");
2224 assert_eq!(format!("{:#}", wsh), "elwsh(1)");
2225
2226 let sh = StdDescriptor::from_str("elsh(1)").unwrap();
2227 assert_eq!(format!("{}", sh), "elsh(1)#k4aqrx5p");
2228 assert_eq!(format!("{:#}", sh), "elsh(1)");
2229
2230 let shwsh = StdDescriptor::from_str("elsh(wsh(1))").unwrap();
2231 assert_eq!(format!("{}", shwsh), "elsh(wsh(1))#d05z4wjl");
2232 assert_eq!(format!("{:#}", shwsh), "elsh(wsh(1))");
2233
2234 let tr = StdDescriptor::from_str(
2235 "eltr(020000000000000000000000000000000000000000000000000000000000000002)",
2236 )
2237 .unwrap();
2238 assert_eq!(
2239 format!("{}", tr),
2240 "eltr(020000000000000000000000000000000000000000000000000000000000000002)#e874qu8z",
2241 );
2242 assert_eq!(
2243 format!("{:#}", tr),
2244 "eltr(020000000000000000000000000000000000000000000000000000000000000002)",
2245 );
2246 }
2247
2248 #[test]
2249 fn test_regression_29() {
2250 let _ = Descriptor::<String>::from_str("eltr(,thresh(1,spk_eq(,00)))");
2251 }
2252
2253 #[test]
2254 fn multipath_descriptors() {
2255 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();
2257 assert!(desc.is_multipath());
2258 assert!(!desc.multipath_length_mismatch());
2259 assert_eq!(desc.into_single_descriptors().unwrap(), vec![
2260 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/7'/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/0/*)))").unwrap(),
2261 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/8h/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/1/*)))").unwrap(),
2262 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/20/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/987/*)))").unwrap()
2263 ]);
2264
2265 let desc = Descriptor::<DescriptorPublicKey, NoExt>::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<0;1>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap();
2267 assert!(desc.is_multipath());
2268 assert!(!desc.multipath_length_mismatch());
2269 assert_eq!(desc.into_single_descriptors().unwrap(), vec![
2270 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/0/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap(),
2271 Descriptor::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/1/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap(),
2272 ]);
2273
2274 let notmulti_desc = Descriptor::<DescriptorPublicKey, NoExt>::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap();
2276 assert!(!notmulti_desc.is_multipath());
2277 assert!(!notmulti_desc.multipath_length_mismatch());
2278 assert_eq!(
2279 notmulti_desc.clone().into_single_descriptors().unwrap(),
2280 vec![notmulti_desc]
2281 );
2282
2283 Descriptor::<DescriptorPublicKey>::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<0;1>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/<0;1;2;3;4>/*)))").unwrap_err();
2285 Descriptor::<DescriptorPublicKey>::from_str("elwsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<0;1;2;3>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/<0;1;2>/*)))").unwrap_err();
2286 }
2287}