1use core::fmt;
16use core::ops::Range;
17use core::str::{self, FromStr};
18
19use bellscoin::address::WitnessVersion;
20use bellscoin::hashes::{hash160, ripemd160, sha256};
21use bellscoin::{secp256k1, Address, Network, Script, ScriptBuf, TxIn, Witness};
22use sync::Arc;
23
24use self::checksum::verify_checksum;
25use crate::miniscript::{Legacy, Miniscript, Segwitv0};
26use crate::prelude::*;
27use crate::{
28 expression, hash256, miniscript, BareCtx, Error, ForEachKey, MiniscriptKey, Satisfier,
29 ToPublicKey, TranslateErr, TranslatePk, Translator,
30};
31
32mod bare;
33mod segwitv0;
34mod sh;
35mod sortedmulti;
36mod tr;
37
38pub use self::bare::{Bare, Pkh};
40pub use self::segwitv0::{Wpkh, Wsh, WshInner};
41pub use self::sh::{Sh, ShInner};
42pub use self::sortedmulti::SortedMultiVec;
43pub use self::tr::{TapTree, Tr};
44
45pub mod checksum;
46mod key;
47
48pub use self::key::{
49 ConversionError, DefiniteDescriptorKey, DerivPaths, DescriptorKeyParseError,
50 DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, InnerXKey,
51 SinglePriv, SinglePub, SinglePubKey, Wildcard,
52};
53
54pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey>;
61
62#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
64pub enum Descriptor<Pk: MiniscriptKey> {
65 Bare(Bare<Pk>),
67 Pkh(Pkh<Pk>),
69 Wpkh(Wpkh<Pk>),
71 Sh(Sh<Pk>),
73 Wsh(Wsh<Pk>),
75 Tr(Tr<Pk>),
77}
78
79impl<Pk: MiniscriptKey> From<Bare<Pk>> for Descriptor<Pk> {
80 #[inline]
81 fn from(inner: Bare<Pk>) -> Self {
82 Descriptor::Bare(inner)
83 }
84}
85
86impl<Pk: MiniscriptKey> From<Pkh<Pk>> for Descriptor<Pk> {
87 #[inline]
88 fn from(inner: Pkh<Pk>) -> Self {
89 Descriptor::Pkh(inner)
90 }
91}
92
93impl<Pk: MiniscriptKey> From<Wpkh<Pk>> for Descriptor<Pk> {
94 #[inline]
95 fn from(inner: Wpkh<Pk>) -> Self {
96 Descriptor::Wpkh(inner)
97 }
98}
99
100impl<Pk: MiniscriptKey> From<Sh<Pk>> for Descriptor<Pk> {
101 #[inline]
102 fn from(inner: Sh<Pk>) -> Self {
103 Descriptor::Sh(inner)
104 }
105}
106
107impl<Pk: MiniscriptKey> From<Wsh<Pk>> for Descriptor<Pk> {
108 #[inline]
109 fn from(inner: Wsh<Pk>) -> Self {
110 Descriptor::Wsh(inner)
111 }
112}
113
114impl<Pk: MiniscriptKey> From<Tr<Pk>> for Descriptor<Pk> {
115 #[inline]
116 fn from(inner: Tr<Pk>) -> Self {
117 Descriptor::Tr(inner)
118 }
119}
120
121#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
123pub enum DescriptorType {
124 Bare,
126 Sh,
128 Pkh,
130 Wpkh,
132 Wsh,
134 ShWsh,
136 ShWpkh,
138 ShSortedMulti,
140 WshSortedMulti,
142 ShWshSortedMulti,
144 Tr,
146}
147
148impl DescriptorType {
149 pub fn segwit_version(&self) -> Option<WitnessVersion> {
153 use self::DescriptorType::*;
154 match self {
155 Tr => Some(WitnessVersion::V1),
156 Wpkh | ShWpkh | Wsh | ShWsh | ShWshSortedMulti | WshSortedMulti => {
157 Some(WitnessVersion::V0)
158 }
159 Bare | Sh | Pkh | ShSortedMulti => None,
160 }
161 }
162}
163
164impl<Pk: MiniscriptKey> Descriptor<Pk> {
165 pub fn new_pk(pk: Pk) -> Self {
169 let ms: Miniscript<Pk, BareCtx> =
171 Miniscript::from_ast(miniscript::decode::Terminal::Check(Arc::new(
172 Miniscript::from_ast(miniscript::decode::Terminal::PkK(pk))
173 .expect("Type check cannot fail"),
174 )))
175 .expect("Type check cannot fail");
176 Descriptor::Bare(Bare::new(ms).expect("Context checks cannot fail for p2pk"))
177 }
178
179 pub fn new_pkh(pk: Pk) -> Result<Self, Error> {
181 Ok(Descriptor::Pkh(Pkh::new(pk)?))
182 }
183
184 pub fn new_wpkh(pk: Pk) -> Result<Self, Error> {
187 Ok(Descriptor::Wpkh(Wpkh::new(pk)?))
188 }
189
190 pub fn new_sh_wpkh(pk: Pk) -> Result<Self, Error> {
193 Ok(Descriptor::Sh(Sh::new_wpkh(pk)?))
194 }
195
196 pub fn new_sh(ms: Miniscript<Pk, Legacy>) -> Result<Self, Error> {
202 Ok(Descriptor::Sh(Sh::new(ms)?))
203 }
204
205 pub fn new_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
209 Ok(Descriptor::Wsh(Wsh::new(ms)?))
210 }
211
212 pub fn new_sh_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
216 Ok(Descriptor::Sh(Sh::new_wsh(ms)?))
217 }
218
219 pub fn new_bare(ms: Miniscript<Pk, BareCtx>) -> Result<Self, Error> {
223 Ok(Descriptor::Bare(Bare::new(ms)?))
224 }
225
226 pub fn new_sh_with_wpkh(wpkh: Wpkh<Pk>) -> Self {
230 Descriptor::Sh(Sh::new_with_wpkh(wpkh))
231 }
232
233 pub fn new_sh_with_wsh(wsh: Wsh<Pk>) -> Self {
235 Descriptor::Sh(Sh::new_with_wsh(wsh))
236 }
237
238 pub fn new_sh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
244 Ok(Descriptor::Sh(Sh::new_sortedmulti(k, pks)?))
245 }
246
247 pub fn new_sh_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
251 Ok(Descriptor::Sh(Sh::new_wsh_sortedmulti(k, pks)?))
252 }
253
254 pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
257 Ok(Descriptor::Wsh(Wsh::new_sortedmulti(k, pks)?))
258 }
259
260 pub fn new_tr(key: Pk, script: Option<tr::TapTree<Pk>>) -> Result<Self, Error> {
263 Ok(Descriptor::Tr(Tr::new(key, script)?))
264 }
265
266 pub fn desc_type(&self) -> DescriptorType {
268 match *self {
269 Descriptor::Bare(ref _bare) => DescriptorType::Bare,
270 Descriptor::Pkh(ref _pkh) => DescriptorType::Pkh,
271 Descriptor::Wpkh(ref _wpkh) => DescriptorType::Wpkh,
272 Descriptor::Sh(ref sh) => match sh.as_inner() {
273 ShInner::Wsh(ref wsh) => match wsh.as_inner() {
274 WshInner::SortedMulti(ref _smv) => DescriptorType::ShWshSortedMulti,
275 WshInner::Ms(ref _ms) => DescriptorType::ShWsh,
276 },
277 ShInner::Wpkh(ref _wpkh) => DescriptorType::ShWpkh,
278 ShInner::SortedMulti(ref _smv) => DescriptorType::ShSortedMulti,
279 ShInner::Ms(ref _ms) => DescriptorType::Sh,
280 },
281 Descriptor::Wsh(ref wsh) => match wsh.as_inner() {
282 WshInner::SortedMulti(ref _smv) => DescriptorType::WshSortedMulti,
283 WshInner::Ms(ref _ms) => DescriptorType::Wsh,
284 },
285 Descriptor::Tr(ref _tr) => DescriptorType::Tr,
286 }
287 }
288
289 pub fn sanity_check(&self) -> Result<(), Error> {
299 match *self {
300 Descriptor::Bare(ref bare) => bare.sanity_check(),
301 Descriptor::Pkh(_) => Ok(()),
302 Descriptor::Wpkh(ref wpkh) => wpkh.sanity_check(),
303 Descriptor::Wsh(ref wsh) => wsh.sanity_check(),
304 Descriptor::Sh(ref sh) => sh.sanity_check(),
305 Descriptor::Tr(ref tr) => tr.sanity_check(),
306 }
307 }
308
309 pub fn max_weight_to_satisfy(&self) -> Result<usize, Error> {
348 let weight = match *self {
349 Descriptor::Bare(ref bare) => bare.max_weight_to_satisfy()?,
350 Descriptor::Pkh(ref pkh) => pkh.max_weight_to_satisfy(),
351 Descriptor::Wpkh(ref wpkh) => wpkh.max_weight_to_satisfy(),
352 Descriptor::Wsh(ref wsh) => wsh.max_weight_to_satisfy()?,
353 Descriptor::Sh(ref sh) => sh.max_weight_to_satisfy()?,
354 Descriptor::Tr(ref tr) => tr.max_weight_to_satisfy()?,
355 };
356 Ok(weight)
357 }
358
359 #[deprecated(note = "use max_weight_to_satisfy instead")]
369 #[allow(deprecated)]
370 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
371 let weight = match *self {
372 Descriptor::Bare(ref bare) => bare.max_satisfaction_weight()?,
373 Descriptor::Pkh(ref pkh) => pkh.max_satisfaction_weight(),
374 Descriptor::Wpkh(ref wpkh) => wpkh.max_satisfaction_weight(),
375 Descriptor::Wsh(ref wsh) => wsh.max_satisfaction_weight()?,
376 Descriptor::Sh(ref sh) => sh.max_satisfaction_weight()?,
377 Descriptor::Tr(ref tr) => tr.max_satisfaction_weight()?,
378 };
379 Ok(weight)
380 }
381}
382
383impl<Pk: MiniscriptKey + ToPublicKey> Descriptor<Pk> {
384 pub fn address(&self, network: Network) -> Result<Address, Error> {
391 match *self {
392 Descriptor::Bare(_) => Err(Error::BareDescriptorAddr),
393 Descriptor::Pkh(ref pkh) => Ok(pkh.address(network)),
394 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.address(network)),
395 Descriptor::Wsh(ref wsh) => Ok(wsh.address(network)),
396 Descriptor::Sh(ref sh) => Ok(sh.address(network)),
397 Descriptor::Tr(ref tr) => Ok(tr.address(network)),
398 }
399 }
400
401 pub fn script_pubkey(&self) -> ScriptBuf {
403 match *self {
404 Descriptor::Bare(ref bare) => bare.script_pubkey(),
405 Descriptor::Pkh(ref pkh) => pkh.script_pubkey(),
406 Descriptor::Wpkh(ref wpkh) => wpkh.script_pubkey(),
407 Descriptor::Wsh(ref wsh) => wsh.script_pubkey(),
408 Descriptor::Sh(ref sh) => sh.script_pubkey(),
409 Descriptor::Tr(ref tr) => tr.script_pubkey(),
410 }
411 }
412
413 pub fn unsigned_script_sig(&self) -> ScriptBuf {
421 match *self {
422 Descriptor::Bare(_) => ScriptBuf::new(),
423 Descriptor::Pkh(_) => ScriptBuf::new(),
424 Descriptor::Wpkh(_) => ScriptBuf::new(),
425 Descriptor::Wsh(_) => ScriptBuf::new(),
426 Descriptor::Sh(ref sh) => sh.unsigned_script_sig(),
427 Descriptor::Tr(_) => ScriptBuf::new(),
428 }
429 }
430
431 pub fn explicit_script(&self) -> Result<ScriptBuf, Error> {
438 match *self {
439 Descriptor::Bare(ref bare) => Ok(bare.script_pubkey()),
440 Descriptor::Pkh(ref pkh) => Ok(pkh.script_pubkey()),
441 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.script_pubkey()),
442 Descriptor::Wsh(ref wsh) => Ok(wsh.inner_script()),
443 Descriptor::Sh(ref sh) => Ok(sh.inner_script()),
444 Descriptor::Tr(_) => Err(Error::TrNoScriptCode),
445 }
446 }
447
448 pub fn script_code(&self) -> Result<ScriptBuf, Error> {
456 match *self {
457 Descriptor::Bare(ref bare) => Ok(bare.ecdsa_sighash_script_code()),
458 Descriptor::Pkh(ref pkh) => Ok(pkh.ecdsa_sighash_script_code()),
459 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.ecdsa_sighash_script_code()),
460 Descriptor::Wsh(ref wsh) => Ok(wsh.ecdsa_sighash_script_code()),
461 Descriptor::Sh(ref sh) => Ok(sh.ecdsa_sighash_script_code()),
462 Descriptor::Tr(_) => Err(Error::TrNoScriptCode),
463 }
464 }
465
466 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
470 where
471 S: Satisfier<Pk>,
472 {
473 match *self {
474 Descriptor::Bare(ref bare) => bare.get_satisfaction(satisfier),
475 Descriptor::Pkh(ref pkh) => pkh.get_satisfaction(satisfier),
476 Descriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction(satisfier),
477 Descriptor::Wsh(ref wsh) => wsh.get_satisfaction(satisfier),
478 Descriptor::Sh(ref sh) => sh.get_satisfaction(satisfier),
479 Descriptor::Tr(ref tr) => tr.get_satisfaction(satisfier),
480 }
481 }
482
483 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
487 where
488 S: Satisfier<Pk>,
489 {
490 match *self {
491 Descriptor::Bare(ref bare) => bare.get_satisfaction_mall(satisfier),
492 Descriptor::Pkh(ref pkh) => pkh.get_satisfaction_mall(satisfier),
493 Descriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction_mall(satisfier),
494 Descriptor::Wsh(ref wsh) => wsh.get_satisfaction_mall(satisfier),
495 Descriptor::Sh(ref sh) => sh.get_satisfaction_mall(satisfier),
496 Descriptor::Tr(ref tr) => tr.get_satisfaction_mall(satisfier),
497 }
498 }
499
500 pub fn satisfy<S>(&self, txin: &mut TxIn, satisfier: S) -> Result<(), Error>
504 where
505 S: Satisfier<Pk>,
506 {
507 let (witness, script_sig) = self.get_satisfaction(satisfier)?;
508 txin.witness = Witness::from_slice(&witness);
509 txin.script_sig = script_sig;
510 Ok(())
511 }
512}
513
514impl<P, Q> TranslatePk<P, Q> for Descriptor<P>
515where
516 P: MiniscriptKey,
517 Q: MiniscriptKey,
518{
519 type Output = Descriptor<Q>;
520
521 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, TranslateErr<E>>
523 where
524 T: Translator<P, Q, E>,
525 {
526 let desc = match *self {
527 Descriptor::Bare(ref bare) => Descriptor::Bare(bare.translate_pk(t)?),
528 Descriptor::Pkh(ref pk) => Descriptor::Pkh(pk.translate_pk(t)?),
529 Descriptor::Wpkh(ref pk) => Descriptor::Wpkh(pk.translate_pk(t)?),
530 Descriptor::Sh(ref sh) => Descriptor::Sh(sh.translate_pk(t)?),
531 Descriptor::Wsh(ref wsh) => Descriptor::Wsh(wsh.translate_pk(t)?),
532 Descriptor::Tr(ref tr) => Descriptor::Tr(tr.translate_pk(t)?),
533 };
534 Ok(desc)
535 }
536}
537
538impl<Pk: MiniscriptKey> ForEachKey<Pk> for Descriptor<Pk> {
539 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool {
540 match *self {
541 Descriptor::Bare(ref bare) => bare.for_each_key(pred),
542 Descriptor::Pkh(ref pkh) => pkh.for_each_key(pred),
543 Descriptor::Wpkh(ref wpkh) => wpkh.for_each_key(pred),
544 Descriptor::Wsh(ref wsh) => wsh.for_each_key(pred),
545 Descriptor::Sh(ref sh) => sh.for_each_key(pred),
546 Descriptor::Tr(ref tr) => tr.for_each_key(pred),
547 }
548 }
549}
550
551impl Descriptor<DescriptorPublicKey> {
552 #[deprecated(note = "use has_wildcards instead")]
554 pub fn is_deriveable(&self) -> bool {
555 self.has_wildcard()
556 }
557
558 pub fn has_wildcard(&self) -> bool {
560 self.for_any_key(|key| key.has_wildcard())
561 }
562
563 pub fn at_derivation_index(
569 &self,
570 index: u32,
571 ) -> Result<Descriptor<DefiniteDescriptorKey>, ConversionError> {
572 struct Derivator(u32);
573
574 impl Translator<DescriptorPublicKey, DefiniteDescriptorKey, ConversionError> for Derivator {
575 fn pk(
576 &mut self,
577 pk: &DescriptorPublicKey,
578 ) -> Result<DefiniteDescriptorKey, ConversionError> {
579 pk.clone().at_derivation_index(self.0)
580 }
581
582 translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, ConversionError);
583 }
584 self.translate_pk(&mut Derivator(index))
585 .map_err(|e| e.expect_translator_err("No Context errors while translating"))
586 }
587
588 #[deprecated(note = "use at_derivation_index instead")]
589 pub fn derive(&self, index: u32) -> Result<Descriptor<DefiniteDescriptorKey>, ConversionError> {
591 self.at_derivation_index(index)
592 }
593
594 pub fn derived_descriptor<C: secp256k1::Verification>(
621 &self,
622 secp: &secp256k1::Secp256k1<C>,
623 index: u32,
624 ) -> Result<Descriptor<bellscoin::PublicKey>, ConversionError> {
625 self.at_derivation_index(index)?.derived_descriptor(secp)
626 }
627
628 pub fn parse_descriptor<C: secp256k1::Signing>(
633 secp: &secp256k1::Secp256k1<C>,
634 s: &str,
635 ) -> Result<(Descriptor<DescriptorPublicKey>, KeyMap), Error> {
636 fn parse_key<C: secp256k1::Signing>(
637 s: &str,
638 key_map: &mut KeyMap,
639 secp: &secp256k1::Secp256k1<C>,
640 ) -> Result<DescriptorPublicKey, Error> {
641 let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
642 Ok(sk) => (
643 sk.to_public(secp)
644 .map_err(|e| Error::Unexpected(e.to_string()))?,
645 Some(sk),
646 ),
647 Err(_) => (
648 DescriptorPublicKey::from_str(s)
649 .map_err(|e| Error::Unexpected(e.to_string()))?,
650 None,
651 ),
652 };
653
654 if let Some(secret_key) = secret_key {
655 key_map.insert(public_key.clone(), secret_key);
656 }
657
658 Ok(public_key)
659 }
660
661 let mut keymap_pk = KeyMapWrapper(HashMap::new(), secp);
662
663 struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
664
665 impl<'a, C: secp256k1::Signing> Translator<String, DescriptorPublicKey, Error>
666 for KeyMapWrapper<'a, C>
667 {
668 fn pk(&mut self, pk: &String) -> Result<DescriptorPublicKey, Error> {
669 parse_key(pk, &mut self.0, self.1)
670 }
671
672 fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Error> {
673 let hash =
674 sha256::Hash::from_str(sha256).map_err(|e| Error::Unexpected(e.to_string()))?;
675 Ok(hash)
676 }
677
678 fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, Error> {
679 let hash = hash256::Hash::from_str(hash256)
680 .map_err(|e| Error::Unexpected(e.to_string()))?;
681 Ok(hash)
682 }
683
684 fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, Error> {
685 let hash = ripemd160::Hash::from_str(ripemd160)
686 .map_err(|e| Error::Unexpected(e.to_string()))?;
687 Ok(hash)
688 }
689
690 fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, Error> {
691 let hash = hash160::Hash::from_str(hash160)
692 .map_err(|e| Error::Unexpected(e.to_string()))?;
693 Ok(hash)
694 }
695 }
696
697 let descriptor = Descriptor::<String>::from_str(s)?;
698 let descriptor = descriptor.translate_pk(&mut keymap_pk).map_err(|e| {
699 Error::Unexpected(
700 e.expect_translator_err("No Outer context errors")
701 .to_string(),
702 )
703 })?;
704
705 Ok((descriptor, keymap_pk.0))
706 }
707
708 pub fn to_string_with_secret(&self, key_map: &KeyMap) -> String {
710 struct KeyMapLookUp<'a>(&'a KeyMap);
711
712 impl<'a> Translator<DescriptorPublicKey, String, ()> for KeyMapLookUp<'a> {
713 fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, ()> {
714 key_to_string(pk, self.0)
715 }
716
717 fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
718 Ok(sha256.to_string())
719 }
720
721 fn hash256(&mut self, hash256: &hash256::Hash) -> Result<String, ()> {
722 Ok(hash256.to_string())
723 }
724
725 fn ripemd160(&mut self, ripemd160: &ripemd160::Hash) -> Result<String, ()> {
726 Ok(ripemd160.to_string())
727 }
728
729 fn hash160(&mut self, hash160: &hash160::Hash) -> Result<String, ()> {
730 Ok(hash160.to_string())
731 }
732 }
733
734 fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> Result<String, ()> {
735 Ok(match key_map.get(pk) {
736 Some(secret) => secret.to_string(),
737 None => pk.to_string(),
738 })
739 }
740
741 let descriptor = self
742 .translate_pk(&mut KeyMapLookUp(key_map))
743 .expect("Translation to string cannot fail");
744
745 descriptor.to_string()
746 }
747
748 pub fn find_derivation_index_for_spk<C: secp256k1::Verification>(
756 &self,
757 secp: &secp256k1::Secp256k1<C>,
758 script_pubkey: &Script,
759 range: Range<u32>,
760 ) -> Result<Option<(u32, Descriptor<bellscoin::PublicKey>)>, ConversionError> {
761 let range = if self.has_wildcard() { range } else { 0..1 };
762
763 for i in range {
764 let concrete = self.derived_descriptor(secp, i)?;
765 if &concrete.script_pubkey() == script_pubkey {
766 return Ok(Some((i, concrete)));
767 }
768 }
769
770 Ok(None)
771 }
772
773 pub fn is_multipath(&self) -> bool {
775 self.for_any_key(DescriptorPublicKey::is_multipath)
776 }
777
778 #[allow(clippy::blocks_in_if_conditions)]
783 pub fn into_single_descriptors(self) -> Result<Vec<Descriptor<DescriptorPublicKey>>, Error> {
784 let mut descriptors = Vec::new();
786 if !self.for_any_key(|key| {
788 if !descriptors.is_empty() {
791 return true;
792 }
793
794 match key {
795 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
796 DescriptorPublicKey::MultiXPub(xpub) => {
797 for _ in 0..xpub.derivation_paths.paths().len() {
798 descriptors.push(self.clone());
799 }
800 true
801 }
802 }
803 }) {
804 return Ok(vec![self]);
806 }
807 assert!(!descriptors.is_empty());
808
809 struct IndexChoser(usize);
811 impl Translator<DescriptorPublicKey, DescriptorPublicKey, Error> for IndexChoser {
812 fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DescriptorPublicKey, Error> {
813 match pk {
814 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => {
815 Ok(pk.clone())
816 }
817 DescriptorPublicKey::MultiXPub(_) => pk
818 .clone()
819 .into_single_keys()
820 .get(self.0)
821 .cloned()
822 .ok_or(Error::MultipathDescLenMismatch),
823 }
824 }
825 translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, Error);
826 }
827
828 for (i, desc) in descriptors.iter_mut().enumerate() {
829 let mut index_choser = IndexChoser(i);
830 *desc = desc
831 .translate_pk(&mut index_choser)
832 .map_err(|e| e.expect_translator_err("No Context errors possible"))?;
833 }
834
835 Ok(descriptors)
836 }
837}
838
839impl Descriptor<DefiniteDescriptorKey> {
840 pub fn derived_descriptor<C: secp256k1::Verification>(
863 &self,
864 secp: &secp256k1::Secp256k1<C>,
865 ) -> Result<Descriptor<bellscoin::PublicKey>, ConversionError> {
866 struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
867
868 impl<'a, C: secp256k1::Verification>
869 Translator<DefiniteDescriptorKey, bellscoin::PublicKey, ConversionError>
870 for Derivator<'a, C>
871 {
872 fn pk(
873 &mut self,
874 pk: &DefiniteDescriptorKey,
875 ) -> Result<bellscoin::PublicKey, ConversionError> {
876 pk.derive_public_key(self.0)
877 }
878
879 translate_hash_clone!(DefiniteDescriptorKey, bellscoin::PublicKey, ConversionError);
880 }
881
882 let derived = self.translate_pk(&mut Derivator(secp));
883 match derived {
884 Ok(derived) => Ok(derived),
885 Err(e) => Err(e.expect_translator_err("No Context errors when deriving keys")),
886 }
887 }
888}
889
890impl_from_tree!(
891 Descriptor<Pk>,
892 fn from_tree(top: &expression::Tree) -> Result<Descriptor<Pk>, Error> {
894 Ok(match (top.name, top.args.len() as u32) {
895 ("pkh", 1) => Descriptor::Pkh(Pkh::from_tree(top)?),
896 ("wpkh", 1) => Descriptor::Wpkh(Wpkh::from_tree(top)?),
897 ("sh", 1) => Descriptor::Sh(Sh::from_tree(top)?),
898 ("wsh", 1) => Descriptor::Wsh(Wsh::from_tree(top)?),
899 ("tr", _) => Descriptor::Tr(Tr::from_tree(top)?),
900 _ => Descriptor::Bare(Bare::from_tree(top)?),
901 })
902 }
903);
904
905impl_from_str!(
906 Descriptor<Pk>,
907 type Err = Error;,
908 fn from_str(s: &str) -> Result<Descriptor<Pk>, Error> {
909 let desc = if s.starts_with("tr(") {
913 Ok(Descriptor::Tr(Tr::from_str(s)?))
914 } else {
915 let desc_str = verify_checksum(s)?;
916 let top = expression::Tree::from_str(desc_str)?;
917 expression::FromTree::from_tree(&top)
918 }?;
919
920 Ok(desc)
921 }
922);
923
924impl<Pk: MiniscriptKey> fmt::Debug for Descriptor<Pk> {
925 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
926 match *self {
927 Descriptor::Bare(ref sub) => fmt::Debug::fmt(sub, f),
928 Descriptor::Pkh(ref pkh) => fmt::Debug::fmt(pkh, f),
929 Descriptor::Wpkh(ref wpkh) => fmt::Debug::fmt(wpkh, f),
930 Descriptor::Sh(ref sub) => fmt::Debug::fmt(sub, f),
931 Descriptor::Wsh(ref sub) => fmt::Debug::fmt(sub, f),
932 Descriptor::Tr(ref tr) => fmt::Debug::fmt(tr, f),
933 }
934 }
935}
936
937impl<Pk: MiniscriptKey> fmt::Display for Descriptor<Pk> {
938 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
939 match *self {
940 Descriptor::Bare(ref sub) => fmt::Display::fmt(sub, f),
941 Descriptor::Pkh(ref pkh) => fmt::Display::fmt(pkh, f),
942 Descriptor::Wpkh(ref wpkh) => fmt::Display::fmt(wpkh, f),
943 Descriptor::Sh(ref sub) => fmt::Display::fmt(sub, f),
944 Descriptor::Wsh(ref sub) => fmt::Display::fmt(sub, f),
945 Descriptor::Tr(ref tr) => fmt::Display::fmt(tr, f),
946 }
947 }
948}
949
950serde_string_impl_pk!(Descriptor, "a script descriptor");
951
952#[cfg(test)]
953mod tests {
954 use core::convert::TryFrom;
955 use core::str::FromStr;
956
957 use bellscoin::blockdata::opcodes::all::{OP_CLTV, OP_CSV};
958 use bellscoin::blockdata::script::Instruction;
959 use bellscoin::blockdata::{opcodes, script};
960 use bellscoin::hashes::hex::FromHex;
961 use bellscoin::hashes::{hash160, sha256, Hash};
962 use bellscoin::script::PushBytes;
963 use bellscoin::sighash::EcdsaSighashType;
964 use bellscoin::{self, bip32, secp256k1, PublicKey, Sequence};
965
966 use super::checksum::desc_checksum;
967 use super::tr::Tr;
968 use super::*;
969 use crate::descriptor::key::Wildcard;
970 use crate::descriptor::{DescriptorPublicKey, DescriptorXKey, SinglePub};
971 #[cfg(feature = "compiler")]
972 use crate::policy;
973 use crate::{hex_script, Descriptor, Error, Miniscript, Satisfier};
974
975 type StdDescriptor = Descriptor<PublicKey>;
976 const TEST_PK: &str = "pk(020000000000000000000000000000000000000000000000000000000000000002)";
977
978 fn roundtrip_descriptor(s: &str) {
979 let desc = Descriptor::<String>::from_str(s).unwrap();
980 let output = desc.to_string();
981 let normalize_aliases = s.replace("c:pk_k(", "pk(").replace("c:pk_h(", "pkh(");
982 assert_eq!(
983 format!(
984 "{}#{}",
985 &normalize_aliases,
986 desc_checksum(&normalize_aliases).unwrap()
987 ),
988 output
989 );
990 }
991
992 #[test]
993 fn desc_rtt_tests() {
994 roundtrip_descriptor("c:pk_k()");
995 roundtrip_descriptor("wsh(pk())");
996 roundtrip_descriptor("wsh(c:pk_k())");
997 roundtrip_descriptor("c:pk_h()");
998 }
999 #[test]
1000 fn parse_descriptor() {
1001 StdDescriptor::from_str("(").unwrap_err();
1002 StdDescriptor::from_str("(x()").unwrap_err();
1003 StdDescriptor::from_str("(\u{7f}()3").unwrap_err();
1004 StdDescriptor::from_str("pk()").unwrap_err();
1005 StdDescriptor::from_str("nl:0").unwrap_err(); let compressed_pk = String::from("");
1007 assert_eq!(
1008 StdDescriptor::from_str("sh(sortedmulti)")
1009 .unwrap_err()
1010 .to_string(),
1011 "unexpected «no arguments given for sortedmulti»"
1012 ); assert_eq!(
1014 StdDescriptor::from_str(&format!("sh(sortedmulti(2,{}))", compressed_pk))
1015 .unwrap_err()
1016 .to_string(),
1017 "unexpected «higher threshold than there were keys in sortedmulti»"
1018 ); StdDescriptor::from_str(TEST_PK).unwrap();
1021
1022 let uncompressed_pk =
1023 "0414fc03b8df87cd7b872996810db8458d61da8448e531569c8517b469a119d267be5645686309c6e6736dbd93940707cc9143d3cf29f1b877ff340e2cb2d259cf";
1024
1025 StdDescriptor::from_str(&format!("pk({})", uncompressed_pk)).unwrap();
1027 StdDescriptor::from_str(&format!("pkh({})", uncompressed_pk)).unwrap();
1028 StdDescriptor::from_str(&format!("sh(pk({}))", uncompressed_pk)).unwrap();
1029 StdDescriptor::from_str(&format!("wpkh({})", uncompressed_pk)).unwrap_err();
1030 StdDescriptor::from_str(&format!("sh(wpkh({}))", uncompressed_pk)).unwrap_err();
1031 StdDescriptor::from_str(&format!("wsh(pk{})", uncompressed_pk)).unwrap_err();
1032 StdDescriptor::from_str(&format!("sh(wsh(pk{}))", uncompressed_pk)).unwrap_err();
1033 StdDescriptor::from_str(&format!(
1034 "or_i(pk({}),pk({}))",
1035 uncompressed_pk, uncompressed_pk
1036 ))
1037 .unwrap_err();
1038 }
1039
1040 #[test]
1041 pub fn script_pubkey() {
1042 let bare = StdDescriptor::from_str(
1043 "multi(1,020000000000000000000000000000000000000000000000000000000000000002)",
1044 )
1045 .unwrap();
1046 assert_eq!(
1047 bare.script_pubkey(),
1048 hex_script(
1049 "512102000000000000000000000000000000000000000000000000000000000000000251ae"
1050 )
1051 );
1052 assert_eq!(
1053 bare.address(Network::Bellscoin).unwrap_err().to_string(),
1054 "Bare descriptors don't have address"
1055 );
1056
1057 let pk = StdDescriptor::from_str(TEST_PK).unwrap();
1058 assert_eq!(
1059 pk.script_pubkey(),
1060 ScriptBuf::from(vec![
1061 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1063 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xac,
1064 ])
1065 );
1066
1067 let pkh = StdDescriptor::from_str(
1068 "pkh(\
1069 020000000000000000000000000000000000000000000000000000000000000002\
1070 )",
1071 )
1072 .unwrap();
1073 assert_eq!(
1074 pkh.script_pubkey(),
1075 script::Builder::new()
1076 .push_opcode(opcodes::all::OP_DUP)
1077 .push_opcode(opcodes::all::OP_HASH160)
1078 .push_slice(
1079 &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",)
1080 .unwrap()
1081 .to_byte_array()
1082 )
1083 .push_opcode(opcodes::all::OP_EQUALVERIFY)
1084 .push_opcode(opcodes::all::OP_CHECKSIG)
1085 .into_script()
1086 );
1087 assert_eq!(
1088 pkh.address(Network::Bellscoin,).unwrap().to_string(),
1089 "1D7nRvrRgzCg9kYBwhPH3j3Gs6SmsRg3Wq"
1090 );
1091
1092 let wpkh = StdDescriptor::from_str(
1093 "wpkh(\
1094 020000000000000000000000000000000000000000000000000000000000000002\
1095 )",
1096 )
1097 .unwrap();
1098 assert_eq!(
1099 wpkh.script_pubkey(),
1100 script::Builder::new()
1101 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1102 .push_slice(
1103 &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",)
1104 .unwrap()
1105 .to_byte_array()
1106 )
1107 .into_script()
1108 );
1109 assert_eq!(
1110 wpkh.address(Network::Bellscoin,).unwrap().to_string(),
1111 "bc1qsn57m9drscflq5nl76z6ny52hck5w4x5wqd9yt"
1112 );
1113
1114 let shwpkh = StdDescriptor::from_str(
1115 "sh(wpkh(\
1116 020000000000000000000000000000000000000000000000000000000000000002\
1117 ))",
1118 )
1119 .unwrap();
1120 assert_eq!(
1121 shwpkh.script_pubkey(),
1122 script::Builder::new()
1123 .push_opcode(opcodes::all::OP_HASH160)
1124 .push_slice(
1125 &hash160::Hash::from_str("f1c3b9a431134cb90a500ec06e0067cfa9b8bba7",)
1126 .unwrap()
1127 .to_byte_array()
1128 )
1129 .push_opcode(opcodes::all::OP_EQUAL)
1130 .into_script()
1131 );
1132 assert_eq!(
1133 shwpkh.address(Network::Bellscoin,).unwrap().to_string(),
1134 "3PjMEzoveVbvajcnDDuxcJhsuqPHgydQXq"
1135 );
1136
1137 let sh = StdDescriptor::from_str(
1138 "sh(c:pk_k(\
1139 020000000000000000000000000000000000000000000000000000000000000002\
1140 ))",
1141 )
1142 .unwrap();
1143 assert_eq!(
1144 sh.script_pubkey(),
1145 script::Builder::new()
1146 .push_opcode(opcodes::all::OP_HASH160)
1147 .push_slice(
1148 &hash160::Hash::from_str("aa5282151694d3f2f32ace7d00ad38f927a33ac8",)
1149 .unwrap()
1150 .to_byte_array()
1151 )
1152 .push_opcode(opcodes::all::OP_EQUAL)
1153 .into_script()
1154 );
1155 assert_eq!(
1156 sh.address(Network::Bellscoin,).unwrap().to_string(),
1157 "3HDbdvM9CQ6ASnQFUkWw6Z4t3qNwMesJE9"
1158 );
1159
1160 let wsh = StdDescriptor::from_str(
1161 "wsh(c:pk_k(\
1162 020000000000000000000000000000000000000000000000000000000000000002\
1163 ))",
1164 )
1165 .unwrap();
1166 assert_eq!(
1167 wsh.script_pubkey(),
1168 script::Builder::new()
1169 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1170 .push_slice(
1171 &sha256::Hash::from_str(
1172 "\
1173 f9379edc8983152dc781747830075bd5\
1174 3896e4b0ce5bff73777fd77d124ba085\
1175 "
1176 )
1177 .unwrap()
1178 .to_byte_array()
1179 )
1180 .into_script()
1181 );
1182 assert_eq!(
1183 wsh.address(Network::Bellscoin,).unwrap().to_string(),
1184 "bc1qlymeahyfsv2jm3upw3urqp6m65ufde9seedl7umh0lth6yjt5zzsk33tv6"
1185 );
1186
1187 let shwsh = StdDescriptor::from_str(
1188 "sh(wsh(c:pk_k(\
1189 020000000000000000000000000000000000000000000000000000000000000002\
1190 )))",
1191 )
1192 .unwrap();
1193 assert_eq!(
1194 shwsh.script_pubkey(),
1195 script::Builder::new()
1196 .push_opcode(opcodes::all::OP_HASH160)
1197 .push_slice(
1198 &hash160::Hash::from_str("4bec5d7feeed99e1d0a23fe32a4afe126a7ff07e",)
1199 .unwrap()
1200 .to_byte_array()
1201 )
1202 .push_opcode(opcodes::all::OP_EQUAL)
1203 .into_script()
1204 );
1205 assert_eq!(
1206 shwsh.address(Network::Bellscoin,).unwrap().to_string(),
1207 "38cTksiyPT2b1uGRVbVqHdDhW9vKs84N6Z"
1208 );
1209 }
1210
1211 #[test]
1212 fn satisfy() {
1213 let secp = secp256k1::Secp256k1::new();
1214 let sk =
1215 secp256k1::SecretKey::from_slice(&b"sally was a secret key, she said"[..]).unwrap();
1216 let pk = bellscoin::PublicKey::new(secp256k1::PublicKey::from_secret_key(&secp, &sk));
1217 let msg = secp256k1::Message::from_slice(&b"michael was a message, amusingly"[..])
1218 .expect("32 bytes");
1219 let sig = secp.sign_ecdsa(&msg, &sk);
1220 let mut sigser = sig.serialize_der().to_vec();
1221 sigser.push(0x01); struct SimpleSat {
1224 sig: secp256k1::ecdsa::Signature,
1225 pk: bellscoin::PublicKey,
1226 }
1227
1228 impl Satisfier<bellscoin::PublicKey> for SimpleSat {
1229 fn lookup_ecdsa_sig(
1230 &self,
1231 pk: &bellscoin::PublicKey,
1232 ) -> Option<bellscoin::ecdsa::Signature> {
1233 if *pk == self.pk {
1234 Some(bellscoin::ecdsa::Signature {
1235 sig: self.sig,
1236 hash_ty: bellscoin::sighash::EcdsaSighashType::All,
1237 })
1238 } else {
1239 None
1240 }
1241 }
1242 }
1243
1244 let satisfier = SimpleSat { sig, pk };
1245 let ms = ms_str!("c:pk_k({})", pk);
1246
1247 let mut txin = bellscoin::TxIn {
1248 previous_output: bellscoin::OutPoint::default(),
1249 script_sig: bellscoin::ScriptBuf::new(),
1250 sequence: Sequence::from_height(100),
1251 witness: Witness::default(),
1252 };
1253 let bare = Descriptor::new_bare(ms).unwrap();
1254
1255 bare.satisfy(&mut txin, &satisfier).expect("satisfaction");
1256 assert_eq!(
1257 txin,
1258 bellscoin::TxIn {
1259 previous_output: bellscoin::OutPoint::default(),
1260 script_sig: script::Builder::new()
1261 .push_slice(<&PushBytes>::try_from(sigser.as_slice()).unwrap())
1262 .into_script(),
1263 sequence: Sequence::from_height(100),
1264 witness: Witness::default(),
1265 }
1266 );
1267 assert_eq!(bare.unsigned_script_sig(), bellscoin::ScriptBuf::new());
1268
1269 let pkh = Descriptor::new_pkh(pk).unwrap();
1270 pkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1271 assert_eq!(
1272 txin,
1273 bellscoin::TxIn {
1274 previous_output: bellscoin::OutPoint::default(),
1275 script_sig: script::Builder::new()
1276 .push_slice(<&PushBytes>::try_from(sigser.as_slice()).unwrap())
1277 .push_key(&pk)
1278 .into_script(),
1279 sequence: Sequence::from_height(100),
1280 witness: Witness::default(),
1281 }
1282 );
1283 assert_eq!(pkh.unsigned_script_sig(), bellscoin::ScriptBuf::new());
1284
1285 let wpkh = Descriptor::new_wpkh(pk).unwrap();
1286 wpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1287 assert_eq!(
1288 txin,
1289 bellscoin::TxIn {
1290 previous_output: bellscoin::OutPoint::default(),
1291 script_sig: bellscoin::ScriptBuf::new(),
1292 sequence: Sequence::from_height(100),
1293 witness: Witness::from_slice(&vec![sigser.clone(), pk.to_bytes(),]),
1294 }
1295 );
1296 assert_eq!(wpkh.unsigned_script_sig(), bellscoin::ScriptBuf::new());
1297
1298 let shwpkh = Descriptor::new_sh_wpkh(pk).unwrap();
1299 shwpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1300 let redeem_script = script::Builder::new()
1301 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1302 .push_slice(
1303 &hash160::Hash::from_str("d1b2a1faf62e73460af885c687dee3b7189cd8ab")
1304 .unwrap()
1305 .to_byte_array(),
1306 )
1307 .into_script();
1308 assert_eq!(
1309 txin,
1310 bellscoin::TxIn {
1311 previous_output: bellscoin::OutPoint::default(),
1312 script_sig: script::Builder::new()
1313 .push_slice(<&PushBytes>::try_from(redeem_script.as_bytes()).unwrap())
1314 .into_script(),
1315 sequence: Sequence::from_height(100),
1316 witness: Witness::from_slice(&vec![sigser.clone(), pk.to_bytes(),]),
1317 }
1318 );
1319 assert_eq!(
1320 shwpkh.unsigned_script_sig(),
1321 script::Builder::new()
1322 .push_slice(<&PushBytes>::try_from(redeem_script.as_bytes()).unwrap())
1323 .into_script()
1324 );
1325
1326 let ms = ms_str!("c:pk_k({})", pk);
1327 let sh = Descriptor::new_sh(ms.clone()).unwrap();
1328 sh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1329 assert_eq!(
1330 txin,
1331 bellscoin::TxIn {
1332 previous_output: bellscoin::OutPoint::default(),
1333 script_sig: script::Builder::new()
1334 .push_slice(<&PushBytes>::try_from(sigser.as_slice()).unwrap())
1335 .push_slice(<&PushBytes>::try_from(ms.encode().as_bytes()).unwrap())
1336 .into_script(),
1337 sequence: Sequence::from_height(100),
1338 witness: Witness::default(),
1339 }
1340 );
1341 assert_eq!(sh.unsigned_script_sig(), bellscoin::ScriptBuf::new());
1342
1343 let ms = ms_str!("c:pk_k({})", pk);
1344
1345 let wsh = Descriptor::new_wsh(ms.clone()).unwrap();
1346 wsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1347 assert_eq!(
1348 txin,
1349 bellscoin::TxIn {
1350 previous_output: bellscoin::OutPoint::default(),
1351 script_sig: bellscoin::ScriptBuf::new(),
1352 sequence: Sequence::from_height(100),
1353 witness: Witness::from_slice(&vec![sigser.clone(), ms.encode().into_bytes(),]),
1354 }
1355 );
1356 assert_eq!(wsh.unsigned_script_sig(), bellscoin::ScriptBuf::new());
1357
1358 let shwsh = Descriptor::new_sh_wsh(ms.clone()).unwrap();
1359 shwsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1360 assert_eq!(
1361 txin,
1362 bellscoin::TxIn {
1363 previous_output: bellscoin::OutPoint::default(),
1364 script_sig: script::Builder::new()
1365 .push_slice(
1366 <&PushBytes>::try_from(ms.encode().to_v0_p2wsh().as_bytes()).unwrap()
1367 )
1368 .into_script(),
1369 sequence: Sequence::from_height(100),
1370 witness: Witness::from_slice(&vec![sigser.clone(), ms.encode().into_bytes(),]),
1371 }
1372 );
1373 assert_eq!(
1374 shwsh.unsigned_script_sig(),
1375 script::Builder::new()
1376 .push_slice(<&PushBytes>::try_from(ms.encode().to_v0_p2wsh().as_bytes()).unwrap())
1377 .into_script()
1378 );
1379 }
1380
1381 #[test]
1382 fn after_is_cltv() {
1383 let descriptor = Descriptor::<bellscoin::PublicKey>::from_str("wsh(after(1000))").unwrap();
1384 let script = descriptor.explicit_script().unwrap();
1385
1386 let actual_instructions: Vec<_> = script.instructions().collect();
1387 let check = actual_instructions.last().unwrap();
1388
1389 assert_eq!(check, &Ok(Instruction::Op(OP_CLTV)))
1390 }
1391
1392 #[test]
1393 fn older_is_csv() {
1394 let descriptor = Descriptor::<bellscoin::PublicKey>::from_str("wsh(older(1000))").unwrap();
1395 let script = descriptor.explicit_script().unwrap();
1396
1397 let actual_instructions: Vec<_> = script.instructions().collect();
1398 let check = actual_instructions.last().unwrap();
1399
1400 assert_eq!(check, &Ok(Instruction::Op(OP_CSV)))
1401 }
1402
1403 #[test]
1404 fn tr_roundtrip_key() {
1405 let script = Tr::<String>::from_str("tr()").unwrap().to_string();
1406 assert_eq!(script, format!("tr()#x4ml3kxd"))
1407 }
1408
1409 #[test]
1410 fn tr_roundtrip_script() {
1411 let descriptor = Tr::<String>::from_str("tr(,{pk(),pk()})")
1412 .unwrap()
1413 .to_string();
1414
1415 assert_eq!(descriptor, "tr(,{pk(),pk()})#7dqr6v8r");
1416
1417 let descriptor = Descriptor::<String>::from_str("tr(A,{pk(B),pk(C)})")
1418 .unwrap()
1419 .to_string();
1420 assert_eq!(descriptor, "tr(A,{pk(B),pk(C)})#y0uc9t6x");
1421 }
1422
1423 #[test]
1424 fn tr_roundtrip_tree() {
1425 let p1 = "020000000000000000000000000000000000000000000000000000000000000001";
1426 let p2 = "020000000000000000000000000000000000000000000000000000000000000002";
1427 let p3 = "020000000000000000000000000000000000000000000000000000000000000003";
1428 let p4 = "020000000000000000000000000000000000000000000000000000000000000004";
1429 let p5 = "03f8551772d66557da28c1de858124f365a8eb30ce6ad79c10e0f4c546d0ab0f82";
1430 let descriptor = Tr::<PublicKey>::from_str(&format!(
1431 "tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})",
1432 p1, p2, p3, p4, p5
1433 ))
1434 .unwrap()
1435 .to_string();
1436
1437 assert_eq!(
1439 descriptor,
1440 format!(
1441 "tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})#tvu28c0s",
1442 p1, p2, p3, p4, p5
1443 )
1444 )
1445 }
1446
1447 #[test]
1448 fn tr_script_pubkey() {
1449 let key = Descriptor::<bellscoin::PublicKey>::from_str(
1450 "tr(02e20e746af365e86647826397ba1c0e0d5cb685752976fe2f326ab76bdc4d6ee9)",
1451 )
1452 .unwrap();
1453 assert_eq!(
1454 key.script_pubkey().to_hex_string(),
1455 "51209c19294f03757da3dc235a5960631e3c55751632f5889b06b7a053bdc0bcfbcb"
1456 )
1457 }
1458
1459 #[test]
1460 fn roundtrip_tests() {
1461 let descriptor = Descriptor::<bellscoin::PublicKey>::from_str("multi");
1462 assert_eq!(
1463 descriptor.unwrap_err().to_string(),
1464 "unexpected «no arguments given»"
1465 )
1466 }
1467
1468 #[test]
1469 fn empty_thresh() {
1470 let descriptor = Descriptor::<bellscoin::PublicKey>::from_str("thresh");
1471 assert_eq!(
1472 descriptor.unwrap_err().to_string(),
1473 "unexpected «no arguments given»"
1474 )
1475 }
1476
1477 #[test]
1478 fn witness_stack_for_andv_is_arranged_in_correct_order() {
1479 let a = bellscoin::PublicKey::from_str(
1481 "02937402303919b3a2ee5edd5009f4236f069bf75667b8e6ecf8e5464e20116a0e",
1482 )
1483 .unwrap();
1484 let sig_a = secp256k1::ecdsa::Signature::from_str("3045022100a7acc3719e9559a59d60d7b2837f9842df30e7edcd754e63227e6168cec72c5d022066c2feba4671c3d99ea75d9976b4da6c86968dbf3bab47b1061e7a1966b1778c").unwrap();
1485
1486 let b = bellscoin::PublicKey::from_str(
1487 "02eb64639a17f7334bb5a1a3aad857d6fec65faef439db3de72f85c88bc2906ad3",
1488 )
1489 .unwrap();
1490 let sig_b = secp256k1::ecdsa::Signature::from_str("3044022075b7b65a7e6cd386132c5883c9db15f9a849a0f32bc680e9986398879a57c276022056d94d12255a4424f51c700ac75122cb354895c9f2f88f0cbb47ba05c9c589ba").unwrap();
1491
1492 let descriptor = Descriptor::<bellscoin::PublicKey>::from_str(&format!(
1493 "wsh(and_v(v:pk({A}),pk({B})))",
1494 A = a,
1495 B = b
1496 ))
1497 .unwrap();
1498
1499 let mut txin = bellscoin::TxIn {
1500 previous_output: bellscoin::OutPoint::default(),
1501 script_sig: bellscoin::ScriptBuf::new(),
1502 sequence: Sequence::ZERO,
1503 witness: Witness::default(),
1504 };
1505 let satisfier = {
1506 let mut satisfier = HashMap::with_capacity(2);
1507
1508 satisfier.insert(
1509 a,
1510 bellscoin::ecdsa::Signature {
1511 sig: sig_a,
1512 hash_ty: EcdsaSighashType::All,
1513 },
1514 );
1515 satisfier.insert(
1516 b,
1517 bellscoin::ecdsa::Signature {
1518 sig: sig_b,
1519 hash_ty: EcdsaSighashType::All,
1520 },
1521 );
1522
1523 satisfier
1524 };
1525
1526 descriptor.satisfy(&mut txin, &satisfier).unwrap();
1528
1529 let wit = txin.witness.to_vec();
1531 let witness0 = &wit[0];
1532 let witness1 = &wit[1];
1533
1534 let sig0 = secp256k1::ecdsa::Signature::from_der(&witness0[..witness0.len() - 1]).unwrap();
1535 let sig1 = secp256k1::ecdsa::Signature::from_der(&witness1[..witness1.len() - 1]).unwrap();
1536
1537 assert_eq!(sig1, sig_a);
1542 assert_eq!(sig0, sig_b);
1543 }
1544
1545 #[test]
1546 fn test_scriptcode() {
1547 let descriptor = Descriptor::<PublicKey>::from_str(
1549 "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
1550 )
1551 .unwrap();
1552 assert_eq!(
1553 *descriptor.script_code().unwrap().as_bytes(),
1554 Vec::<u8>::from_hex("76a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac").unwrap()[..]
1555 );
1556
1557 let descriptor = Descriptor::<PublicKey>::from_str(
1559 "sh(wpkh(03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873))",
1560 )
1561 .unwrap();
1562 assert_eq!(
1563 *descriptor.script_code().unwrap().as_bytes(),
1564 Vec::<u8>::from_hex("76a91479091972186c449eb1ded22b78e40d009bdf008988ac").unwrap()[..]
1565 );
1566
1567 let descriptor = Descriptor::<PublicKey>::from_str(
1569 "wsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626))",
1570 )
1571 .unwrap();
1572 assert_eq!(
1573 *descriptor
1574 .script_code().unwrap()
1575 .as_bytes(),
1576 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae").unwrap()[..]
1577 );
1578
1579 let descriptor = Descriptor::<PublicKey>::from_str("sh(wsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626)))").unwrap();
1581 assert_eq!(
1582 *descriptor
1583 .script_code().unwrap()
1584 .as_bytes(),
1585 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae")
1586 .unwrap()[..]
1587 );
1588 }
1589
1590 #[test]
1591 fn parse_descriptor_key() {
1592 let key = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*";
1594 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1595 origin: Some((
1596 bip32::Fingerprint::from([0x78, 0x41, 0x2e, 0x3a]),
1597 (&[
1598 bip32::ChildNumber::from_hardened_idx(44).unwrap(),
1599 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1600 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1601 ][..])
1602 .into(),
1603 )),
1604 xkey: bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1605 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1606 wildcard: Wildcard::Unhardened,
1607 });
1608 assert_eq!(expected, key.parse().unwrap());
1609 assert_eq!(format!("{}", expected), key);
1610
1611 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1";
1613 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1614 origin: None,
1615 xkey: bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1616 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1617 wildcard: Wildcard::None,
1618 });
1619 assert_eq!(expected, key.parse().unwrap());
1620 assert_eq!(format!("{}", expected), key);
1621
1622 let key = "tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed/1";
1624 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1625 origin: None,
1626 xkey: bip32::ExtendedPubKey::from_str("tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed").unwrap(),
1627 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1628 wildcard: Wildcard::None,
1629 });
1630 assert_eq!(expected, key.parse().unwrap());
1631 assert_eq!(format!("{}", expected), key);
1632
1633 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
1635 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1636 origin: None,
1637 xkey: bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1638 derivation_path: bip32::DerivationPath::from(&[][..]),
1639 wildcard: Wildcard::None,
1640 });
1641 assert_eq!(expected, key.parse().unwrap());
1642 assert_eq!(format!("{}", expected), key);
1643
1644 let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
1646 let expected = DescriptorPublicKey::Single(SinglePub {
1647 key: SinglePubKey::FullKey(
1648 bellscoin::PublicKey::from_str(
1649 "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8",
1650 )
1651 .unwrap(),
1652 ),
1653 origin: None,
1654 });
1655 assert_eq!(expected, key.parse().unwrap());
1656 assert_eq!(format!("{}", expected), key);
1657
1658 let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a";
1660 let expected = DescriptorPublicKey::Single(SinglePub {
1661 key: SinglePubKey::FullKey(bellscoin::PublicKey::from_str(
1662 "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a",
1663 )
1664 .unwrap()),
1665 origin: None,
1666 });
1667 assert_eq!(expected, key.parse().unwrap());
1668 assert_eq!(format!("{}", expected), key);
1669
1670 let desc =
1672 "[78412e3a/0'/42/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8";
1673 let expected = DescriptorPublicKey::Single(SinglePub {
1674 key: SinglePubKey::FullKey(
1675 bellscoin::PublicKey::from_str(
1676 "0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8",
1677 )
1678 .unwrap(),
1679 ),
1680 origin: Some((
1681 bip32::Fingerprint::from([0x78, 0x41, 0x2e, 0x3a]),
1682 (&[
1683 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1684 bip32::ChildNumber::from_normal_idx(42).unwrap(),
1685 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1686 ][..])
1687 .into(),
1688 )),
1689 });
1690 assert_eq!(expected, desc.parse().expect("Parsing desc"));
1691 assert_eq!(format!("{}", expected), desc);
1692 }
1693
1694 #[test]
1695 fn test_sortedmulti() {
1696 fn _test_sortedmulti(raw_desc_one: &str, raw_desc_two: &str, raw_addr_expected: &str) {
1697 let secp_ctx = secp256k1::Secp256k1::verification_only();
1698 let index = 5;
1699
1700 let desc_one = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_one).unwrap();
1702 let desc_two = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_two).unwrap();
1703
1704 assert_eq!(desc_one.to_string(), raw_desc_one);
1706 assert_eq!(desc_two.to_string(), raw_desc_two);
1707
1708 let addr_one = desc_one
1710 .at_derivation_index(index)
1711 .unwrap()
1712 .derived_descriptor(&secp_ctx)
1713 .unwrap()
1714 .address(bellscoin::Network::Bellscoin)
1715 .unwrap();
1716 let addr_two = desc_two
1717 .at_derivation_index(index)
1718 .unwrap()
1719 .derived_descriptor(&secp_ctx)
1720 .unwrap()
1721 .address(bellscoin::Network::Bellscoin)
1722 .unwrap();
1723 let addr_expected = bellscoin::Address::from_str(raw_addr_expected)
1724 .unwrap()
1725 .assume_checked();
1726 assert_eq!(addr_one, addr_expected);
1727 assert_eq!(addr_two, addr_expected);
1728 }
1729
1730 _test_sortedmulti(
1732 "sh(sortedmulti(1,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352))#uetvewm2",
1733 "sh(sortedmulti(1,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))#7l8smyg9",
1734 "3JZJNxvDKe6Y55ZaF5223XHwfF2eoMNnoV",
1735 );
1736
1737 _test_sortedmulti(
1739 "wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH))#7etm7zk7",
1740 "wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB))#ppmeel9k",
1741 "bc1qpq2cfgz5lktxzr5zqv7nrzz46hsvq3492ump9pz8rzcl8wqtwqcspx5y6a",
1742 );
1743
1744 _test_sortedmulti(
1746 "sh(wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*)))#u60cee0u",
1747 "sh(wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*)))#75dkf44w",
1748 "325zcVBN5o2eqqqtGwPjmtDd8dJRyYP82s",
1749 );
1750 }
1751
1752 #[test]
1753 fn test_parse_descriptor() {
1754 let secp = &secp256k1::Secp256k1::signing_only();
1755 let (descriptor, key_map) = Descriptor::parse_descriptor(secp, "wpkh(tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/44'/0'/0'/0/*)").unwrap();
1756 assert_eq!(descriptor.to_string(), "wpkh([2cbe2a6d/44'/0'/0']tpubDCvNhURocXGZsLNqWcqD3syHTqPXrMSTwi8feKVwAcpi29oYKsDD3Vex7x2TDneKMVN23RbLprfxB69v94iYqdaYHsVz3kPR37NQXeqouVz/0/*)#nhdxg96s");
1757 assert_eq!(key_map.len(), 1);
1758
1759 macro_rules! check_invalid_checksum {
1761 ($secp: ident,$($desc: expr),*) => {
1762 $(
1763 match Descriptor::parse_descriptor($secp, $desc) {
1764 Err(Error::BadDescriptor(_)) => {},
1765 Err(e) => panic!("Expected bad checksum for {}, got '{}'", $desc, e),
1766 _ => panic!("Invalid checksum treated as valid: {}", $desc),
1767 };
1768 )*
1769 };
1770 }
1771 check_invalid_checksum!(secp,
1772 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#",
1773 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#",
1774 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfyq",
1775 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq",
1776 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf",
1777 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5",
1778 "sh(multi(3,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy",
1779 "sh(multi(3,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t",
1780 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjq09x4t",
1781 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))##ggssrxfy",
1782 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))##tjq09x4t"
1783 );
1784
1785 Descriptor::parse_descriptor(secp, "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy").expect("Valid descriptor with checksum");
1786 Descriptor::parse_descriptor(secp, "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t").expect("Valid descriptor with checksum");
1787 }
1788
1789 #[test]
1790 #[cfg(feature = "compiler")]
1791 fn parse_and_derive() {
1792 let descriptor_str = "thresh(2,\
1793pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*),\
1794pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
1795pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
1796 let policy: policy::concrete::Policy<DescriptorPublicKey> = descriptor_str.parse().unwrap();
1797 let descriptor = Descriptor::new_sh(policy.compile().unwrap()).unwrap();
1798 let definite_descriptor = descriptor.at_derivation_index(42).unwrap();
1799
1800 let res_descriptor_str = "thresh(2,\
1801pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42),\
1802pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
1803pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
1804 let res_policy: policy::concrete::Policy<DescriptorPublicKey> =
1805 res_descriptor_str.parse().unwrap();
1806 let res_descriptor = Descriptor::new_sh(res_policy.compile().unwrap()).unwrap();
1807
1808 assert_eq!(res_descriptor.to_string(), definite_descriptor.to_string());
1809 }
1810
1811 #[test]
1812 fn parse_with_secrets() {
1813 let secp = &secp256k1::Secp256k1::signing_only();
1814 let descriptor_str = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)#v20xlvm9";
1815 let (descriptor, keymap) =
1816 Descriptor::<DescriptorPublicKey>::parse_descriptor(secp, descriptor_str).unwrap();
1817
1818 let expected = "wpkh([a12b02f4/44'/0'/0']xpub6BzhLAQUDcBUfHRQHZxDF2AbcJqp4Kaeq6bzJpXrjrWuK26ymTFwkEFbxPra2bJ7yeZKbDjfDeFwxe93JMqpo5SsPJH6dZdvV9kMzJkAZ69/0/*)#u37l7u8u";
1819 assert_eq!(expected, descriptor.to_string());
1820 assert_eq!(keymap.len(), 1);
1821
1822 assert_eq!(descriptor_str, descriptor.to_string_with_secret(&keymap));
1824 }
1825
1826 #[test]
1827 fn checksum_for_nested_sh() {
1828 let descriptor_str = "sh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))";
1829 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
1830 assert_eq!(descriptor.to_string(), "sh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))#tjp2zm88");
1831
1832 let descriptor_str = "sh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))";
1833 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
1834 assert_eq!(descriptor.to_string(), "sh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))#6c6hwr22");
1835 }
1836
1837 #[test]
1838 fn test_xonly_keys() {
1839 let comp_key = "0308c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
1840 let x_only_key = "08c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
1841
1842 Descriptor::<DescriptorPublicKey>::from_str(&format!("tr({})", comp_key)).unwrap();
1844 Descriptor::<DescriptorPublicKey>::from_str(&format!("tr({})", x_only_key)).unwrap();
1845
1846 Descriptor::<DescriptorPublicKey>::from_str(&format!("wsh(pk({}))", comp_key)).unwrap();
1848 Descriptor::<DescriptorPublicKey>::from_str(&format!("wsh(pk({}))", x_only_key))
1849 .unwrap_err();
1850 }
1851
1852 #[test]
1853 fn test_find_derivation_index_for_spk() {
1854 let secp = secp256k1::Secp256k1::verification_only();
1855 let descriptor = Descriptor::from_str("tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)").unwrap();
1856 let script_at_0_1 = ScriptBuf::from_hex(
1857 "5120a82f29944d65b86ae6b5e5cc75e294ead6c59391a1edc5e016e3498c67fc7bbb",
1858 )
1859 .unwrap();
1860 let expected_concrete = Descriptor::from_str(
1861 "tr(0283dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145)",
1862 )
1863 .unwrap();
1864
1865 assert_eq!(
1866 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..1),
1867 Ok(None)
1868 );
1869 assert_eq!(
1870 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..2),
1871 Ok(Some((1, expected_concrete.clone())))
1872 );
1873 assert_eq!(
1874 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..10),
1875 Ok(Some((1, expected_concrete)))
1876 );
1877 }
1878
1879 #[test]
1880 fn display_alternate() {
1881 let bare = StdDescriptor::from_str(
1882 "pk(020000000000000000000000000000000000000000000000000000000000000002)",
1883 )
1884 .unwrap();
1885 assert_eq!(
1886 format!("{}", bare),
1887 "pk(020000000000000000000000000000000000000000000000000000000000000002)#7yxkn84h",
1888 );
1889 assert_eq!(
1890 format!("{:#}", bare),
1891 "pk(020000000000000000000000000000000000000000000000000000000000000002)",
1892 );
1893
1894 let pkh = StdDescriptor::from_str(
1895 "pkh(020000000000000000000000000000000000000000000000000000000000000002)",
1896 )
1897 .unwrap();
1898 assert_eq!(
1899 format!("{}", pkh),
1900 "pkh(020000000000000000000000000000000000000000000000000000000000000002)#ma7nspkf",
1901 );
1902 assert_eq!(
1903 format!("{:#}", pkh),
1904 "pkh(020000000000000000000000000000000000000000000000000000000000000002)",
1905 );
1906
1907 let wpkh = StdDescriptor::from_str(
1908 "wpkh(020000000000000000000000000000000000000000000000000000000000000002)",
1909 )
1910 .unwrap();
1911 assert_eq!(
1912 format!("{}", wpkh),
1913 "wpkh(020000000000000000000000000000000000000000000000000000000000000002)#d3xz2xye",
1914 );
1915 assert_eq!(
1916 format!("{:#}", wpkh),
1917 "wpkh(020000000000000000000000000000000000000000000000000000000000000002)",
1918 );
1919
1920 let shwpkh = StdDescriptor::from_str(
1921 "sh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))",
1922 )
1923 .unwrap();
1924 assert_eq!(
1925 format!("{}", shwpkh),
1926 "sh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))#45zpjtet",
1927 );
1928 assert_eq!(
1929 format!("{:#}", shwpkh),
1930 "sh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))",
1931 );
1932
1933 let wsh = StdDescriptor::from_str("wsh(1)").unwrap();
1934 assert_eq!(format!("{}", wsh), "wsh(1)#mrg7xj7p");
1935 assert_eq!(format!("{:#}", wsh), "wsh(1)");
1936
1937 let sh = StdDescriptor::from_str("sh(1)").unwrap();
1938 assert_eq!(format!("{}", sh), "sh(1)#l8r75ggs");
1939 assert_eq!(format!("{:#}", sh), "sh(1)");
1940
1941 let shwsh = StdDescriptor::from_str("sh(wsh(1))").unwrap();
1942 assert_eq!(format!("{}", shwsh), "sh(wsh(1))#hcyfl07f");
1943 assert_eq!(format!("{:#}", shwsh), "sh(wsh(1))");
1944
1945 let tr = StdDescriptor::from_str(
1946 "tr(020000000000000000000000000000000000000000000000000000000000000002)",
1947 )
1948 .unwrap();
1949 assert_eq!(
1950 format!("{}", tr),
1951 "tr(020000000000000000000000000000000000000000000000000000000000000002)#8hc7wq5h",
1952 );
1953 assert_eq!(
1954 format!("{:#}", tr),
1955 "tr(020000000000000000000000000000000000000000000000000000000000000002)",
1956 );
1957 }
1958
1959 #[test]
1960 fn multipath_descriptors() {
1961 let desc = Descriptor::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<7';8h;20>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/<0;1;987>/*)))").unwrap();
1963 assert!(desc.is_multipath());
1964 assert_eq!(desc.into_single_descriptors().unwrap(), vec![
1965 Descriptor::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/7'/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/0/*)))").unwrap(),
1966 Descriptor::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/8h/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/1/*)))").unwrap(),
1967 Descriptor::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/20/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/987/*)))").unwrap()
1968 ]);
1969
1970 let desc = Descriptor::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<0;1>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap();
1972 assert!(desc.is_multipath());
1973 assert_eq!(desc.into_single_descriptors().unwrap(), vec![
1974 Descriptor::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/0/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap(),
1975 Descriptor::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/1/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap(),
1976 ]);
1977
1978 let notmulti_desc = Descriptor::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/4567/*)))").unwrap();
1980 assert!(!notmulti_desc.is_multipath());
1981 assert_eq!(
1982 notmulti_desc.clone().into_single_descriptors().unwrap(),
1983 vec![notmulti_desc]
1984 );
1985
1986 Descriptor::<DescriptorPublicKey>::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<0;1>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/<0;1;2;3;4>/*)))").unwrap_err();
1988 Descriptor::<DescriptorPublicKey>::from_str("wsh(andor(pk(tpubDEN9WSToTyy9ZQfaYqSKfmVqmq1VVLNtYfj3Vkqh67et57eJ5sTKZQBkHqSwPUsoSskJeaYnPttHe2VrkCsKA27kUaN9SDc5zhqeLzKa1rr/0'/<0;1;2;3>/*),older(10000),pk(tpubD8LYfn6njiA2inCoxwM7EuN3cuLVcaHAwLYeups13dpevd3nHLRdK9NdQksWXrhLQVxcUZRpnp5CkJ1FhE61WRAsHxDNAkvGkoQkAeWDYjV/8/<0;1;2>/*)))").unwrap_err();
1989 }
1990
1991 #[test]
1992 fn test_context_pks() {
1993 let comp_key = bellscoin::PublicKey::from_str(
1994 "02015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab",
1995 )
1996 .unwrap();
1997 let x_only_key = bellscoin::key::XOnlyPublicKey::from_str(
1998 "015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab",
1999 )
2000 .unwrap();
2001 let uncomp_key = bellscoin::PublicKey::from_str("04015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab0d46021e9e69ef061eb25eab41ae206187b2b05e829559df59d78319bd9267b4").unwrap();
2002
2003 type Desc = Descriptor<DescriptorPublicKey>;
2004
2005 Desc::from_str(&format!("sh(pk({}))", comp_key)).unwrap();
2007 Desc::from_str(&format!("sh(pk({}))", uncomp_key)).unwrap();
2008 Desc::from_str(&format!("sh(pk({}))", x_only_key)).unwrap_err();
2009
2010 Desc::from_str(&format!("pk({})", comp_key)).unwrap();
2012 Desc::from_str(&format!("pk({})", uncomp_key)).unwrap();
2013 Desc::from_str(&format!("pk({})", x_only_key)).unwrap_err();
2014
2015 Desc::from_str(&format!("pkh({})", comp_key)).unwrap();
2017 Desc::from_str(&format!("pkh({})", uncomp_key)).unwrap();
2018 Desc::from_str(&format!("pkh({})", x_only_key)).unwrap_err();
2019
2020 Desc::from_str(&format!("wpkh({})", comp_key)).unwrap();
2022 Desc::from_str(&format!("wpkh({})", uncomp_key)).unwrap_err();
2023 Desc::from_str(&format!("wpkh({})", x_only_key)).unwrap_err();
2024
2025 Desc::from_str(&format!("wsh(pk({}))", comp_key)).unwrap();
2027 Desc::from_str(&format!("wsh(pk({}))", uncomp_key)).unwrap_err();
2028 Desc::from_str(&format!("wsh(pk({}))", x_only_key)).unwrap_err();
2029
2030 Desc::from_str(&format!("tr({})", comp_key)).unwrap();
2032 Desc::from_str(&format!("tr({})", uncomp_key)).unwrap_err();
2033 Desc::from_str(&format!("tr({})", x_only_key)).unwrap();
2034
2035 Desc::from_str(&format!("tr({},pk({}))", x_only_key, comp_key)).unwrap();
2037 Desc::from_str(&format!("tr({},pk({}))", x_only_key, uncomp_key)).unwrap_err();
2038 Desc::from_str(&format!("tr({},pk({}))", x_only_key, x_only_key)).unwrap();
2039 }
2040}