1use core::fmt;
27use core::ops::Range;
28use core::str::{self, FromStr};
29
30use bitcoin::blockdata::witness::Witness;
31use bitcoin::hashes::{hash160, ripemd160, sha256};
32use bitcoin::util::address::WitnessVersion;
33use bitcoin::{self, secp256k1, Address, Network, Script, TxIn};
34use sync::Arc;
35
36use self::checksum::verify_checksum;
37use crate::miniscript::{Legacy, Miniscript, Segwitv0};
38use crate::prelude::*;
39use crate::{
40 expression, hash256, miniscript, BareCtx, Error, ForEachKey, MiniscriptKey, Satisfier,
41 ToPublicKey, TranslatePk, Translator,
42};
43
44mod bare;
45mod segwitv0;
46mod sh;
47mod sortedmulti;
48mod tr;
49
50pub use self::bare::{Bare, Pkh};
52pub use self::segwitv0::{Wpkh, Wsh, WshInner};
53pub use self::sh::{Sh, ShInner};
54pub use self::sortedmulti::SortedMultiVec;
55pub use self::tr::{TapTree, Tr};
56
57mod checksum;
58mod key;
59
60pub use self::key::{
61 ConversionError, DefiniteDescriptorKey, DescriptorKeyParseError, DescriptorPublicKey,
62 DescriptorSecretKey, DescriptorXKey, InnerXKey, SinglePriv, SinglePub, SinglePubKey, Wildcard,
63};
64
65pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey>;
72
73#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
75pub enum Descriptor<Pk: MiniscriptKey> {
76 Bare(Bare<Pk>),
78 Pkh(Pkh<Pk>),
80 Wpkh(Wpkh<Pk>),
82 Sh(Sh<Pk>),
84 Wsh(Wsh<Pk>),
86 Tr(Tr<Pk>),
88}
89
90impl<Pk: MiniscriptKey> From<Bare<Pk>> for Descriptor<Pk> {
91 #[inline]
92 fn from(inner: Bare<Pk>) -> Self {
93 Descriptor::Bare(inner)
94 }
95}
96
97impl<Pk: MiniscriptKey> From<Pkh<Pk>> for Descriptor<Pk> {
98 #[inline]
99 fn from(inner: Pkh<Pk>) -> Self {
100 Descriptor::Pkh(inner)
101 }
102}
103
104impl<Pk: MiniscriptKey> From<Wpkh<Pk>> for Descriptor<Pk> {
105 #[inline]
106 fn from(inner: Wpkh<Pk>) -> Self {
107 Descriptor::Wpkh(inner)
108 }
109}
110
111impl<Pk: MiniscriptKey> From<Sh<Pk>> for Descriptor<Pk> {
112 #[inline]
113 fn from(inner: Sh<Pk>) -> Self {
114 Descriptor::Sh(inner)
115 }
116}
117
118impl<Pk: MiniscriptKey> From<Wsh<Pk>> for Descriptor<Pk> {
119 #[inline]
120 fn from(inner: Wsh<Pk>) -> Self {
121 Descriptor::Wsh(inner)
122 }
123}
124
125impl<Pk: MiniscriptKey> From<Tr<Pk>> for Descriptor<Pk> {
126 #[inline]
127 fn from(inner: Tr<Pk>) -> Self {
128 Descriptor::Tr(inner)
129 }
130}
131
132#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
134pub enum DescriptorType {
135 Bare,
137 Sh,
139 Pkh,
141 Wpkh,
143 Wsh,
145 ShWsh,
147 ShWpkh,
149 ShSortedMulti,
151 WshSortedMulti,
153 ShWshSortedMulti,
155 Tr,
157}
158
159impl DescriptorType {
160 pub fn segwit_version(&self) -> Option<WitnessVersion> {
164 use self::DescriptorType::*;
165 match self {
166 Tr => Some(WitnessVersion::V1),
167 Wpkh | ShWpkh | Wsh | ShWsh | ShWshSortedMulti | WshSortedMulti => {
168 Some(WitnessVersion::V0)
169 }
170 Bare | Sh | Pkh | ShSortedMulti => None,
171 }
172 }
173}
174
175impl<Pk: MiniscriptKey> Descriptor<Pk> {
176 pub fn new_pk(pk: Pk) -> Self {
180 let ms: Miniscript<Pk, BareCtx> =
182 Miniscript::from_ast(miniscript::decode::Terminal::Check(Arc::new(
183 Miniscript::from_ast(miniscript::decode::Terminal::PkK(pk))
184 .expect("Type check cannot fail"),
185 )))
186 .expect("Type check cannot fail");
187 Descriptor::Bare(Bare::new(ms).expect("Context checks cannot fail for p2pk"))
188 }
189
190 pub fn new_pkh(pk: Pk) -> Self {
192 Descriptor::Pkh(Pkh::new(pk))
193 }
194
195 pub fn new_wpkh(pk: Pk) -> Result<Self, Error> {
198 Ok(Descriptor::Wpkh(Wpkh::new(pk)?))
199 }
200
201 pub fn new_sh_wpkh(pk: Pk) -> Result<Self, Error> {
204 Ok(Descriptor::Sh(Sh::new_wpkh(pk)?))
205 }
206
207 pub fn new_sh(ms: Miniscript<Pk, Legacy>) -> Result<Self, Error> {
213 Ok(Descriptor::Sh(Sh::new(ms)?))
214 }
215
216 pub fn new_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
220 Ok(Descriptor::Wsh(Wsh::new(ms)?))
221 }
222
223 pub fn new_sh_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
227 Ok(Descriptor::Sh(Sh::new_wsh(ms)?))
228 }
229
230 pub fn new_bare(ms: Miniscript<Pk, BareCtx>) -> Result<Self, Error> {
234 Ok(Descriptor::Bare(Bare::new(ms)?))
235 }
236
237 pub fn new_sh_with_wpkh(wpkh: Wpkh<Pk>) -> Self {
241 Descriptor::Sh(Sh::new_with_wpkh(wpkh))
242 }
243
244 pub fn new_sh_with_wsh(wsh: Wsh<Pk>) -> Self {
246 Descriptor::Sh(Sh::new_with_wsh(wsh))
247 }
248
249 pub fn new_sh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
255 Ok(Descriptor::Sh(Sh::new_sortedmulti(k, pks)?))
256 }
257
258 pub fn new_sh_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
262 Ok(Descriptor::Sh(Sh::new_wsh_sortedmulti(k, pks)?))
263 }
264
265 pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
268 Ok(Descriptor::Wsh(Wsh::new_sortedmulti(k, pks)?))
269 }
270
271 pub fn new_tr(key: Pk, script: Option<tr::TapTree<Pk>>) -> Result<Self, Error> {
274 Ok(Descriptor::Tr(Tr::new(key, script)?))
275 }
276
277 pub fn desc_type(&self) -> DescriptorType {
279 match *self {
280 Descriptor::Bare(ref _bare) => DescriptorType::Bare,
281 Descriptor::Pkh(ref _pkh) => DescriptorType::Pkh,
282 Descriptor::Wpkh(ref _wpkh) => DescriptorType::Wpkh,
283 Descriptor::Sh(ref sh) => match sh.as_inner() {
284 ShInner::Wsh(ref wsh) => match wsh.as_inner() {
285 WshInner::SortedMulti(ref _smv) => DescriptorType::ShWshSortedMulti,
286 WshInner::Ms(ref _ms) => DescriptorType::ShWsh,
287 },
288 ShInner::Wpkh(ref _wpkh) => DescriptorType::ShWpkh,
289 ShInner::SortedMulti(ref _smv) => DescriptorType::ShSortedMulti,
290 ShInner::Ms(ref _ms) => DescriptorType::Sh,
291 },
292 Descriptor::Wsh(ref wsh) => match wsh.as_inner() {
293 WshInner::SortedMulti(ref _smv) => DescriptorType::WshSortedMulti,
294 WshInner::Ms(ref _ms) => DescriptorType::Wsh,
295 },
296 Descriptor::Tr(ref _tr) => DescriptorType::Tr,
297 }
298 }
299
300 pub fn sanity_check(&self) -> Result<(), Error> {
310 match *self {
311 Descriptor::Bare(ref bare) => bare.sanity_check(),
312 Descriptor::Pkh(_) => Ok(()),
313 Descriptor::Wpkh(ref wpkh) => wpkh.sanity_check(),
314 Descriptor::Wsh(ref wsh) => wsh.sanity_check(),
315 Descriptor::Sh(ref sh) => sh.sanity_check(),
316 Descriptor::Tr(ref tr) => tr.sanity_check(),
317 }
318 }
319
320 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
330 let weight = match *self {
331 Descriptor::Bare(ref bare) => bare.max_satisfaction_weight()?,
332 Descriptor::Pkh(ref pkh) => pkh.max_satisfaction_weight(),
333 Descriptor::Wpkh(ref wpkh) => wpkh.max_satisfaction_weight(),
334 Descriptor::Wsh(ref wsh) => wsh.max_satisfaction_weight()?,
335 Descriptor::Sh(ref sh) => sh.max_satisfaction_weight()?,
336 Descriptor::Tr(ref tr) => tr.max_satisfaction_weight()?,
337 };
338 Ok(weight)
339 }
340}
341
342impl<Pk: MiniscriptKey + ToPublicKey> Descriptor<Pk> {
343 pub fn address(&self, network: Network) -> Result<Address, Error> {
350 match *self {
351 Descriptor::Bare(_) => Err(Error::BareDescriptorAddr),
352 Descriptor::Pkh(ref pkh) => Ok(pkh.address(network)),
353 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.address(network)),
354 Descriptor::Wsh(ref wsh) => Ok(wsh.address(network)),
355 Descriptor::Sh(ref sh) => Ok(sh.address(network)),
356 Descriptor::Tr(ref tr) => Ok(tr.address(network)),
357 }
358 }
359
360 pub fn script_pubkey(&self) -> Script {
362 match *self {
363 Descriptor::Bare(ref bare) => bare.script_pubkey(),
364 Descriptor::Pkh(ref pkh) => pkh.script_pubkey(),
365 Descriptor::Wpkh(ref wpkh) => wpkh.script_pubkey(),
366 Descriptor::Wsh(ref wsh) => wsh.script_pubkey(),
367 Descriptor::Sh(ref sh) => sh.script_pubkey(),
368 Descriptor::Tr(ref tr) => tr.script_pubkey(),
369 }
370 }
371
372 pub fn unsigned_script_sig(&self) -> Script {
380 match *self {
381 Descriptor::Bare(_) => Script::new(),
382 Descriptor::Pkh(_) => Script::new(),
383 Descriptor::Wpkh(_) => Script::new(),
384 Descriptor::Wsh(_) => Script::new(),
385 Descriptor::Sh(ref sh) => sh.unsigned_script_sig(),
386 Descriptor::Tr(_) => Script::new(),
387 }
388 }
389
390 pub fn explicit_script(&self) -> Result<Script, Error> {
397 match *self {
398 Descriptor::Bare(ref bare) => Ok(bare.script_pubkey()),
399 Descriptor::Pkh(ref pkh) => Ok(pkh.script_pubkey()),
400 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.script_pubkey()),
401 Descriptor::Wsh(ref wsh) => Ok(wsh.inner_script()),
402 Descriptor::Sh(ref sh) => Ok(sh.inner_script()),
403 Descriptor::Tr(_) => Err(Error::TrNoScriptCode),
404 }
405 }
406
407 pub fn script_code(&self) -> Result<Script, Error> {
415 match *self {
416 Descriptor::Bare(ref bare) => Ok(bare.ecdsa_sighash_script_code()),
417 Descriptor::Pkh(ref pkh) => Ok(pkh.ecdsa_sighash_script_code()),
418 Descriptor::Wpkh(ref wpkh) => Ok(wpkh.ecdsa_sighash_script_code()),
419 Descriptor::Wsh(ref wsh) => Ok(wsh.ecdsa_sighash_script_code()),
420 Descriptor::Sh(ref sh) => Ok(sh.ecdsa_sighash_script_code()),
421 Descriptor::Tr(_) => Err(Error::TrNoScriptCode),
422 }
423 }
424
425 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
429 where
430 S: Satisfier<Pk>,
431 {
432 match *self {
433 Descriptor::Bare(ref bare) => bare.get_satisfaction(satisfier),
434 Descriptor::Pkh(ref pkh) => pkh.get_satisfaction(satisfier),
435 Descriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction(satisfier),
436 Descriptor::Wsh(ref wsh) => wsh.get_satisfaction(satisfier),
437 Descriptor::Sh(ref sh) => sh.get_satisfaction(satisfier),
438 Descriptor::Tr(ref tr) => tr.get_satisfaction(satisfier),
439 }
440 }
441
442 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
446 where
447 S: Satisfier<Pk>,
448 {
449 match *self {
450 Descriptor::Bare(ref bare) => bare.get_satisfaction_mall(satisfier),
451 Descriptor::Pkh(ref pkh) => pkh.get_satisfaction_mall(satisfier),
452 Descriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction_mall(satisfier),
453 Descriptor::Wsh(ref wsh) => wsh.get_satisfaction_mall(satisfier),
454 Descriptor::Sh(ref sh) => sh.get_satisfaction_mall(satisfier),
455 Descriptor::Tr(ref tr) => tr.get_satisfaction_mall(satisfier),
456 }
457 }
458
459 pub fn satisfy<S>(&self, txin: &mut TxIn, satisfier: S) -> Result<(), Error>
463 where
464 S: Satisfier<Pk>,
465 {
466 let (witness, script_sig) = self.get_satisfaction(satisfier)?;
467 txin.witness = Witness::from_vec(witness);
468 txin.script_sig = script_sig;
469 Ok(())
470 }
471}
472
473impl<P, Q> TranslatePk<P, Q> for Descriptor<P>
474where
475 P: MiniscriptKey,
476 Q: MiniscriptKey,
477{
478 type Output = Descriptor<Q>;
479
480 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
482 where
483 T: Translator<P, Q, E>,
484 {
485 let desc = match *self {
486 Descriptor::Bare(ref bare) => Descriptor::Bare(bare.translate_pk(t)?),
487 Descriptor::Pkh(ref pk) => Descriptor::Pkh(pk.translate_pk(t)?),
488 Descriptor::Wpkh(ref pk) => Descriptor::Wpkh(pk.translate_pk(t)?),
489 Descriptor::Sh(ref sh) => Descriptor::Sh(sh.translate_pk(t)?),
490 Descriptor::Wsh(ref wsh) => Descriptor::Wsh(wsh.translate_pk(t)?),
491 Descriptor::Tr(ref tr) => Descriptor::Tr(tr.translate_pk(t)?),
492 };
493 Ok(desc)
494 }
495}
496
497impl<Pk: MiniscriptKey> ForEachKey<Pk> for Descriptor<Pk> {
498 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
499 where
500 Pk: 'a,
501 {
502 match *self {
503 Descriptor::Bare(ref bare) => bare.for_each_key(pred),
504 Descriptor::Pkh(ref pkh) => pkh.for_each_key(pred),
505 Descriptor::Wpkh(ref wpkh) => wpkh.for_each_key(pred),
506 Descriptor::Wsh(ref wsh) => wsh.for_each_key(pred),
507 Descriptor::Sh(ref sh) => sh.for_each_key(pred),
508 Descriptor::Tr(ref tr) => tr.for_each_key(pred),
509 }
510 }
511}
512
513impl Descriptor<DescriptorPublicKey> {
514 #[deprecated(note = "use has_wildcards instead")]
516 pub fn is_deriveable(&self) -> bool {
517 self.has_wildcard()
518 }
519
520 pub fn has_wildcard(&self) -> bool {
522 self.for_any_key(|key| key.has_wildcard())
523 }
524
525 pub fn at_derivation_index(&self, index: u32) -> Descriptor<DefiniteDescriptorKey> {
532 struct Derivator(u32);
533
534 impl Translator<DescriptorPublicKey, DefiniteDescriptorKey, ()> for Derivator {
535 fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DefiniteDescriptorKey, ()> {
536 Ok(pk.clone().at_derivation_index(self.0))
537 }
538
539 translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, ());
540 }
541 self.translate_pk(&mut Derivator(index))
542 .expect("BIP 32 key index substitution cannot fail")
543 }
544
545 #[deprecated(note = "use at_derivation_index instead")]
546 pub fn derive(&self, index: u32) -> Descriptor<DefiniteDescriptorKey> {
548 self.at_derivation_index(index)
549 }
550
551 pub fn derived_descriptor<C: secp256k1::Verification>(
578 &self,
579 secp: &secp256k1::Secp256k1<C>,
580 index: u32,
581 ) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
582 self.at_derivation_index(index).derived_descriptor(&secp)
583 }
584
585 pub fn parse_descriptor<C: secp256k1::Signing>(
590 secp: &secp256k1::Secp256k1<C>,
591 s: &str,
592 ) -> Result<(Descriptor<DescriptorPublicKey>, KeyMap), Error> {
593 fn parse_key<C: secp256k1::Signing>(
594 s: &String,
595 key_map: &mut KeyMap,
596 secp: &secp256k1::Secp256k1<C>,
597 ) -> Result<DescriptorPublicKey, Error> {
598 let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
599 Ok(sk) => (
600 sk.to_public(secp)
601 .map_err(|e| Error::Unexpected(e.to_string()))?,
602 Some(sk),
603 ),
604 Err(_) => (
605 DescriptorPublicKey::from_str(s)
606 .map_err(|e| Error::Unexpected(e.to_string()))?,
607 None,
608 ),
609 };
610
611 if let Some(secret_key) = secret_key {
612 key_map.insert(public_key.clone(), secret_key);
613 }
614
615 Ok(public_key)
616 }
617
618 let mut keymap_pk = KeyMapWrapper(HashMap::new(), secp);
619
620 struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
621
622 impl<'a, C: secp256k1::Signing> Translator<String, DescriptorPublicKey, Error>
623 for KeyMapWrapper<'a, C>
624 {
625 fn pk(&mut self, pk: &String) -> Result<DescriptorPublicKey, Error> {
626 parse_key(pk, &mut self.0, self.1)
627 }
628
629 fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Error> {
630 let hash =
631 sha256::Hash::from_str(sha256).map_err(|e| Error::Unexpected(e.to_string()))?;
632 Ok(hash)
633 }
634
635 fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, Error> {
636 let hash = hash256::Hash::from_str(hash256)
637 .map_err(|e| Error::Unexpected(e.to_string()))?;
638 Ok(hash)
639 }
640
641 fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, Error> {
642 let hash = ripemd160::Hash::from_str(ripemd160)
643 .map_err(|e| Error::Unexpected(e.to_string()))?;
644 Ok(hash)
645 }
646
647 fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, Error> {
648 let hash = hash160::Hash::from_str(hash160)
649 .map_err(|e| Error::Unexpected(e.to_string()))?;
650 Ok(hash)
651 }
652 }
653
654 let descriptor = Descriptor::<String>::from_str(s)?;
655 let descriptor = descriptor
656 .translate_pk(&mut keymap_pk)
657 .map_err(|e| Error::Unexpected(e.to_string()))?;
658
659 Ok((descriptor, keymap_pk.0))
660 }
661
662 pub fn to_string_with_secret(&self, key_map: &KeyMap) -> String {
664 struct KeyMapLookUp<'a>(&'a KeyMap);
665
666 impl<'a> Translator<DescriptorPublicKey, String, ()> for KeyMapLookUp<'a> {
667 fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, ()> {
668 key_to_string(pk, self.0)
669 }
670
671 fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
672 Ok(sha256.to_string())
673 }
674
675 fn hash256(&mut self, hash256: &hash256::Hash) -> Result<String, ()> {
676 Ok(hash256.to_string())
677 }
678
679 fn ripemd160(&mut self, ripemd160: &ripemd160::Hash) -> Result<String, ()> {
680 Ok(ripemd160.to_string())
681 }
682
683 fn hash160(&mut self, hash160: &hash160::Hash) -> Result<String, ()> {
684 Ok(hash160.to_string())
685 }
686 }
687
688 fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> Result<String, ()> {
689 Ok(match key_map.get(pk) {
690 Some(secret) => secret.to_string(),
691 None => pk.to_string(),
692 })
693 }
694
695 let descriptor = self
696 .translate_pk(&mut KeyMapLookUp(key_map))
697 .expect("Translation to string cannot fail");
698
699 descriptor.to_string()
700 }
701
702 pub fn find_derivation_index_for_spk<C: secp256k1::Verification>(
710 &self,
711 secp: &secp256k1::Secp256k1<C>,
712 script_pubkey: &Script,
713 range: Range<u32>,
714 ) -> Result<Option<(u32, Descriptor<bitcoin::PublicKey>)>, ConversionError> {
715 let range = if self.has_wildcard() { range } else { 0..1 };
716
717 for i in range {
718 let concrete = self.derived_descriptor(secp, i)?;
719 if &concrete.script_pubkey() == script_pubkey {
720 return Ok(Some((i, concrete)));
721 }
722 }
723
724 Ok(None)
725 }
726}
727
728impl Descriptor<DefiniteDescriptorKey> {
729 pub fn derived_descriptor<C: secp256k1::Verification>(
752 &self,
753 secp: &secp256k1::Secp256k1<C>,
754 ) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
755 struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
756
757 impl<'a, C: secp256k1::Verification>
758 Translator<DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError>
759 for Derivator<'a, C>
760 {
761 fn pk(
762 &mut self,
763 pk: &DefiniteDescriptorKey,
764 ) -> Result<bitcoin::PublicKey, ConversionError> {
765 pk.derive_public_key(&self.0)
766 }
767
768 translate_hash_clone!(DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError);
769 }
770
771 let derived = self.translate_pk(&mut Derivator(secp))?;
772 Ok(derived)
773 }
774}
775
776impl_from_tree!(
777 Descriptor<Pk>,
778 fn from_tree(top: &expression::Tree) -> Result<Descriptor<Pk>, Error> {
780 Ok(match (top.name, top.args.len() as u32) {
781 ("pkh", 1) => Descriptor::Pkh(Pkh::from_tree(top)?),
782 ("wpkh", 1) => Descriptor::Wpkh(Wpkh::from_tree(top)?),
783 ("sh", 1) => Descriptor::Sh(Sh::from_tree(top)?),
784 ("wsh", 1) => Descriptor::Wsh(Wsh::from_tree(top)?),
785 ("tr", _) => Descriptor::Tr(Tr::from_tree(top)?),
786 _ => Descriptor::Bare(Bare::from_tree(top)?),
787 })
788 }
789);
790
791impl_from_str!(
792 Descriptor<Pk>,
793 type Err = Error;,
794 fn from_str(s: &str) -> Result<Descriptor<Pk>, Error> {
795 if s.starts_with("tr(") {
799 Ok(Descriptor::Tr(Tr::from_str(s)?))
800 } else {
801 let desc_str = verify_checksum(s)?;
802 let top = expression::Tree::from_str(desc_str)?;
803 expression::FromTree::from_tree(&top)
804 }
805 }
806);
807
808impl<Pk: MiniscriptKey> fmt::Debug for Descriptor<Pk> {
809 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
810 match *self {
811 Descriptor::Bare(ref sub) => fmt::Debug::fmt(sub, f),
812 Descriptor::Pkh(ref pkh) => fmt::Debug::fmt(pkh, f),
813 Descriptor::Wpkh(ref wpkh) => fmt::Debug::fmt(wpkh, f),
814 Descriptor::Sh(ref sub) => fmt::Debug::fmt(sub, f),
815 Descriptor::Wsh(ref sub) => fmt::Debug::fmt(sub, f),
816 Descriptor::Tr(ref tr) => fmt::Debug::fmt(tr, f),
817 }
818 }
819}
820
821impl<Pk: MiniscriptKey> fmt::Display for Descriptor<Pk> {
822 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
823 match *self {
824 Descriptor::Bare(ref sub) => fmt::Display::fmt(sub, f),
825 Descriptor::Pkh(ref pkh) => fmt::Display::fmt(pkh, f),
826 Descriptor::Wpkh(ref wpkh) => fmt::Display::fmt(wpkh, f),
827 Descriptor::Sh(ref sub) => fmt::Display::fmt(sub, f),
828 Descriptor::Wsh(ref sub) => fmt::Display::fmt(sub, f),
829 Descriptor::Tr(ref tr) => fmt::Display::fmt(tr, f),
830 }
831 }
832}
833
834serde_string_impl_pk!(Descriptor, "a script descriptor");
835
836#[cfg(test)]
837mod tests {
838 use core::cmp;
839 use core::str::FromStr;
840
841 use bitcoin::blockdata::opcodes::all::{OP_CLTV, OP_CSV};
842 use bitcoin::blockdata::script::Instruction;
843 use bitcoin::blockdata::{opcodes, script};
844 use bitcoin::hashes::hex::{FromHex, ToHex};
845 use bitcoin::hashes::{hash160, sha256};
846 use bitcoin::util::bip32;
847 use bitcoin::{self, secp256k1, EcdsaSighashType, PublicKey, Sequence};
848
849 use super::checksum::desc_checksum;
850 use super::tr::Tr;
851 use super::*;
852 use crate::descriptor::key::Wildcard;
853 use crate::descriptor::{DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, SinglePub};
854 #[cfg(feature = "compiler")]
855 use crate::policy;
856 use crate::{hex_script, Descriptor, DummyKey, Error, Miniscript, Satisfier};
857
858 type StdDescriptor = Descriptor<PublicKey>;
859 const TEST_PK: &'static str =
860 "pk(020000000000000000000000000000000000000000000000000000000000000002)";
861
862 impl cmp::PartialEq for DescriptorSecretKey {
863 fn eq(&self, other: &Self) -> bool {
864 match (self, other) {
865 (&DescriptorSecretKey::Single(ref a), &DescriptorSecretKey::Single(ref b)) => {
866 a.origin == b.origin && a.key == b.key
867 }
868 (&DescriptorSecretKey::XPrv(ref a), &DescriptorSecretKey::XPrv(ref b)) => {
869 a.origin == b.origin
870 && a.xkey == b.xkey
871 && a.derivation_path == b.derivation_path
872 && a.wildcard == b.wildcard
873 }
874 _ => false,
875 }
876 }
877 }
878
879 fn roundtrip_descriptor(s: &str) {
880 let desc = Descriptor::<DummyKey>::from_str(&s).unwrap();
881 let output = desc.to_string();
882 let normalize_aliases = s.replace("c:pk_k(", "pk(").replace("c:pk_h(", "pkh(");
883 assert_eq!(
884 format!(
885 "{}#{}",
886 &normalize_aliases,
887 desc_checksum(&normalize_aliases).unwrap()
888 ),
889 output
890 );
891 }
892
893 #[test]
894 fn desc_rtt_tests() {
895 roundtrip_descriptor("c:pk_k()");
896 roundtrip_descriptor("wsh(pk())");
897 roundtrip_descriptor("wsh(c:pk_k())");
898 roundtrip_descriptor("c:pk_h()");
899 }
900 #[test]
901 fn parse_descriptor() {
902 StdDescriptor::from_str("(").unwrap_err();
903 StdDescriptor::from_str("(x()").unwrap_err();
904 StdDescriptor::from_str("(\u{7f}()3").unwrap_err();
905 StdDescriptor::from_str("pk()").unwrap_err();
906 StdDescriptor::from_str("nl:0").unwrap_err(); let compressed_pk = DummyKey.to_string();
908 assert_eq!(
909 StdDescriptor::from_str("sh(sortedmulti)")
910 .unwrap_err()
911 .to_string(),
912 "unexpected «no arguments given for sortedmulti»"
913 ); assert_eq!(
915 StdDescriptor::from_str(&format!("sh(sortedmulti(2,{}))", compressed_pk))
916 .unwrap_err()
917 .to_string(),
918 "unexpected «higher threshold than there were keys in sortedmulti»"
919 ); StdDescriptor::from_str(TEST_PK).unwrap();
922
923 let uncompressed_pk =
924 "0414fc03b8df87cd7b872996810db8458d61da8448e531569c8517b469a119d267be5645686309c6e6736dbd93940707cc9143d3cf29f1b877ff340e2cb2d259cf";
925
926 StdDescriptor::from_str(&format!("pk({})", uncompressed_pk)).unwrap();
928 StdDescriptor::from_str(&format!("pkh({})", uncompressed_pk)).unwrap();
929 StdDescriptor::from_str(&format!("sh(pk({}))", uncompressed_pk)).unwrap();
930 StdDescriptor::from_str(&format!("wpkh({})", uncompressed_pk)).unwrap_err();
931 StdDescriptor::from_str(&format!("sh(wpkh({}))", uncompressed_pk)).unwrap_err();
932 StdDescriptor::from_str(&format!("wsh(pk{})", uncompressed_pk)).unwrap_err();
933 StdDescriptor::from_str(&format!("sh(wsh(pk{}))", uncompressed_pk)).unwrap_err();
934 StdDescriptor::from_str(&format!(
935 "or_i(pk({}),pk({}))",
936 uncompressed_pk, uncompressed_pk
937 ))
938 .unwrap_err();
939 }
940
941 #[test]
942 pub fn script_pubkey() {
943 let bare = StdDescriptor::from_str(&format!(
944 "multi(1,020000000000000000000000000000000000000000000000000000000000000002)"
945 ))
946 .unwrap();
947 assert_eq!(
948 bare.script_pubkey(),
949 hex_script(
950 "512102000000000000000000000000000000000000000000000000000000000000000251ae"
951 )
952 );
953 assert_eq!(
954 bare.address(Network::Bitcoin).unwrap_err().to_string(),
955 "Bare descriptors don't have address"
956 );
957
958 let pk = StdDescriptor::from_str(TEST_PK).unwrap();
959 assert_eq!(
960 pk.script_pubkey(),
961 Script::from(vec![
962 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
964 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xac,
965 ])
966 );
967
968 let pkh = StdDescriptor::from_str(
969 "pkh(\
970 020000000000000000000000000000000000000000000000000000000000000002\
971 )",
972 )
973 .unwrap();
974 assert_eq!(
975 pkh.script_pubkey(),
976 script::Builder::new()
977 .push_opcode(opcodes::all::OP_DUP)
978 .push_opcode(opcodes::all::OP_HASH160)
979 .push_slice(
980 &hash160::Hash::from_hex("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap()
981 [..]
982 )
983 .push_opcode(opcodes::all::OP_EQUALVERIFY)
984 .push_opcode(opcodes::all::OP_CHECKSIG)
985 .into_script()
986 );
987 assert_eq!(
988 pkh.address(Network::Bitcoin,).unwrap().to_string(),
989 "1D7nRvrRgzCg9kYBwhPH3j3Gs6SmsRg3Wq"
990 );
991
992 let wpkh = StdDescriptor::from_str(
993 "wpkh(\
994 020000000000000000000000000000000000000000000000000000000000000002\
995 )",
996 )
997 .unwrap();
998 assert_eq!(
999 wpkh.script_pubkey(),
1000 script::Builder::new()
1001 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1002 .push_slice(
1003 &hash160::Hash::from_hex("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap()
1004 [..]
1005 )
1006 .into_script()
1007 );
1008 assert_eq!(
1009 wpkh.address(Network::Bitcoin,).unwrap().to_string(),
1010 "bc1qsn57m9drscflq5nl76z6ny52hck5w4x5wqd9yt"
1011 );
1012
1013 let shwpkh = StdDescriptor::from_str(
1014 "sh(wpkh(\
1015 020000000000000000000000000000000000000000000000000000000000000002\
1016 ))",
1017 )
1018 .unwrap();
1019 assert_eq!(
1020 shwpkh.script_pubkey(),
1021 script::Builder::new()
1022 .push_opcode(opcodes::all::OP_HASH160)
1023 .push_slice(
1024 &hash160::Hash::from_hex("f1c3b9a431134cb90a500ec06e0067cfa9b8bba7",).unwrap()
1025 [..]
1026 )
1027 .push_opcode(opcodes::all::OP_EQUAL)
1028 .into_script()
1029 );
1030 assert_eq!(
1031 shwpkh.address(Network::Bitcoin,).unwrap().to_string(),
1032 "3PjMEzoveVbvajcnDDuxcJhsuqPHgydQXq"
1033 );
1034
1035 let sh = StdDescriptor::from_str(
1036 "sh(c:pk_k(\
1037 020000000000000000000000000000000000000000000000000000000000000002\
1038 ))",
1039 )
1040 .unwrap();
1041 assert_eq!(
1042 sh.script_pubkey(),
1043 script::Builder::new()
1044 .push_opcode(opcodes::all::OP_HASH160)
1045 .push_slice(
1046 &hash160::Hash::from_hex("aa5282151694d3f2f32ace7d00ad38f927a33ac8",).unwrap()
1047 [..]
1048 )
1049 .push_opcode(opcodes::all::OP_EQUAL)
1050 .into_script()
1051 );
1052 assert_eq!(
1053 sh.address(Network::Bitcoin,).unwrap().to_string(),
1054 "3HDbdvM9CQ6ASnQFUkWw6Z4t3qNwMesJE9"
1055 );
1056
1057 let wsh = StdDescriptor::from_str(
1058 "wsh(c:pk_k(\
1059 020000000000000000000000000000000000000000000000000000000000000002\
1060 ))",
1061 )
1062 .unwrap();
1063 assert_eq!(
1064 wsh.script_pubkey(),
1065 script::Builder::new()
1066 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1067 .push_slice(
1068 &sha256::Hash::from_hex(
1069 "\
1070 f9379edc8983152dc781747830075bd5\
1071 3896e4b0ce5bff73777fd77d124ba085\
1072 "
1073 )
1074 .unwrap()[..]
1075 )
1076 .into_script()
1077 );
1078 assert_eq!(
1079 wsh.address(Network::Bitcoin,).unwrap().to_string(),
1080 "bc1qlymeahyfsv2jm3upw3urqp6m65ufde9seedl7umh0lth6yjt5zzsk33tv6"
1081 );
1082
1083 let shwsh = StdDescriptor::from_str(
1084 "sh(wsh(c:pk_k(\
1085 020000000000000000000000000000000000000000000000000000000000000002\
1086 )))",
1087 )
1088 .unwrap();
1089 assert_eq!(
1090 shwsh.script_pubkey(),
1091 script::Builder::new()
1092 .push_opcode(opcodes::all::OP_HASH160)
1093 .push_slice(
1094 &hash160::Hash::from_hex("4bec5d7feeed99e1d0a23fe32a4afe126a7ff07e",).unwrap()
1095 [..]
1096 )
1097 .push_opcode(opcodes::all::OP_EQUAL)
1098 .into_script()
1099 );
1100 assert_eq!(
1101 shwsh.address(Network::Bitcoin,).unwrap().to_string(),
1102 "38cTksiyPT2b1uGRVbVqHdDhW9vKs84N6Z"
1103 );
1104 }
1105
1106 #[test]
1107 fn satisfy() {
1108 let secp = secp256k1::Secp256k1::new();
1109 let sk =
1110 secp256k1::SecretKey::from_slice(&b"sally was a secret key, she said"[..]).unwrap();
1111 let pk = bitcoin::PublicKey::new(secp256k1::PublicKey::from_secret_key(&secp, &sk));
1112 let msg = secp256k1::Message::from_slice(&b"michael was a message, amusingly"[..])
1113 .expect("32 bytes");
1114 let sig = secp.sign_ecdsa(&msg, &sk);
1115 let mut sigser = sig.serialize_der().to_vec();
1116 sigser.push(0x01); struct SimpleSat {
1119 sig: secp256k1::ecdsa::Signature,
1120 pk: bitcoin::PublicKey,
1121 }
1122
1123 impl Satisfier<bitcoin::PublicKey> for SimpleSat {
1124 fn lookup_ecdsa_sig(&self, pk: &bitcoin::PublicKey) -> Option<bitcoin::EcdsaSig> {
1125 if *pk == self.pk {
1126 Some(bitcoin::EcdsaSig {
1127 sig: self.sig,
1128 hash_ty: bitcoin::EcdsaSighashType::All,
1129 })
1130 } else {
1131 None
1132 }
1133 }
1134 }
1135
1136 let satisfier = SimpleSat { sig, pk };
1137 let ms = ms_str!("c:pk_k({})", pk);
1138
1139 let mut txin = bitcoin::TxIn {
1140 previous_output: bitcoin::OutPoint::default(),
1141 script_sig: bitcoin::Script::new(),
1142 sequence: Sequence::from_height(100),
1143 witness: Witness::default(),
1144 };
1145 let bare = Descriptor::new_bare(ms.clone()).unwrap();
1146
1147 bare.satisfy(&mut txin, &satisfier).expect("satisfaction");
1148 assert_eq!(
1149 txin,
1150 bitcoin::TxIn {
1151 previous_output: bitcoin::OutPoint::default(),
1152 script_sig: script::Builder::new().push_slice(&sigser[..]).into_script(),
1153 sequence: Sequence::from_height(100),
1154 witness: Witness::default(),
1155 }
1156 );
1157 assert_eq!(bare.unsigned_script_sig(), bitcoin::Script::new());
1158
1159 let pkh = Descriptor::new_pkh(pk);
1160 pkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1161 assert_eq!(
1162 txin,
1163 bitcoin::TxIn {
1164 previous_output: bitcoin::OutPoint::default(),
1165 script_sig: script::Builder::new()
1166 .push_slice(&sigser[..])
1167 .push_key(&pk)
1168 .into_script(),
1169 sequence: Sequence::from_height(100),
1170 witness: Witness::default(),
1171 }
1172 );
1173 assert_eq!(pkh.unsigned_script_sig(), bitcoin::Script::new());
1174
1175 let wpkh = Descriptor::new_wpkh(pk).unwrap();
1176 wpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1177 assert_eq!(
1178 txin,
1179 bitcoin::TxIn {
1180 previous_output: bitcoin::OutPoint::default(),
1181 script_sig: bitcoin::Script::new(),
1182 sequence: Sequence::from_height(100),
1183 witness: Witness::from_vec(vec![sigser.clone(), pk.to_bytes(),]),
1184 }
1185 );
1186 assert_eq!(wpkh.unsigned_script_sig(), bitcoin::Script::new());
1187
1188 let shwpkh = Descriptor::new_sh_wpkh(pk).unwrap();
1189 shwpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1190 let redeem_script = script::Builder::new()
1191 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1192 .push_slice(
1193 &hash160::Hash::from_hex("d1b2a1faf62e73460af885c687dee3b7189cd8ab").unwrap()[..],
1194 )
1195 .into_script();
1196 assert_eq!(
1197 txin,
1198 bitcoin::TxIn {
1199 previous_output: bitcoin::OutPoint::default(),
1200 script_sig: script::Builder::new()
1201 .push_slice(&redeem_script[..])
1202 .into_script(),
1203 sequence: Sequence::from_height(100),
1204 witness: Witness::from_vec(vec![sigser.clone(), pk.to_bytes(),]),
1205 }
1206 );
1207 assert_eq!(
1208 shwpkh.unsigned_script_sig(),
1209 script::Builder::new()
1210 .push_slice(&redeem_script[..])
1211 .into_script()
1212 );
1213
1214 let ms = ms_str!("c:pk_k({})", pk);
1215 let sh = Descriptor::new_sh(ms.clone()).unwrap();
1216 sh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1217 assert_eq!(
1218 txin,
1219 bitcoin::TxIn {
1220 previous_output: bitcoin::OutPoint::default(),
1221 script_sig: script::Builder::new()
1222 .push_slice(&sigser[..])
1223 .push_slice(&ms.encode()[..])
1224 .into_script(),
1225 sequence: Sequence::from_height(100),
1226 witness: Witness::default(),
1227 }
1228 );
1229 assert_eq!(sh.unsigned_script_sig(), bitcoin::Script::new());
1230
1231 let ms = ms_str!("c:pk_k({})", pk);
1232
1233 let wsh = Descriptor::new_wsh(ms.clone()).unwrap();
1234 wsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1235 assert_eq!(
1236 txin,
1237 bitcoin::TxIn {
1238 previous_output: bitcoin::OutPoint::default(),
1239 script_sig: bitcoin::Script::new(),
1240 sequence: Sequence::from_height(100),
1241 witness: Witness::from_vec(vec![sigser.clone(), ms.encode().into_bytes(),]),
1242 }
1243 );
1244 assert_eq!(wsh.unsigned_script_sig(), bitcoin::Script::new());
1245
1246 let shwsh = Descriptor::new_sh_wsh(ms.clone()).unwrap();
1247 shwsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1248 assert_eq!(
1249 txin,
1250 bitcoin::TxIn {
1251 previous_output: bitcoin::OutPoint::default(),
1252 script_sig: script::Builder::new()
1253 .push_slice(&ms.encode().to_v0_p2wsh()[..])
1254 .into_script(),
1255 sequence: Sequence::from_height(100),
1256 witness: Witness::from_vec(vec![sigser.clone(), ms.encode().into_bytes(),]),
1257 }
1258 );
1259 assert_eq!(
1260 shwsh.unsigned_script_sig(),
1261 script::Builder::new()
1262 .push_slice(&ms.encode().to_v0_p2wsh()[..])
1263 .into_script()
1264 );
1265 }
1266
1267 #[test]
1268 fn after_is_cltv() {
1269 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("wsh(after(1000))").unwrap();
1270 let script = descriptor.explicit_script().unwrap();
1271
1272 let actual_instructions: Vec<_> = script.instructions().collect();
1273 let check = actual_instructions.last().unwrap();
1274
1275 assert_eq!(check, &Ok(Instruction::Op(OP_CLTV)))
1276 }
1277
1278 #[test]
1279 fn older_is_csv() {
1280 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("wsh(older(1000))").unwrap();
1281 let script = descriptor.explicit_script().unwrap();
1282
1283 let actual_instructions: Vec<_> = script.instructions().collect();
1284 let check = actual_instructions.last().unwrap();
1285
1286 assert_eq!(check, &Ok(Instruction::Op(OP_CSV)))
1287 }
1288
1289 #[test]
1290 fn tr_roundtrip_key() {
1291 let script = Tr::<DummyKey>::from_str("tr()").unwrap().to_string();
1292 assert_eq!(script, format!("tr()#x4ml3kxd"))
1293 }
1294
1295 #[test]
1296 fn tr_roundtrip_script() {
1297 let descriptor = Tr::<DummyKey>::from_str("tr(,{pk(),pk()})")
1298 .unwrap()
1299 .to_string();
1300
1301 assert_eq!(descriptor, "tr(,{pk(),pk()})#7dqr6v8r");
1302
1303 let descriptor = Descriptor::<String>::from_str("tr(A,{pk(B),pk(C)})")
1304 .unwrap()
1305 .to_string();
1306 assert_eq!(descriptor, "tr(A,{pk(B),pk(C)})#y0uc9t6x");
1307 }
1308
1309 #[test]
1310 fn tr_roundtrip_tree() {
1311 let p1 = "020000000000000000000000000000000000000000000000000000000000000001";
1312 let p2 = "020000000000000000000000000000000000000000000000000000000000000002";
1313 let p3 = "020000000000000000000000000000000000000000000000000000000000000003";
1314 let p4 = "020000000000000000000000000000000000000000000000000000000000000004";
1315 let p5 = "03f8551772d66557da28c1de858124f365a8eb30ce6ad79c10e0f4c546d0ab0f82";
1316 let descriptor = Tr::<PublicKey>::from_str(&format!(
1317 "tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})",
1318 p1, p2, p3, p4, p5
1319 ))
1320 .unwrap()
1321 .to_string();
1322
1323 assert_eq!(
1325 descriptor,
1326 format!(
1327 "tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})#tvu28c0s",
1328 p1, p2, p3, p4, p5
1329 )
1330 )
1331 }
1332
1333 #[test]
1334 fn tr_script_pubkey() {
1335 let key = Descriptor::<bitcoin::PublicKey>::from_str(
1336 "tr(02e20e746af365e86647826397ba1c0e0d5cb685752976fe2f326ab76bdc4d6ee9)",
1337 )
1338 .unwrap();
1339 assert_eq!(
1340 key.script_pubkey().to_hex(),
1341 "51209c19294f03757da3dc235a5960631e3c55751632f5889b06b7a053bdc0bcfbcb"
1342 )
1343 }
1344
1345 #[test]
1346 fn roundtrip_tests() {
1347 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("multi");
1348 assert_eq!(
1349 descriptor.unwrap_err().to_string(),
1350 "unexpected «no arguments given»"
1351 )
1352 }
1353
1354 #[test]
1355 fn empty_thresh() {
1356 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("thresh");
1357 assert_eq!(
1358 descriptor.unwrap_err().to_string(),
1359 "unexpected «no arguments given»"
1360 )
1361 }
1362
1363 #[test]
1364 fn witness_stack_for_andv_is_arranged_in_correct_order() {
1365 let a = bitcoin::PublicKey::from_str(
1367 "02937402303919b3a2ee5edd5009f4236f069bf75667b8e6ecf8e5464e20116a0e",
1368 )
1369 .unwrap();
1370 let sig_a = secp256k1::ecdsa::Signature::from_str("3045022100a7acc3719e9559a59d60d7b2837f9842df30e7edcd754e63227e6168cec72c5d022066c2feba4671c3d99ea75d9976b4da6c86968dbf3bab47b1061e7a1966b1778c").unwrap();
1371
1372 let b = bitcoin::PublicKey::from_str(
1373 "02eb64639a17f7334bb5a1a3aad857d6fec65faef439db3de72f85c88bc2906ad3",
1374 )
1375 .unwrap();
1376 let sig_b = secp256k1::ecdsa::Signature::from_str("3044022075b7b65a7e6cd386132c5883c9db15f9a849a0f32bc680e9986398879a57c276022056d94d12255a4424f51c700ac75122cb354895c9f2f88f0cbb47ba05c9c589ba").unwrap();
1377
1378 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str(&format!(
1379 "wsh(and_v(v:pk({A}),pk({B})))",
1380 A = a,
1381 B = b
1382 ))
1383 .unwrap();
1384
1385 let mut txin = bitcoin::TxIn {
1386 previous_output: bitcoin::OutPoint::default(),
1387 script_sig: bitcoin::Script::new(),
1388 sequence: Sequence::ZERO,
1389 witness: Witness::default(),
1390 };
1391 let satisfier = {
1392 let mut satisfier = HashMap::with_capacity(2);
1393
1394 satisfier.insert(
1395 a,
1396 bitcoin::EcdsaSig {
1397 sig: sig_a,
1398 hash_ty: EcdsaSighashType::All,
1399 },
1400 );
1401 satisfier.insert(
1402 b,
1403 bitcoin::EcdsaSig {
1404 sig: sig_b,
1405 hash_ty: EcdsaSighashType::All,
1406 },
1407 );
1408
1409 satisfier
1410 };
1411
1412 descriptor.satisfy(&mut txin, &satisfier).unwrap();
1414
1415 let wit = txin.witness.to_vec();
1417 let witness0 = &wit[0];
1418 let witness1 = &wit[1];
1419
1420 let sig0 = secp256k1::ecdsa::Signature::from_der(&witness0[..witness0.len() - 1]).unwrap();
1421 let sig1 = secp256k1::ecdsa::Signature::from_der(&witness1[..witness1.len() - 1]).unwrap();
1422
1423 assert_eq!(sig1, sig_a);
1428 assert_eq!(sig0, sig_b);
1429 }
1430
1431 #[test]
1432 fn test_scriptcode() {
1433 let descriptor = Descriptor::<PublicKey>::from_str(
1435 "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
1436 )
1437 .unwrap();
1438 assert_eq!(
1439 *descriptor.script_code().unwrap().as_bytes(),
1440 Vec::<u8>::from_hex("76a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac").unwrap()[..]
1441 );
1442
1443 let descriptor = Descriptor::<PublicKey>::from_str(
1445 "sh(wpkh(03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873))",
1446 )
1447 .unwrap();
1448 assert_eq!(
1449 *descriptor.script_code().unwrap().as_bytes(),
1450 Vec::<u8>::from_hex("76a91479091972186c449eb1ded22b78e40d009bdf008988ac").unwrap()[..]
1451 );
1452
1453 let descriptor = Descriptor::<PublicKey>::from_str(
1455 "wsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626))",
1456 )
1457 .unwrap();
1458 assert_eq!(
1459 *descriptor
1460 .script_code().unwrap()
1461 .as_bytes(),
1462 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae").unwrap()[..]
1463 );
1464
1465 let descriptor = Descriptor::<PublicKey>::from_str("sh(wsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626)))").unwrap();
1467 assert_eq!(
1468 *descriptor
1469 .script_code().unwrap()
1470 .as_bytes(),
1471 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae")
1472 .unwrap()[..]
1473 );
1474 }
1475
1476 #[test]
1477 fn parse_descriptor_key() {
1478 let key = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*";
1480 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1481 origin: Some((
1482 bip32::Fingerprint::from(&[0x78, 0x41, 0x2e, 0x3a][..]),
1483 (&[
1484 bip32::ChildNumber::from_hardened_idx(44).unwrap(),
1485 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1486 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1487 ][..])
1488 .into(),
1489 )),
1490 xkey: bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1491 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1492 wildcard: Wildcard::Unhardened,
1493 });
1494 assert_eq!(expected, key.parse().unwrap());
1495 assert_eq!(format!("{}", expected), key);
1496
1497 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1";
1499 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1500 origin: None,
1501 xkey: bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1502 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1503 wildcard: Wildcard::None,
1504 });
1505 assert_eq!(expected, key.parse().unwrap());
1506 assert_eq!(format!("{}", expected), key);
1507
1508 let key = "tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed/1";
1510 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1511 origin: None,
1512 xkey: bip32::ExtendedPubKey::from_str("tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed").unwrap(),
1513 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1514 wildcard: Wildcard::None,
1515 });
1516 assert_eq!(expected, key.parse().unwrap());
1517 assert_eq!(format!("{}", expected), key);
1518
1519 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
1521 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1522 origin: None,
1523 xkey: bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1524 derivation_path: bip32::DerivationPath::from(&[][..]),
1525 wildcard: Wildcard::None,
1526 });
1527 assert_eq!(expected, key.parse().unwrap());
1528 assert_eq!(format!("{}", expected), key);
1529
1530 let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
1532 let expected = DescriptorPublicKey::Single(SinglePub {
1533 key: SinglePubKey::FullKey(
1534 bitcoin::PublicKey::from_str(
1535 "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8",
1536 )
1537 .unwrap(),
1538 ),
1539 origin: None,
1540 });
1541 assert_eq!(expected, key.parse().unwrap());
1542 assert_eq!(format!("{}", expected), key);
1543
1544 let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a";
1546 let expected = DescriptorPublicKey::Single(SinglePub {
1547 key: SinglePubKey::FullKey(bitcoin::PublicKey::from_str(
1548 "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a",
1549 )
1550 .unwrap()),
1551 origin: None,
1552 });
1553 assert_eq!(expected, key.parse().unwrap());
1554 assert_eq!(format!("{}", expected), key);
1555
1556 let desc =
1558 "[78412e3a/0'/42/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8";
1559 let expected = DescriptorPublicKey::Single(SinglePub {
1560 key: SinglePubKey::FullKey(
1561 bitcoin::PublicKey::from_str(
1562 "0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8",
1563 )
1564 .unwrap(),
1565 ),
1566 origin: Some((
1567 bip32::Fingerprint::from(&[0x78, 0x41, 0x2e, 0x3a][..]),
1568 (&[
1569 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1570 bip32::ChildNumber::from_normal_idx(42).unwrap(),
1571 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1572 ][..])
1573 .into(),
1574 )),
1575 });
1576 assert_eq!(expected, desc.parse().expect("Parsing desc"));
1577 assert_eq!(format!("{}", expected), desc);
1578 }
1579
1580 #[test]
1581 fn test_sortedmulti() {
1582 fn _test_sortedmulti(raw_desc_one: &str, raw_desc_two: &str, raw_addr_expected: &str) {
1583 let secp_ctx = secp256k1::Secp256k1::verification_only();
1584 let index = 5;
1585
1586 let desc_one = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_one).unwrap();
1588 let desc_two = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_two).unwrap();
1589
1590 assert_eq!(desc_one.to_string(), raw_desc_one);
1592 assert_eq!(desc_two.to_string(), raw_desc_two);
1593
1594 let addr_one = desc_one
1596 .at_derivation_index(index)
1597 .derived_descriptor(&secp_ctx)
1598 .unwrap()
1599 .address(bitcoin::Network::Bitcoin)
1600 .unwrap();
1601 let addr_two = desc_two
1602 .at_derivation_index(index)
1603 .derived_descriptor(&secp_ctx)
1604 .unwrap()
1605 .address(bitcoin::Network::Bitcoin)
1606 .unwrap();
1607 let addr_expected = bitcoin::Address::from_str(raw_addr_expected).unwrap();
1608 assert_eq!(addr_one, addr_expected);
1609 assert_eq!(addr_two, addr_expected);
1610 }
1611
1612 _test_sortedmulti(
1614 "sh(sortedmulti(1,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352))#uetvewm2",
1615 "sh(sortedmulti(1,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))#7l8smyg9",
1616 "3JZJNxvDKe6Y55ZaF5223XHwfF2eoMNnoV",
1617 );
1618
1619 _test_sortedmulti(
1621 "wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH))#7etm7zk7",
1622 "wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB))#ppmeel9k",
1623 "bc1qpq2cfgz5lktxzr5zqv7nrzz46hsvq3492ump9pz8rzcl8wqtwqcspx5y6a",
1624 );
1625
1626 _test_sortedmulti(
1628 "sh(wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*)))#u60cee0u",
1629 "sh(wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*)))#75dkf44w",
1630 "325zcVBN5o2eqqqtGwPjmtDd8dJRyYP82s",
1631 );
1632 }
1633
1634 #[test]
1635 fn test_parse_descriptor() {
1636 let secp = &secp256k1::Secp256k1::signing_only();
1637 let (descriptor, key_map) = Descriptor::parse_descriptor(secp, "wpkh(tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/44'/0'/0'/0/*)").unwrap();
1638 assert_eq!(descriptor.to_string(), "wpkh([2cbe2a6d/44'/0'/0']tpubDCvNhURocXGZsLNqWcqD3syHTqPXrMSTwi8feKVwAcpi29oYKsDD3Vex7x2TDneKMVN23RbLprfxB69v94iYqdaYHsVz3kPR37NQXeqouVz/0/*)#nhdxg96s");
1639 assert_eq!(key_map.len(), 1);
1640
1641 macro_rules! check_invalid_checksum {
1643 ($secp: ident,$($desc: expr),*) => {
1644 $(
1645 match Descriptor::parse_descriptor($secp, $desc) {
1646 Err(Error::BadDescriptor(_)) => {},
1647 Err(e) => panic!("Expected bad checksum for {}, got '{}'", $desc, e),
1648 _ => panic!("Invalid checksum treated as valid: {}", $desc),
1649 };
1650 )*
1651 };
1652 }
1653 check_invalid_checksum!(secp,
1654 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#",
1655 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#",
1656 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfyq",
1657 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq",
1658 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf",
1659 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5",
1660 "sh(multi(3,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy",
1661 "sh(multi(3,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t",
1662 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjq09x4t",
1663 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))##ggssrxfy",
1664 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))##tjq09x4t"
1665 );
1666
1667 Descriptor::parse_descriptor(&secp, "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy").expect("Valid descriptor with checksum");
1668 Descriptor::parse_descriptor(&secp, "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t").expect("Valid descriptor with checksum");
1669 }
1670
1671 #[test]
1672 #[cfg(feature = "compiler")]
1673 fn parse_and_derive() {
1674 let descriptor_str = "thresh(2,\
1675pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*),\
1676pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
1677pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
1678 let policy: policy::concrete::Policy<DescriptorPublicKey> = descriptor_str.parse().unwrap();
1679 let descriptor = Descriptor::new_sh(policy.compile().unwrap()).unwrap();
1680 let definite_descriptor = descriptor.at_derivation_index(42);
1681
1682 let res_descriptor_str = "thresh(2,\
1683pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42),\
1684pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
1685pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
1686 let res_policy: policy::concrete::Policy<DescriptorPublicKey> =
1687 res_descriptor_str.parse().unwrap();
1688 let res_descriptor = Descriptor::new_sh(res_policy.compile().unwrap()).unwrap();
1689
1690 assert_eq!(res_descriptor.to_string(), definite_descriptor.to_string());
1691 }
1692
1693 #[test]
1694 fn parse_with_secrets() {
1695 let secp = &secp256k1::Secp256k1::signing_only();
1696 let descriptor_str = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)#v20xlvm9";
1697 let (descriptor, keymap) =
1698 Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, descriptor_str).unwrap();
1699
1700 let expected = "wpkh([a12b02f4/44'/0'/0']xpub6BzhLAQUDcBUfHRQHZxDF2AbcJqp4Kaeq6bzJpXrjrWuK26ymTFwkEFbxPra2bJ7yeZKbDjfDeFwxe93JMqpo5SsPJH6dZdvV9kMzJkAZ69/0/*)#u37l7u8u";
1701 assert_eq!(expected, descriptor.to_string());
1702 assert_eq!(keymap.len(), 1);
1703
1704 assert_eq!(descriptor_str, descriptor.to_string_with_secret(&keymap));
1706 }
1707
1708 #[test]
1709 fn checksum_for_nested_sh() {
1710 let descriptor_str = "sh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))";
1711 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
1712 assert_eq!(descriptor.to_string(), "sh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))#tjp2zm88");
1713
1714 let descriptor_str = "sh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))";
1715 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
1716 assert_eq!(descriptor.to_string(), "sh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))#6c6hwr22");
1717 }
1718
1719 #[test]
1720 fn test_xonly_keys() {
1721 let comp_key = "0308c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
1722 let x_only_key = "08c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
1723
1724 Descriptor::<DescriptorPublicKey>::from_str(&format!("tr({})", comp_key)).unwrap();
1726 Descriptor::<DescriptorPublicKey>::from_str(&format!("tr({})", x_only_key)).unwrap();
1727
1728 Descriptor::<DescriptorPublicKey>::from_str(&format!("wsh(pk({}))", comp_key)).unwrap();
1730 Descriptor::<DescriptorPublicKey>::from_str(&format!("wsh(pk({}))", x_only_key))
1731 .unwrap_err();
1732 }
1733
1734 #[test]
1735 fn test_find_derivation_index_for_spk() {
1736 let secp = secp256k1::Secp256k1::verification_only();
1737 let descriptor = Descriptor::from_str("tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)").unwrap();
1738 let script_at_0_1 = Script::from_str(
1739 "5120a82f29944d65b86ae6b5e5cc75e294ead6c59391a1edc5e016e3498c67fc7bbb",
1740 )
1741 .unwrap();
1742 let expected_concrete = Descriptor::from_str(
1743 "tr(0283dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145)",
1744 )
1745 .unwrap();
1746
1747 assert_eq!(
1748 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..1),
1749 Ok(None)
1750 );
1751 assert_eq!(
1752 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..2),
1753 Ok(Some((1, expected_concrete.clone())))
1754 );
1755 assert_eq!(
1756 descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..10),
1757 Ok(Some((1, expected_concrete)))
1758 );
1759 }
1760
1761 #[test]
1762 fn display_alternate() {
1763 let bare = StdDescriptor::from_str(
1764 "pk(020000000000000000000000000000000000000000000000000000000000000002)",
1765 )
1766 .unwrap();
1767 assert_eq!(
1768 format!("{}", bare),
1769 "pk(020000000000000000000000000000000000000000000000000000000000000002)#7yxkn84h",
1770 );
1771 assert_eq!(
1772 format!("{:#}", bare),
1773 "pk(020000000000000000000000000000000000000000000000000000000000000002)",
1774 );
1775
1776 let pkh = StdDescriptor::from_str(
1777 "pkh(020000000000000000000000000000000000000000000000000000000000000002)",
1778 )
1779 .unwrap();
1780 assert_eq!(
1781 format!("{}", pkh),
1782 "pkh(020000000000000000000000000000000000000000000000000000000000000002)#ma7nspkf",
1783 );
1784 assert_eq!(
1785 format!("{:#}", pkh),
1786 "pkh(020000000000000000000000000000000000000000000000000000000000000002)",
1787 );
1788
1789 let wpkh = StdDescriptor::from_str(
1790 "wpkh(020000000000000000000000000000000000000000000000000000000000000002)",
1791 )
1792 .unwrap();
1793 assert_eq!(
1794 format!("{}", wpkh),
1795 "wpkh(020000000000000000000000000000000000000000000000000000000000000002)#d3xz2xye",
1796 );
1797 assert_eq!(
1798 format!("{:#}", wpkh),
1799 "wpkh(020000000000000000000000000000000000000000000000000000000000000002)",
1800 );
1801
1802 let shwpkh = StdDescriptor::from_str(
1803 "sh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))",
1804 )
1805 .unwrap();
1806 assert_eq!(
1807 format!("{}", shwpkh),
1808 "sh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))#45zpjtet",
1809 );
1810 assert_eq!(
1811 format!("{:#}", shwpkh),
1812 "sh(wpkh(020000000000000000000000000000000000000000000000000000000000000002))",
1813 );
1814
1815 let wsh = StdDescriptor::from_str("wsh(1)").unwrap();
1816 assert_eq!(format!("{}", wsh), "wsh(1)#mrg7xj7p");
1817 assert_eq!(format!("{:#}", wsh), "wsh(1)");
1818
1819 let sh = StdDescriptor::from_str("sh(1)").unwrap();
1820 assert_eq!(format!("{}", sh), "sh(1)#l8r75ggs");
1821 assert_eq!(format!("{:#}", sh), "sh(1)");
1822
1823 let shwsh = StdDescriptor::from_str("sh(wsh(1))").unwrap();
1824 assert_eq!(format!("{}", shwsh), "sh(wsh(1))#hcyfl07f");
1825 assert_eq!(format!("{:#}", shwsh), "sh(wsh(1))");
1826
1827 let tr = StdDescriptor::from_str(
1828 "tr(020000000000000000000000000000000000000000000000000000000000000002)",
1829 )
1830 .unwrap();
1831 assert_eq!(
1832 format!("{}", tr),
1833 "tr(020000000000000000000000000000000000000000000000000000000000000002)#8hc7wq5h",
1834 );
1835 assert_eq!(
1836 format!("{:#}", tr),
1837 "tr(020000000000000000000000000000000000000000000000000000000000000002)",
1838 );
1839 }
1840}