1use std::{collections::HashMap, sync::Arc};
27use std::{
28 fmt,
29 str::{self, FromStr},
30};
31
32use bitcoin::blockdata::witness::Witness;
33use bitcoin::{self, secp256k1, Script};
34
35use self::checksum::verify_checksum;
36use expression;
37use miniscript;
38use miniscript::{Legacy, Miniscript, Segwitv0};
39use {
40 BareCtx, Error, ForEach, ForEachKey, MiniscriptKey, Satisfier, ToPublicKey, TranslatePk,
41 TranslatePk2,
42};
43
44pub(crate) mod pretaproot;
46
47mod bare;
48mod segwitv0;
49mod sh;
50mod sortedmulti;
51mod tr;
52
53pub use self::bare::{Bare, Pkh};
55pub use self::segwitv0::{Wpkh, Wsh, WshInner};
56pub use self::sh::{Sh, ShInner};
57pub use self::sortedmulti::SortedMultiVec;
58pub use self::tr::{TapTree, Tr};
59
60mod checksum;
61mod key;
62
63pub use self::key::{
64 ConversionError, DescriptorKeyParseError, DescriptorPublicKey, DescriptorSecretKey,
65 DescriptorSinglePriv, DescriptorSinglePub, DescriptorXKey, InnerXKey, SinglePubKey, Wildcard,
66};
67
68pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey>;
75
76pub trait DescriptorTrait<Pk: MiniscriptKey> {
83 fn sanity_check(&self) -> Result<(), Error>;
92
93 fn address(&self, network: bitcoin::Network) -> Result<bitcoin::Address, Error>
98 where
99 Pk: ToPublicKey;
100
101 fn script_pubkey(&self) -> Script
103 where
104 Pk: ToPublicKey;
105
106 fn unsigned_script_sig(&self) -> Script
115 where
116 Pk: ToPublicKey;
117
118 fn explicit_script(&self) -> Result<Script, Error>
124 where
125 Pk: ToPublicKey;
126
127 fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
131 where
132 Pk: ToPublicKey,
133 S: Satisfier<Pk>;
134
135 fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
139 where
140 Pk: ToPublicKey,
141 S: Satisfier<Pk>;
142
143 fn satisfy<S>(&self, txin: &mut bitcoin::TxIn, satisfier: S) -> Result<(), Error>
147 where
148 Pk: ToPublicKey,
149 S: Satisfier<Pk>,
150 {
151 let (witness, script_sig) = self.get_satisfaction(satisfier)?;
153 txin.witness = Witness::from_vec(witness);
154 txin.script_sig = script_sig;
155 Ok(())
156 }
157
158 fn max_satisfaction_weight(&self) -> Result<usize, Error>;
164
165 fn script_code(&self) -> Result<Script, Error>
172 where
173 Pk: ToPublicKey;
174}
175
176#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
178pub enum Descriptor<Pk: MiniscriptKey> {
179 Bare(Bare<Pk>),
181 Pkh(Pkh<Pk>),
183 Wpkh(Wpkh<Pk>),
185 Sh(Sh<Pk>),
187 Wsh(Wsh<Pk>),
189 Tr(Tr<Pk>),
191}
192
193impl<Pk: MiniscriptKey> From<Bare<Pk>> for Descriptor<Pk> {
194 #[inline]
195 fn from(inner: Bare<Pk>) -> Self {
196 Descriptor::Bare(inner)
197 }
198}
199
200impl<Pk: MiniscriptKey> From<Pkh<Pk>> for Descriptor<Pk> {
201 #[inline]
202 fn from(inner: Pkh<Pk>) -> Self {
203 Descriptor::Pkh(inner)
204 }
205}
206
207impl<Pk: MiniscriptKey> From<Wpkh<Pk>> for Descriptor<Pk> {
208 #[inline]
209 fn from(inner: Wpkh<Pk>) -> Self {
210 Descriptor::Wpkh(inner)
211 }
212}
213
214impl<Pk: MiniscriptKey> From<Sh<Pk>> for Descriptor<Pk> {
215 #[inline]
216 fn from(inner: Sh<Pk>) -> Self {
217 Descriptor::Sh(inner)
218 }
219}
220
221impl<Pk: MiniscriptKey> From<Wsh<Pk>> for Descriptor<Pk> {
222 #[inline]
223 fn from(inner: Wsh<Pk>) -> Self {
224 Descriptor::Wsh(inner)
225 }
226}
227
228impl<Pk: MiniscriptKey> From<Tr<Pk>> for Descriptor<Pk> {
229 #[inline]
230 fn from(inner: Tr<Pk>) -> Self {
231 Descriptor::Tr(inner)
232 }
233}
234
235#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
237pub enum DescriptorType {
238 Bare,
240 Sh,
242 Pkh,
244 Wpkh,
246 Wsh,
248 ShWsh,
250 ShWpkh,
252 ShSortedMulti,
254 WshSortedMulti,
256 ShWshSortedMulti,
258 Tr,
260}
261
262impl<Pk: MiniscriptKey> Descriptor<Pk> {
263 pub fn new_pk(pk: Pk) -> Self {
267 let ms: Miniscript<Pk, BareCtx> =
269 Miniscript::from_ast(miniscript::decode::Terminal::Check(Arc::new(
270 Miniscript::from_ast(miniscript::decode::Terminal::PkK(pk))
271 .expect("Type check cannot fail"),
272 )))
273 .expect("Type check cannot fail");
274 Descriptor::Bare(Bare::new(ms).expect("Context checks cannot fail for p2pk"))
275 }
276
277 pub fn new_pkh(pk: Pk) -> Self {
279 Descriptor::Pkh(Pkh::new(pk))
280 }
281
282 pub fn new_wpkh(pk: Pk) -> Result<Self, Error> {
285 Ok(Descriptor::Wpkh(Wpkh::new(pk)?))
286 }
287
288 pub fn new_sh_wpkh(pk: Pk) -> Result<Self, Error> {
291 Ok(Descriptor::Sh(Sh::new_wpkh(pk)?))
292 }
293
294 pub fn new_sh(ms: Miniscript<Pk, Legacy>) -> Result<Self, Error> {
300 Ok(Descriptor::Sh(Sh::new(ms)?))
301 }
302
303 pub fn new_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
307 Ok(Descriptor::Wsh(Wsh::new(ms)?))
308 }
309
310 pub fn new_sh_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
314 Ok(Descriptor::Sh(Sh::new_wsh(ms)?))
315 }
316
317 pub fn new_bare(ms: Miniscript<Pk, BareCtx>) -> Result<Self, Error> {
321 Ok(Descriptor::Bare(Bare::new(ms)?))
322 }
323
324 pub fn new_sh_with_wpkh(wpkh: Wpkh<Pk>) -> Self {
328 Descriptor::Sh(Sh::new_with_wpkh(wpkh))
329 }
330
331 pub fn new_sh_with_wsh(wsh: Wsh<Pk>) -> Self {
333 Descriptor::Sh(Sh::new_with_wsh(wsh))
334 }
335
336 pub fn new_sh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
342 Ok(Descriptor::Sh(Sh::new_sortedmulti(k, pks)?))
343 }
344
345 pub fn new_sh_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
349 Ok(Descriptor::Sh(Sh::new_wsh_sortedmulti(k, pks)?))
350 }
351
352 pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
355 Ok(Descriptor::Wsh(Wsh::new_sortedmulti(k, pks)?))
356 }
357
358 pub fn new_tr(key: Pk, script: Option<tr::TapTree<Pk>>) -> Result<Self, Error> {
361 Ok(Descriptor::Tr(Tr::new(key, script)?))
362 }
363
364 pub fn desc_type(&self) -> DescriptorType {
366 match *self {
367 Descriptor::Bare(ref _bare) => DescriptorType::Bare,
368 Descriptor::Pkh(ref _pkh) => DescriptorType::Pkh,
369 Descriptor::Wpkh(ref _wpkh) => DescriptorType::Wpkh,
370 Descriptor::Sh(ref sh) => match sh.as_inner() {
371 ShInner::Wsh(ref wsh) => match wsh.as_inner() {
372 WshInner::SortedMulti(ref _smv) => DescriptorType::ShWshSortedMulti,
373 WshInner::Ms(ref _ms) => DescriptorType::ShWsh,
374 },
375 ShInner::Wpkh(ref _wpkh) => DescriptorType::ShWpkh,
376 ShInner::SortedMulti(ref _smv) => DescriptorType::ShSortedMulti,
377 ShInner::Ms(ref _ms) => DescriptorType::Sh,
378 },
379 Descriptor::Wsh(ref wsh) => match wsh.as_inner() {
380 WshInner::SortedMulti(ref _smv) => DescriptorType::WshSortedMulti,
381 WshInner::Ms(ref _ms) => DescriptorType::Wsh,
382 },
383 Descriptor::Tr(ref _tr) => DescriptorType::Tr,
384 }
385 }
386
387 pub fn into_pre_taproot_desc(self) -> Result<pretaproot::PreTaprootDescriptor<Pk>, Self> {
415 match self {
416 Descriptor::Bare(bare) => Ok(pretaproot::PreTaprootDescriptor::Bare(bare)),
417 Descriptor::Pkh(pkh) => Ok(pretaproot::PreTaprootDescriptor::Pkh(pkh)),
418 Descriptor::Wpkh(wpkh) => Ok(pretaproot::PreTaprootDescriptor::Wpkh(wpkh)),
419 Descriptor::Sh(sh) => Ok(pretaproot::PreTaprootDescriptor::Sh(sh)),
420 Descriptor::Wsh(wsh) => Ok(pretaproot::PreTaprootDescriptor::Wsh(wsh)),
421 Descriptor::Tr(tr) => Err(Descriptor::Tr(tr)),
422 }
423 }
424}
425
426impl<P: MiniscriptKey, Q: MiniscriptKey> TranslatePk<P, Q> for Descriptor<P> {
427 type Output = Descriptor<Q>;
428 fn translate_pk<Fpk, Fpkh, E>(
433 &self,
434 mut translatefpk: Fpk,
435 mut translatefpkh: Fpkh,
436 ) -> Result<Descriptor<Q>, E>
437 where
438 Fpk: FnMut(&P) -> Result<Q, E>,
439 Fpkh: FnMut(&P::Hash) -> Result<Q::Hash, E>,
440 Q: MiniscriptKey,
441 {
442 let desc = match *self {
443 Descriptor::Bare(ref bare) => {
444 Descriptor::Bare(bare.translate_pk(&mut translatefpk, &mut translatefpkh)?)
445 }
446 Descriptor::Pkh(ref pk) => {
447 Descriptor::Pkh(pk.translate_pk(&mut translatefpk, &mut translatefpkh)?)
448 }
449 Descriptor::Wpkh(ref pk) => {
450 Descriptor::Wpkh(pk.translate_pk(&mut translatefpk, &mut translatefpkh)?)
451 }
452 Descriptor::Sh(ref sh) => {
453 Descriptor::Sh(sh.translate_pk(&mut translatefpk, &mut translatefpkh)?)
454 }
455 Descriptor::Wsh(ref wsh) => {
456 Descriptor::Wsh(wsh.translate_pk(&mut translatefpk, &mut translatefpkh)?)
457 }
458 Descriptor::Tr(ref tr) => {
459 Descriptor::Tr(tr.translate_pk(&mut translatefpk, &mut translatefpkh)?)
460 }
461 };
462 Ok(desc)
463 }
464}
465
466impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Descriptor<Pk> {
467 fn sanity_check(&self) -> Result<(), Error> {
476 match *self {
477 Descriptor::Bare(ref bare) => bare.sanity_check(),
478 Descriptor::Pkh(ref pkh) => pkh.sanity_check(),
479 Descriptor::Wpkh(ref wpkh) => wpkh.sanity_check(),
480 Descriptor::Wsh(ref wsh) => wsh.sanity_check(),
481 Descriptor::Sh(ref sh) => sh.sanity_check(),
482 Descriptor::Tr(ref tr) => tr.sanity_check(),
483 }
484 }
485 fn address(&self, network: bitcoin::Network) -> Result<bitcoin::Address, Error>
487 where
488 Pk: ToPublicKey,
489 {
490 match *self {
491 Descriptor::Bare(ref bare) => bare.address(network),
492 Descriptor::Pkh(ref pkh) => pkh.address(network),
493 Descriptor::Wpkh(ref wpkh) => wpkh.address(network),
494 Descriptor::Wsh(ref wsh) => wsh.address(network),
495 Descriptor::Sh(ref sh) => sh.address(network),
496 Descriptor::Tr(ref tr) => tr.address(network),
497 }
498 }
499
500 fn script_pubkey(&self) -> Script
502 where
503 Pk: ToPublicKey,
504 {
505 match *self {
506 Descriptor::Bare(ref bare) => bare.script_pubkey(),
507 Descriptor::Pkh(ref pkh) => pkh.script_pubkey(),
508 Descriptor::Wpkh(ref wpkh) => wpkh.script_pubkey(),
509 Descriptor::Wsh(ref wsh) => wsh.script_pubkey(),
510 Descriptor::Sh(ref sh) => sh.script_pubkey(),
511 Descriptor::Tr(ref tr) => tr.script_pubkey(),
512 }
513 }
514
515 fn unsigned_script_sig(&self) -> Script
524 where
525 Pk: ToPublicKey,
526 {
527 match *self {
528 Descriptor::Bare(ref bare) => bare.unsigned_script_sig(),
529 Descriptor::Pkh(ref pkh) => pkh.unsigned_script_sig(),
530 Descriptor::Wpkh(ref wpkh) => wpkh.unsigned_script_sig(),
531 Descriptor::Wsh(ref wsh) => wsh.unsigned_script_sig(),
532 Descriptor::Sh(ref sh) => sh.unsigned_script_sig(),
533 Descriptor::Tr(ref tr) => tr.unsigned_script_sig(),
534 }
535 }
536
537 fn explicit_script(&self) -> Result<Script, Error>
544 where
545 Pk: ToPublicKey,
546 {
547 match *self {
548 Descriptor::Bare(ref bare) => bare.explicit_script(),
549 Descriptor::Pkh(ref pkh) => pkh.explicit_script(),
550 Descriptor::Wpkh(ref wpkh) => wpkh.explicit_script(),
551 Descriptor::Wsh(ref wsh) => wsh.explicit_script(),
552 Descriptor::Sh(ref sh) => sh.explicit_script(),
553 Descriptor::Tr(ref tr) => tr.explicit_script(),
554 }
555 }
556
557 fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
561 where
562 Pk: ToPublicKey,
563 S: Satisfier<Pk>,
564 {
565 match *self {
566 Descriptor::Bare(ref bare) => bare.get_satisfaction(satisfier),
567 Descriptor::Pkh(ref pkh) => pkh.get_satisfaction(satisfier),
568 Descriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction(satisfier),
569 Descriptor::Wsh(ref wsh) => wsh.get_satisfaction(satisfier),
570 Descriptor::Sh(ref sh) => sh.get_satisfaction(satisfier),
571 Descriptor::Tr(ref tr) => tr.get_satisfaction(satisfier),
572 }
573 }
574
575 fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
579 where
580 Pk: ToPublicKey,
581 S: Satisfier<Pk>,
582 {
583 match *self {
584 Descriptor::Bare(ref bare) => bare.get_satisfaction_mall(satisfier),
585 Descriptor::Pkh(ref pkh) => pkh.get_satisfaction_mall(satisfier),
586 Descriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction_mall(satisfier),
587 Descriptor::Wsh(ref wsh) => wsh.get_satisfaction_mall(satisfier),
588 Descriptor::Sh(ref sh) => sh.get_satisfaction_mall(satisfier),
589 Descriptor::Tr(ref tr) => tr.get_satisfaction_mall(satisfier),
590 }
591 }
592
593 fn max_satisfaction_weight(&self) -> Result<usize, Error> {
598 match *self {
599 Descriptor::Bare(ref bare) => bare.max_satisfaction_weight(),
600 Descriptor::Pkh(ref pkh) => pkh.max_satisfaction_weight(),
601 Descriptor::Wpkh(ref wpkh) => wpkh.max_satisfaction_weight(),
602 Descriptor::Wsh(ref wsh) => wsh.max_satisfaction_weight(),
603 Descriptor::Sh(ref sh) => sh.max_satisfaction_weight(),
604 Descriptor::Tr(ref tr) => tr.max_satisfaction_weight(),
605 }
606 }
607
608 fn script_code(&self) -> Result<Script, Error>
614 where
615 Pk: ToPublicKey,
616 {
617 match *self {
618 Descriptor::Bare(ref bare) => bare.script_code(),
619 Descriptor::Pkh(ref pkh) => pkh.script_code(),
620 Descriptor::Wpkh(ref wpkh) => wpkh.script_code(),
621 Descriptor::Wsh(ref wsh) => wsh.script_code(),
622 Descriptor::Sh(ref sh) => sh.script_code(),
623 Descriptor::Tr(ref tr) => tr.script_code(),
624 }
625 }
626}
627
628impl<Pk: MiniscriptKey> ForEachKey<Pk> for Descriptor<Pk> {
629 fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, pred: F) -> bool
630 where
631 Pk: 'a,
632 Pk::Hash: 'a,
633 {
634 match *self {
635 Descriptor::Bare(ref bare) => bare.for_each_key(pred),
636 Descriptor::Pkh(ref pkh) => pkh.for_each_key(pred),
637 Descriptor::Wpkh(ref wpkh) => wpkh.for_each_key(pred),
638 Descriptor::Wsh(ref wsh) => wsh.for_each_key(pred),
639 Descriptor::Sh(ref sh) => sh.for_each_key(pred),
640 Descriptor::Tr(ref tr) => tr.for_each_key(pred),
641 }
642 }
643}
644
645impl Descriptor<DescriptorPublicKey> {
646 pub fn is_deriveable(&self) -> bool {
648 self.for_any_key(|key| key.as_key().is_deriveable())
649 }
650
651 pub fn derive(&self, index: u32) -> Descriptor<DescriptorPublicKey> {
658 self.translate_pk2_infallible(|pk| pk.clone().derive(index))
659 }
660
661 pub fn derived_descriptor<C: secp256k1::Verification>(
687 &self,
688 secp: &secp256k1::Secp256k1<C>,
689 index: u32,
690 ) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
691 let derived = self
692 .derive(index)
693 .translate_pk2(|xpk| xpk.derive_public_key(secp))?;
694 Ok(derived)
695 }
696
697 pub fn parse_descriptor<C: secp256k1::Signing>(
702 secp: &secp256k1::Secp256k1<C>,
703 s: &str,
704 ) -> Result<(Descriptor<DescriptorPublicKey>, KeyMap), Error> {
705 let parse_key = |s: &String,
706 key_map: &mut KeyMap|
707 -> Result<DescriptorPublicKey, DescriptorKeyParseError> {
708 let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
709 Ok(sk) => (sk.as_public(&secp)?, Some(sk)),
710 Err(_) => (DescriptorPublicKey::from_str(s)?, None),
711 };
712
713 if let Some(secret_key) = secret_key {
714 key_map.insert(public_key.clone(), secret_key);
715 }
716
717 Ok(public_key)
718 };
719
720 let mut keymap_pk = KeyMap::new();
721 let mut keymap_pkh = KeyMap::new();
722
723 let descriptor = Descriptor::<String>::from_str(s)?;
724 let descriptor = descriptor
725 .translate_pk(
726 |pk| parse_key(pk, &mut keymap_pk),
727 |pkh| parse_key(pkh, &mut keymap_pkh),
728 )
729 .map_err(|e| Error::Unexpected(e.to_string()))?;
730
731 keymap_pk.extend(keymap_pkh.into_iter());
732
733 Ok((descriptor, keymap_pk))
734 }
735
736 pub fn to_string_with_secret(&self, key_map: &KeyMap) -> String {
738 fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> Result<String, ()> {
739 Ok(match key_map.get(pk) {
740 Some(secret) => secret.to_string(),
741 None => pk.to_string(),
742 })
743 }
744
745 let descriptor = self
746 .translate_pk::<_, _, ()>(
747 |pk| key_to_string(pk, key_map),
748 |pkh| key_to_string(pkh, key_map),
749 )
750 .expect("Translation to string cannot fail");
751
752 descriptor.to_string()
753 }
754}
755
756impl<Pk> expression::FromTree for Descriptor<Pk>
757where
758 Pk: MiniscriptKey + str::FromStr,
759 Pk::Hash: str::FromStr,
760 <Pk as FromStr>::Err: ToString,
761 <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString,
762{
763 fn from_tree(top: &expression::Tree) -> Result<Descriptor<Pk>, Error> {
765 Ok(match (top.name, top.args.len() as u32) {
766 ("pkh", 1) => Descriptor::Pkh(Pkh::from_tree(top)?),
767 ("wpkh", 1) => Descriptor::Wpkh(Wpkh::from_tree(top)?),
768 ("sh", 1) => Descriptor::Sh(Sh::from_tree(top)?),
769 ("wsh", 1) => Descriptor::Wsh(Wsh::from_tree(top)?),
770 ("tr", _) => Descriptor::Tr(Tr::from_tree(top)?),
771 _ => Descriptor::Bare(Bare::from_tree(top)?),
772 })
773 }
774}
775
776impl<Pk> FromStr for Descriptor<Pk>
777where
778 Pk: MiniscriptKey + str::FromStr,
779 Pk::Hash: str::FromStr,
780 <Pk as FromStr>::Err: ToString,
781 <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString,
782{
783 type Err = Error;
784
785 fn from_str(s: &str) -> Result<Descriptor<Pk>, Error> {
786 if s.starts_with("tr(") {
790 Ok(Descriptor::Tr(Tr::from_str(s)?))
791 } else {
792 let desc_str = verify_checksum(s)?;
793 let top = expression::Tree::from_str(desc_str)?;
794 expression::FromTree::from_tree(&top)
795 }
796 }
797}
798
799impl<Pk: MiniscriptKey> fmt::Debug for Descriptor<Pk> {
800 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
801 match *self {
802 Descriptor::Bare(ref sub) => write!(f, "{:?}", sub),
803 Descriptor::Pkh(ref pkh) => write!(f, "{:?}", pkh),
804 Descriptor::Wpkh(ref wpkh) => write!(f, "{:?}", wpkh),
805 Descriptor::Sh(ref sub) => write!(f, "{:?}", sub),
806 Descriptor::Wsh(ref sub) => write!(f, "{:?}", sub),
807 Descriptor::Tr(ref tr) => write!(f, "{:?}", tr),
808 }
809 }
810}
811
812impl<Pk: MiniscriptKey> fmt::Display for Descriptor<Pk> {
813 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
814 match *self {
815 Descriptor::Bare(ref sub) => write!(f, "{}", sub),
816 Descriptor::Pkh(ref pkh) => write!(f, "{}", pkh),
817 Descriptor::Wpkh(ref wpkh) => write!(f, "{}", wpkh),
818 Descriptor::Sh(ref sub) => write!(f, "{}", sub),
819 Descriptor::Wsh(ref sub) => write!(f, "{}", sub),
820 Descriptor::Tr(ref tr) => write!(f, "{}", tr),
821 }
822 }
823}
824
825serde_string_impl_pk!(Descriptor, "a script descriptor");
826
827#[cfg(test)]
828mod tests {
829 use super::checksum::desc_checksum;
830 use super::tr::Tr;
831 use super::*;
832 use bitcoin::blockdata::opcodes::all::{OP_CLTV, OP_CSV};
833 use bitcoin::blockdata::script::Instruction;
834 use bitcoin::blockdata::{opcodes, script};
835 use bitcoin::hashes::hex::{FromHex, ToHex};
836 use bitcoin::hashes::{hash160, sha256};
837 use bitcoin::util::bip32;
838 use bitcoin::{self, secp256k1, EcdsaSighashType, PublicKey};
839 use descriptor::key::Wildcard;
840 use descriptor::{
841 DescriptorPublicKey, DescriptorSecretKey, DescriptorSinglePub, DescriptorXKey,
842 };
843 use hex_script;
844 use std::cmp;
845 use std::collections::HashMap;
846 use std::str::FromStr;
847 use {Descriptor, DummyKey, Error, Miniscript, Satisfier, TranslatePk2};
848
849 #[cfg(feature = "compiler")]
850 use policy;
851
852 type StdDescriptor = Descriptor<PublicKey>;
853 const TEST_PK: &'static str =
854 "pk(020000000000000000000000000000000000000000000000000000000000000002)";
855
856 impl cmp::PartialEq for DescriptorSecretKey {
857 fn eq(&self, other: &Self) -> bool {
858 match (self, other) {
859 (
860 &DescriptorSecretKey::SinglePriv(ref a),
861 &DescriptorSecretKey::SinglePriv(ref b),
862 ) => a.origin == b.origin && a.key == b.key,
863 (&DescriptorSecretKey::XPrv(ref a), &DescriptorSecretKey::XPrv(ref b)) => {
864 a.origin == b.origin
865 && a.xkey == b.xkey
866 && a.derivation_path == b.derivation_path
867 && a.wildcard == b.wildcard
868 }
869 _ => false,
870 }
871 }
872 }
873
874 fn roundtrip_descriptor(s: &str) {
875 let desc = Descriptor::<DummyKey>::from_str(&s).unwrap();
876 let output = desc.to_string();
877 let normalize_aliases = s.replace("c:pk_k(", "pk(").replace("c:pk_h(", "pkh(");
878 assert_eq!(
879 format!(
880 "{}#{}",
881 &normalize_aliases,
882 desc_checksum(&normalize_aliases).unwrap()
883 ),
884 output
885 );
886 }
887
888 #[test]
889 fn desc_rtt_tests() {
890 roundtrip_descriptor("c:pk_k()");
891 roundtrip_descriptor("wsh(pk())");
892 roundtrip_descriptor("wsh(c:pk_k())");
893 roundtrip_descriptor("c:pk_h()");
894 }
895 #[test]
896 fn parse_descriptor() {
897 StdDescriptor::from_str("(").unwrap_err();
898 StdDescriptor::from_str("(x()").unwrap_err();
899 StdDescriptor::from_str("(\u{7f}()3").unwrap_err();
900 StdDescriptor::from_str("pk()").unwrap_err();
901 StdDescriptor::from_str("nl:0").unwrap_err(); let compressed_pk = DummyKey.to_string();
903 assert_eq!(
904 StdDescriptor::from_str("sh(sortedmulti)")
905 .unwrap_err()
906 .to_string(),
907 "unexpected «no arguments given for sortedmulti»"
908 ); assert_eq!(
910 StdDescriptor::from_str(&format!("sh(sortedmulti(2,{}))", compressed_pk))
911 .unwrap_err()
912 .to_string(),
913 "unexpected «higher threshold than there were keys in sortedmulti»"
914 ); StdDescriptor::from_str(TEST_PK).unwrap();
917
918 let uncompressed_pk =
919 "0414fc03b8df87cd7b872996810db8458d61da8448e531569c8517b469a119d267be5645686309c6e6736dbd93940707cc9143d3cf29f1b877ff340e2cb2d259cf";
920
921 StdDescriptor::from_str(&format!("pk({})", uncompressed_pk)).unwrap();
923 StdDescriptor::from_str(&format!("pkh({})", uncompressed_pk)).unwrap();
924 StdDescriptor::from_str(&format!("sh(pk({}))", uncompressed_pk)).unwrap();
925 StdDescriptor::from_str(&format!("wpkh({})", uncompressed_pk)).unwrap_err();
926 StdDescriptor::from_str(&format!("sh(wpkh({}))", uncompressed_pk)).unwrap_err();
927 StdDescriptor::from_str(&format!("wsh(pk{})", uncompressed_pk)).unwrap_err();
928 StdDescriptor::from_str(&format!("sh(wsh(pk{}))", uncompressed_pk)).unwrap_err();
929 StdDescriptor::from_str(&format!(
930 "or_i(pk({}),pk({}))",
931 uncompressed_pk, uncompressed_pk
932 ))
933 .unwrap_err();
934 }
935
936 #[test]
937 pub fn script_pubkey() {
938 let bare = StdDescriptor::from_str(&format!(
939 "multi(1,020000000000000000000000000000000000000000000000000000000000000002)"
940 ))
941 .unwrap();
942 assert_eq!(
943 bare.script_pubkey(),
944 hex_script(
945 "512102000000000000000000000000000000000000000000000000000000000000000251ae"
946 )
947 );
948 assert_eq!(
949 bare.address(bitcoin::Network::Bitcoin)
950 .unwrap_err()
951 .to_string(),
952 "Bare descriptors don't have address"
953 );
954
955 let pk = StdDescriptor::from_str(TEST_PK).unwrap();
956 assert_eq!(
957 pk.script_pubkey(),
958 bitcoin::Script::from(vec![
959 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xac,
962 ])
963 );
964
965 let pkh = StdDescriptor::from_str(
966 "pkh(\
967 020000000000000000000000000000000000000000000000000000000000000002\
968 )",
969 )
970 .unwrap();
971 assert_eq!(
972 pkh.script_pubkey(),
973 script::Builder::new()
974 .push_opcode(opcodes::all::OP_DUP)
975 .push_opcode(opcodes::all::OP_HASH160)
976 .push_slice(
977 &hash160::Hash::from_hex("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap()
978 [..]
979 )
980 .push_opcode(opcodes::all::OP_EQUALVERIFY)
981 .push_opcode(opcodes::all::OP_CHECKSIG)
982 .into_script()
983 );
984 assert_eq!(
985 pkh.address(bitcoin::Network::Bitcoin,).unwrap().to_string(),
986 "1D7nRvrRgzCg9kYBwhPH3j3Gs6SmsRg3Wq"
987 );
988
989 let wpkh = StdDescriptor::from_str(
990 "wpkh(\
991 020000000000000000000000000000000000000000000000000000000000000002\
992 )",
993 )
994 .unwrap();
995 assert_eq!(
996 wpkh.script_pubkey(),
997 script::Builder::new()
998 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
999 .push_slice(
1000 &hash160::Hash::from_hex("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap()
1001 [..]
1002 )
1003 .into_script()
1004 );
1005 assert_eq!(
1006 wpkh.address(bitcoin::Network::Bitcoin,)
1007 .unwrap()
1008 .to_string(),
1009 "bc1qsn57m9drscflq5nl76z6ny52hck5w4x5wqd9yt"
1010 );
1011
1012 let shwpkh = StdDescriptor::from_str(
1013 "sh(wpkh(\
1014 020000000000000000000000000000000000000000000000000000000000000002\
1015 ))",
1016 )
1017 .unwrap();
1018 assert_eq!(
1019 shwpkh.script_pubkey(),
1020 script::Builder::new()
1021 .push_opcode(opcodes::all::OP_HASH160)
1022 .push_slice(
1023 &hash160::Hash::from_hex("f1c3b9a431134cb90a500ec06e0067cfa9b8bba7",).unwrap()
1024 [..]
1025 )
1026 .push_opcode(opcodes::all::OP_EQUAL)
1027 .into_script()
1028 );
1029 assert_eq!(
1030 shwpkh
1031 .address(bitcoin::Network::Bitcoin,)
1032 .unwrap()
1033 .to_string(),
1034 "3PjMEzoveVbvajcnDDuxcJhsuqPHgydQXq"
1035 );
1036
1037 let sh = StdDescriptor::from_str(
1038 "sh(c:pk_k(\
1039 020000000000000000000000000000000000000000000000000000000000000002\
1040 ))",
1041 )
1042 .unwrap();
1043 assert_eq!(
1044 sh.script_pubkey(),
1045 script::Builder::new()
1046 .push_opcode(opcodes::all::OP_HASH160)
1047 .push_slice(
1048 &hash160::Hash::from_hex("aa5282151694d3f2f32ace7d00ad38f927a33ac8",).unwrap()
1049 [..]
1050 )
1051 .push_opcode(opcodes::all::OP_EQUAL)
1052 .into_script()
1053 );
1054 assert_eq!(
1055 sh.address(bitcoin::Network::Bitcoin,).unwrap().to_string(),
1056 "3HDbdvM9CQ6ASnQFUkWw6Z4t3qNwMesJE9"
1057 );
1058
1059 let wsh = StdDescriptor::from_str(
1060 "wsh(c:pk_k(\
1061 020000000000000000000000000000000000000000000000000000000000000002\
1062 ))",
1063 )
1064 .unwrap();
1065 assert_eq!(
1066 wsh.script_pubkey(),
1067 script::Builder::new()
1068 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1069 .push_slice(
1070 &sha256::Hash::from_hex(
1071 "\
1072 f9379edc8983152dc781747830075bd5\
1073 3896e4b0ce5bff73777fd77d124ba085\
1074 "
1075 )
1076 .unwrap()[..]
1077 )
1078 .into_script()
1079 );
1080 assert_eq!(
1081 wsh.address(bitcoin::Network::Bitcoin,).unwrap().to_string(),
1082 "bc1qlymeahyfsv2jm3upw3urqp6m65ufde9seedl7umh0lth6yjt5zzsk33tv6"
1083 );
1084
1085 let shwsh = StdDescriptor::from_str(
1086 "sh(wsh(c:pk_k(\
1087 020000000000000000000000000000000000000000000000000000000000000002\
1088 )))",
1089 )
1090 .unwrap();
1091 assert_eq!(
1092 shwsh.script_pubkey(),
1093 script::Builder::new()
1094 .push_opcode(opcodes::all::OP_HASH160)
1095 .push_slice(
1096 &hash160::Hash::from_hex("4bec5d7feeed99e1d0a23fe32a4afe126a7ff07e",).unwrap()
1097 [..]
1098 )
1099 .push_opcode(opcodes::all::OP_EQUAL)
1100 .into_script()
1101 );
1102 assert_eq!(
1103 shwsh
1104 .address(bitcoin::Network::Bitcoin,)
1105 .unwrap()
1106 .to_string(),
1107 "38cTksiyPT2b1uGRVbVqHdDhW9vKs84N6Z"
1108 );
1109 }
1110
1111 #[test]
1112 fn satisfy() {
1113 let secp = secp256k1::Secp256k1::new();
1114 let sk =
1115 secp256k1::SecretKey::from_slice(&b"sally was a secret key, she said"[..]).unwrap();
1116 let pk = bitcoin::PublicKey::new(secp256k1::PublicKey::from_secret_key(&secp, &sk));
1117 let msg = secp256k1::Message::from_slice(&b"michael was a message, amusingly"[..])
1118 .expect("32 bytes");
1119 let sig = secp.sign_ecdsa(&msg, &sk);
1120 let mut sigser = sig.serialize_der().to_vec();
1121 sigser.push(0x01); struct SimpleSat {
1124 sig: secp256k1::ecdsa::Signature,
1125 pk: bitcoin::PublicKey,
1126 }
1127
1128 impl Satisfier<bitcoin::PublicKey> for SimpleSat {
1129 fn lookup_ecdsa_sig(&self, pk: &bitcoin::PublicKey) -> Option<bitcoin::EcdsaSig> {
1130 if *pk == self.pk {
1131 Some(bitcoin::EcdsaSig {
1132 sig: self.sig,
1133 hash_ty: bitcoin::EcdsaSighashType::All,
1134 })
1135 } else {
1136 None
1137 }
1138 }
1139 }
1140
1141 let satisfier = SimpleSat { sig, pk };
1142 let ms = ms_str!("c:pk_k({})", pk);
1143
1144 let mut txin = bitcoin::TxIn {
1145 previous_output: bitcoin::OutPoint::default(),
1146 script_sig: bitcoin::Script::new(),
1147 sequence: 100,
1148 witness: Witness::default(),
1149 };
1150 let bare = Descriptor::new_bare(ms.clone()).unwrap();
1151
1152 bare.satisfy(&mut txin, &satisfier).expect("satisfaction");
1153 assert_eq!(
1154 txin,
1155 bitcoin::TxIn {
1156 previous_output: bitcoin::OutPoint::default(),
1157 script_sig: script::Builder::new().push_slice(&sigser[..]).into_script(),
1158 sequence: 100,
1159 witness: Witness::default(),
1160 }
1161 );
1162 assert_eq!(bare.unsigned_script_sig(), bitcoin::Script::new());
1163
1164 let pkh = Descriptor::new_pkh(pk);
1165 pkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1166 assert_eq!(
1167 txin,
1168 bitcoin::TxIn {
1169 previous_output: bitcoin::OutPoint::default(),
1170 script_sig: script::Builder::new()
1171 .push_slice(&sigser[..])
1172 .push_key(&pk)
1173 .into_script(),
1174 sequence: 100,
1175 witness: Witness::default(),
1176 }
1177 );
1178 assert_eq!(pkh.unsigned_script_sig(), bitcoin::Script::new());
1179
1180 let wpkh = Descriptor::new_wpkh(pk).unwrap();
1181 wpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1182 assert_eq!(
1183 txin,
1184 bitcoin::TxIn {
1185 previous_output: bitcoin::OutPoint::default(),
1186 script_sig: bitcoin::Script::new(),
1187 sequence: 100,
1188 witness: Witness::from_vec(vec![sigser.clone(), pk.to_bytes(),]),
1189 }
1190 );
1191 assert_eq!(wpkh.unsigned_script_sig(), bitcoin::Script::new());
1192
1193 let shwpkh = Descriptor::new_sh_wpkh(pk).unwrap();
1194 shwpkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1195 let redeem_script = script::Builder::new()
1196 .push_opcode(opcodes::all::OP_PUSHBYTES_0)
1197 .push_slice(
1198 &hash160::Hash::from_hex("d1b2a1faf62e73460af885c687dee3b7189cd8ab").unwrap()[..],
1199 )
1200 .into_script();
1201 assert_eq!(
1202 txin,
1203 bitcoin::TxIn {
1204 previous_output: bitcoin::OutPoint::default(),
1205 script_sig: script::Builder::new()
1206 .push_slice(&redeem_script[..])
1207 .into_script(),
1208 sequence: 100,
1209 witness: Witness::from_vec(vec![sigser.clone(), pk.to_bytes(),]),
1210 }
1211 );
1212 assert_eq!(
1213 shwpkh.unsigned_script_sig(),
1214 script::Builder::new()
1215 .push_slice(&redeem_script[..])
1216 .into_script()
1217 );
1218
1219 let ms = ms_str!("c:pk_k({})", pk);
1220 let sh = Descriptor::new_sh(ms.clone()).unwrap();
1221 sh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1222 assert_eq!(
1223 txin,
1224 bitcoin::TxIn {
1225 previous_output: bitcoin::OutPoint::default(),
1226 script_sig: script::Builder::new()
1227 .push_slice(&sigser[..])
1228 .push_slice(&ms.encode()[..])
1229 .into_script(),
1230 sequence: 100,
1231 witness: Witness::default(),
1232 }
1233 );
1234 assert_eq!(sh.unsigned_script_sig(), bitcoin::Script::new());
1235
1236 let ms = ms_str!("c:pk_k({})", pk);
1237
1238 let wsh = Descriptor::new_wsh(ms.clone()).unwrap();
1239 wsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1240 assert_eq!(
1241 txin,
1242 bitcoin::TxIn {
1243 previous_output: bitcoin::OutPoint::default(),
1244 script_sig: bitcoin::Script::new(),
1245 sequence: 100,
1246 witness: Witness::from_vec(vec![sigser.clone(), ms.encode().into_bytes(),]),
1247 }
1248 );
1249 assert_eq!(wsh.unsigned_script_sig(), bitcoin::Script::new());
1250
1251 let shwsh = Descriptor::new_sh_wsh(ms.clone()).unwrap();
1252 shwsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
1253 assert_eq!(
1254 txin,
1255 bitcoin::TxIn {
1256 previous_output: bitcoin::OutPoint::default(),
1257 script_sig: script::Builder::new()
1258 .push_slice(&ms.encode().to_v0_p2wsh()[..])
1259 .into_script(),
1260 sequence: 100,
1261 witness: Witness::from_vec(vec![sigser.clone(), ms.encode().into_bytes(),]),
1262 }
1263 );
1264 assert_eq!(
1265 shwsh.unsigned_script_sig(),
1266 script::Builder::new()
1267 .push_slice(&ms.encode().to_v0_p2wsh()[..])
1268 .into_script()
1269 );
1270 }
1271
1272 #[test]
1273 fn after_is_cltv() {
1274 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("wsh(after(1000))").unwrap();
1275 let script = descriptor.explicit_script().unwrap();
1276
1277 let actual_instructions: Vec<_> = script.instructions().collect();
1278 let check = actual_instructions.last().unwrap();
1279
1280 assert_eq!(check, &Ok(Instruction::Op(OP_CLTV)))
1281 }
1282
1283 #[test]
1284 fn older_is_csv() {
1285 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("wsh(older(1000))").unwrap();
1286 let script = descriptor.explicit_script().unwrap();
1287
1288 let actual_instructions: Vec<_> = script.instructions().collect();
1289 let check = actual_instructions.last().unwrap();
1290
1291 assert_eq!(check, &Ok(Instruction::Op(OP_CSV)))
1292 }
1293
1294 #[test]
1295 fn tr_roundtrip_key() {
1296 let script = Tr::<DummyKey>::from_str("tr()").unwrap().to_string();
1297 assert_eq!(script, format!("tr()#x4ml3kxd"))
1298 }
1299
1300 #[test]
1301 fn tr_roundtrip_script() {
1302 let descriptor = Tr::<DummyKey>::from_str("tr(,{pk(),pk()})")
1303 .unwrap()
1304 .to_string();
1305
1306 assert_eq!(descriptor, "tr(,{pk(),pk()})#7dqr6v8r");
1307
1308 let descriptor = Descriptor::<String>::from_str("tr(A,{pk(B),pk(C)})")
1309 .unwrap()
1310 .to_string();
1311 assert_eq!(descriptor, "tr(A,{pk(B),pk(C)})#y0uc9t6x");
1312 }
1313
1314 #[test]
1315 fn tr_roundtrip_tree() {
1316 let p1 = "020000000000000000000000000000000000000000000000000000000000000001";
1317 let p2 = "020000000000000000000000000000000000000000000000000000000000000002";
1318 let p3 = "020000000000000000000000000000000000000000000000000000000000000003";
1319 let p4 = "020000000000000000000000000000000000000000000000000000000000000004";
1320 let p5 = "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31";
1321 let descriptor = Tr::<PublicKey>::from_str(&format!(
1322 "tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})",
1323 p1, p2, p3, p4, p5
1324 ))
1325 .unwrap()
1326 .to_string();
1327
1328 assert_eq!(
1329 descriptor,
1330 format!(
1331 "tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})#fdhmu4fj",
1332 p1, p2, p3, p4, p5
1333 )
1334 )
1335 }
1336
1337 #[test]
1338 fn tr_script_pubkey() {
1339 let key = Descriptor::<bitcoin::PublicKey>::from_str(
1340 "tr(02e20e746af365e86647826397ba1c0e0d5cb685752976fe2f326ab76bdc4d6ee9)",
1341 )
1342 .unwrap();
1343 assert_eq!(
1344 key.script_pubkey().to_hex(),
1345 "51209c19294f03757da3dc235a5960631e3c55751632f5889b06b7a053bdc0bcfbcb"
1346 )
1347 }
1348
1349 #[test]
1350 fn roundtrip_tests() {
1351 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("multi");
1352 assert_eq!(
1353 descriptor.unwrap_err().to_string(),
1354 "unexpected «no arguments given»"
1355 )
1356 }
1357
1358 #[test]
1359 fn empty_thresh() {
1360 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str("thresh");
1361 assert_eq!(
1362 descriptor.unwrap_err().to_string(),
1363 "unexpected «no arguments given»"
1364 )
1365 }
1366
1367 #[test]
1368 fn witness_stack_for_andv_is_arranged_in_correct_order() {
1369 let a = bitcoin::PublicKey::from_str(
1371 "02937402303919b3a2ee5edd5009f4236f069bf75667b8e6ecf8e5464e20116a0e",
1372 )
1373 .unwrap();
1374 let sig_a = secp256k1::ecdsa::Signature::from_str("3045022100a7acc3719e9559a59d60d7b2837f9842df30e7edcd754e63227e6168cec72c5d022066c2feba4671c3d99ea75d9976b4da6c86968dbf3bab47b1061e7a1966b1778c").unwrap();
1375
1376 let b = bitcoin::PublicKey::from_str(
1377 "02eb64639a17f7334bb5a1a3aad857d6fec65faef439db3de72f85c88bc2906ad3",
1378 )
1379 .unwrap();
1380 let sig_b = secp256k1::ecdsa::Signature::from_str("3044022075b7b65a7e6cd386132c5883c9db15f9a849a0f32bc680e9986398879a57c276022056d94d12255a4424f51c700ac75122cb354895c9f2f88f0cbb47ba05c9c589ba").unwrap();
1381
1382 let descriptor = Descriptor::<bitcoin::PublicKey>::from_str(&format!(
1383 "wsh(and_v(v:pk({A}),pk({B})))",
1384 A = a,
1385 B = b
1386 ))
1387 .unwrap();
1388
1389 let mut txin = bitcoin::TxIn {
1390 previous_output: bitcoin::OutPoint::default(),
1391 script_sig: bitcoin::Script::new(),
1392 sequence: 0,
1393 witness: Witness::default(),
1394 };
1395 let satisfier = {
1396 let mut satisfier = HashMap::with_capacity(2);
1397
1398 satisfier.insert(
1399 a,
1400 bitcoin::EcdsaSig {
1401 sig: sig_a,
1402 hash_ty: EcdsaSighashType::All,
1403 },
1404 );
1405 satisfier.insert(
1406 b,
1407 bitcoin::EcdsaSig {
1408 sig: sig_b,
1409 hash_ty: EcdsaSighashType::All,
1410 },
1411 );
1412
1413 satisfier
1414 };
1415
1416 descriptor.satisfy(&mut txin, &satisfier).unwrap();
1418
1419 let wit = txin.witness.to_vec();
1421 let witness0 = &wit[0];
1422 let witness1 = &wit[1];
1423
1424 let sig0 = secp256k1::ecdsa::Signature::from_der(&witness0[..witness0.len() - 1]).unwrap();
1425 let sig1 = secp256k1::ecdsa::Signature::from_der(&witness1[..witness1.len() - 1]).unwrap();
1426
1427 assert_eq!(sig1, sig_a);
1432 assert_eq!(sig0, sig_b);
1433 }
1434
1435 #[test]
1436 fn test_scriptcode() {
1437 let descriptor = Descriptor::<PublicKey>::from_str(
1439 "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
1440 )
1441 .unwrap();
1442 assert_eq!(
1443 *descriptor.script_code().unwrap().as_bytes(),
1444 Vec::<u8>::from_hex("76a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac").unwrap()[..]
1445 );
1446
1447 let descriptor = Descriptor::<PublicKey>::from_str(
1449 "sh(wpkh(03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873))",
1450 )
1451 .unwrap();
1452 assert_eq!(
1453 *descriptor.script_code().unwrap().as_bytes(),
1454 Vec::<u8>::from_hex("76a91479091972186c449eb1ded22b78e40d009bdf008988ac").unwrap()[..]
1455 );
1456
1457 let descriptor = Descriptor::<PublicKey>::from_str(
1459 "wsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626))",
1460 )
1461 .unwrap();
1462 assert_eq!(
1463 *descriptor
1464 .script_code().unwrap()
1465 .as_bytes(),
1466 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae").unwrap()[..]
1467 );
1468
1469 let descriptor = Descriptor::<PublicKey>::from_str("sh(wsh(multi(2,03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd,03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626)))").unwrap();
1471 assert_eq!(
1472 *descriptor
1473 .script_code().unwrap()
1474 .as_bytes(),
1475 Vec::<u8>::from_hex("522103789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd2103dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a6162652ae")
1476 .unwrap()[..]
1477 );
1478 }
1479
1480 #[test]
1481 fn parse_descriptor_key() {
1482 let key = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*";
1484 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1485 origin: Some((
1486 bip32::Fingerprint::from(&[0x78, 0x41, 0x2e, 0x3a][..]),
1487 (&[
1488 bip32::ChildNumber::from_hardened_idx(44).unwrap(),
1489 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1490 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1491 ][..])
1492 .into(),
1493 )),
1494 xkey: bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1495 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1496 wildcard: Wildcard::Unhardened,
1497 });
1498 assert_eq!(expected, key.parse().unwrap());
1499 assert_eq!(format!("{}", expected), key);
1500
1501 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1";
1503 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1504 origin: None,
1505 xkey: bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1506 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1507 wildcard: Wildcard::None,
1508 });
1509 assert_eq!(expected, key.parse().unwrap());
1510 assert_eq!(format!("{}", expected), key);
1511
1512 let key = "tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed/1";
1514 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1515 origin: None,
1516 xkey: bip32::ExtendedPubKey::from_str("tpubD6NzVbkrYhZ4YqYr3amYH15zjxHvBkUUeadieW8AxTZC7aY2L8aPSk3tpW6yW1QnWzXAB7zoiaNMfwXPPz9S68ZCV4yWvkVXjdeksLskCed").unwrap(),
1517 derivation_path: (&[bip32::ChildNumber::from_normal_idx(1).unwrap()][..]).into(),
1518 wildcard: Wildcard::None,
1519 });
1520 assert_eq!(expected, key.parse().unwrap());
1521 assert_eq!(format!("{}", expected), key);
1522
1523 let key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
1525 let expected = DescriptorPublicKey::XPub(DescriptorXKey {
1526 origin: None,
1527 xkey: bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").unwrap(),
1528 derivation_path: bip32::DerivationPath::from(&[][..]),
1529 wildcard: Wildcard::None,
1530 });
1531 assert_eq!(expected, key.parse().unwrap());
1532 assert_eq!(format!("{}", expected), key);
1533
1534 let key = "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
1536 let expected = DescriptorPublicKey::SinglePub(DescriptorSinglePub {
1537 key: SinglePubKey::FullKey(
1538 bitcoin::PublicKey::from_str(
1539 "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8",
1540 )
1541 .unwrap(),
1542 ),
1543 origin: None,
1544 });
1545 assert_eq!(expected, key.parse().unwrap());
1546 assert_eq!(format!("{}", expected), key);
1547
1548 let key = "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a";
1550 let expected = DescriptorPublicKey::SinglePub(DescriptorSinglePub {
1551 key: SinglePubKey::FullKey(bitcoin::PublicKey::from_str(
1552 "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a",
1553 )
1554 .unwrap()),
1555 origin: None,
1556 });
1557 assert_eq!(expected, key.parse().unwrap());
1558 assert_eq!(format!("{}", expected), key);
1559
1560 let desc =
1562 "[78412e3a/0'/42/0']0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8";
1563 let expected = DescriptorPublicKey::SinglePub(DescriptorSinglePub {
1564 key: SinglePubKey::FullKey(
1565 bitcoin::PublicKey::from_str(
1566 "0231c7d3fc85c148717848033ce276ae2b464a4e2c367ed33886cc428b8af48ff8",
1567 )
1568 .unwrap(),
1569 ),
1570 origin: Some((
1571 bip32::Fingerprint::from(&[0x78, 0x41, 0x2e, 0x3a][..]),
1572 (&[
1573 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1574 bip32::ChildNumber::from_normal_idx(42).unwrap(),
1575 bip32::ChildNumber::from_hardened_idx(0).unwrap(),
1576 ][..])
1577 .into(),
1578 )),
1579 });
1580 assert_eq!(expected, desc.parse().expect("Parsing desc"));
1581 assert_eq!(format!("{}", expected), desc);
1582 }
1583
1584 #[test]
1585 fn test_sortedmulti() {
1586 fn _test_sortedmulti(raw_desc_one: &str, raw_desc_two: &str, raw_addr_expected: &str) {
1587 let secp_ctx = secp256k1::Secp256k1::verification_only();
1588 let index = 5;
1589
1590 let mut desc_one = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_one).unwrap();
1592 let mut desc_two = Descriptor::<DescriptorPublicKey>::from_str(raw_desc_two).unwrap();
1593
1594 assert_eq!(desc_one.to_string(), raw_desc_one);
1596 assert_eq!(desc_two.to_string(), raw_desc_two);
1597
1598 if raw_desc_one.contains("*") && raw_desc_two.contains("*") {
1600 desc_one = desc_one.derive(index);
1601 desc_two = desc_two.derive(index);
1602 }
1603
1604 let addr_one = desc_one
1606 .translate_pk2(|xpk| xpk.derive_public_key(&secp_ctx))
1607 .unwrap()
1608 .address(bitcoin::Network::Bitcoin)
1609 .unwrap();
1610 let addr_two = desc_two
1611 .translate_pk2(|xpk| xpk.derive_public_key(&secp_ctx))
1612 .unwrap()
1613 .address(bitcoin::Network::Bitcoin)
1614 .unwrap();
1615 let addr_expected = bitcoin::Address::from_str(raw_addr_expected).unwrap();
1616 assert_eq!(addr_one, addr_expected);
1617 assert_eq!(addr_two, addr_expected);
1618 }
1619
1620 _test_sortedmulti(
1622 "sh(sortedmulti(1,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352))#uetvewm2",
1623 "sh(sortedmulti(1,0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))#7l8smyg9",
1624 "3JZJNxvDKe6Y55ZaF5223XHwfF2eoMNnoV",
1625 );
1626
1627 _test_sortedmulti(
1629 "wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH))#7etm7zk7",
1630 "wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB))#ppmeel9k",
1631 "bc1qpq2cfgz5lktxzr5zqv7nrzz46hsvq3492ump9pz8rzcl8wqtwqcspx5y6a",
1632 );
1633
1634 _test_sortedmulti(
1636 "sh(wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*)))#u60cee0u",
1637 "sh(wsh(sortedmulti(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*)))#75dkf44w",
1638 "325zcVBN5o2eqqqtGwPjmtDd8dJRyYP82s",
1639 );
1640 }
1641
1642 #[test]
1643 fn test_parse_descriptor() {
1644 let secp = &secp256k1::Secp256k1::signing_only();
1645 let (descriptor, key_map) = Descriptor::parse_descriptor(secp, "wpkh(tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/44'/0'/0'/0/*)").unwrap();
1646 assert_eq!(descriptor.to_string(), "wpkh([2cbe2a6d/44'/0'/0']tpubDCvNhURocXGZsLNqWcqD3syHTqPXrMSTwi8feKVwAcpi29oYKsDD3Vex7x2TDneKMVN23RbLprfxB69v94iYqdaYHsVz3kPR37NQXeqouVz/0/*)#nhdxg96s");
1647 assert_eq!(key_map.len(), 1);
1648
1649 macro_rules! check_invalid_checksum {
1651 ($secp: ident,$($desc: expr),*) => {
1652 $(
1653 match Descriptor::parse_descriptor($secp, $desc) {
1654 Err(Error::BadDescriptor(_)) => {},
1655 Err(e) => panic!("Expected bad checksum for {}, got '{}'", $desc, e),
1656 _ => panic!("Invalid checksum treated as valid: {}", $desc),
1657 };
1658 )*
1659 };
1660 }
1661 check_invalid_checksum!(secp,
1662 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#",
1663 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#",
1664 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfyq",
1665 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq",
1666 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf",
1667 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5",
1668 "sh(multi(3,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy",
1669 "sh(multi(3,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t",
1670 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjq09x4t",
1671 "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))##ggssrxfy",
1672 "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))##tjq09x4t"
1673 );
1674
1675 Descriptor::parse_descriptor(&secp, "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy").expect("Valid descriptor with checksum");
1676 Descriptor::parse_descriptor(&secp, "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t").expect("Valid descriptor with checksum");
1677 }
1678
1679 #[test]
1680 #[cfg(feature = "compiler")]
1681 fn parse_and_derive() {
1682 let descriptor_str = "thresh(2,\
1683pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*),\
1684pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
1685pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
1686 let policy: policy::concrete::Policy<DescriptorPublicKey> = descriptor_str.parse().unwrap();
1687 let descriptor = Descriptor::new_sh(policy.compile().unwrap()).unwrap();
1688 let derived_descriptor = descriptor.derive(42);
1689
1690 let res_descriptor_str = "thresh(2,\
1691pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42),\
1692pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1),\
1693pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
1694 let res_policy: policy::concrete::Policy<DescriptorPublicKey> =
1695 res_descriptor_str.parse().unwrap();
1696 let res_descriptor = Descriptor::new_sh(res_policy.compile().unwrap()).unwrap();
1697
1698 assert_eq!(res_descriptor, derived_descriptor);
1699 }
1700
1701 #[test]
1702 fn parse_with_secrets() {
1703 let secp = &secp256k1::Secp256k1::signing_only();
1704 let descriptor_str = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)#v20xlvm9";
1705 let (descriptor, keymap) =
1706 Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, descriptor_str).unwrap();
1707
1708 let expected = "wpkh([a12b02f4/44'/0'/0']xpub6BzhLAQUDcBUfHRQHZxDF2AbcJqp4Kaeq6bzJpXrjrWuK26ymTFwkEFbxPra2bJ7yeZKbDjfDeFwxe93JMqpo5SsPJH6dZdvV9kMzJkAZ69/0/*)#u37l7u8u";
1709 assert_eq!(expected, descriptor.to_string());
1710 assert_eq!(keymap.len(), 1);
1711
1712 assert_eq!(descriptor_str, descriptor.to_string_with_secret(&keymap));
1714 }
1715
1716 #[test]
1717 fn checksum_for_nested_sh() {
1718 let descriptor_str = "sh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))";
1719 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
1720 assert_eq!(descriptor.to_string(), "sh(wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL))#tjp2zm88");
1721
1722 let descriptor_str = "sh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))";
1723 let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
1724 assert_eq!(descriptor.to_string(), "sh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))#6c6hwr22");
1725 }
1726
1727 #[test]
1728 fn test_xonly_keys() {
1729 let comp_key = "0308c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
1730 let x_only_key = "08c0fcf8895f4361b4fc77afe2ad53b0bd27dcebfd863421b2b246dc283d4103";
1731
1732 Descriptor::<DescriptorPublicKey>::from_str(&format!("tr({})", comp_key)).unwrap();
1734 Descriptor::<DescriptorPublicKey>::from_str(&format!("tr({})", x_only_key)).unwrap();
1735
1736 Descriptor::<DescriptorPublicKey>::from_str(&format!("wsh(pk({}))", comp_key)).unwrap();
1738 Descriptor::<DescriptorPublicKey>::from_str(&format!("wsh(pk({}))", x_only_key))
1739 .unwrap_err();
1740 }
1741}