1use core::convert::TryInto;
4use core::fmt;
5use core::str::FromStr;
6#[cfg(feature = "std")]
7use std::error;
8
9use bellscoin::bip32;
10use bellscoin::hash_types::XpubIdentifier;
11use bellscoin::hashes::hex::FromHex;
12use bellscoin::hashes::{hash160, ripemd160, sha256, Hash, HashEngine};
13use bellscoin::key::XOnlyPublicKey;
14use bellscoin::secp256k1::{Secp256k1, Signing, Verification};
15
16use crate::prelude::*;
17#[cfg(feature = "serde")]
18use crate::serde::{Deserialize, Deserializer, Serialize, Serializer};
19use crate::{hash256, MiniscriptKey, ToPublicKey};
20
21#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
23pub enum DescriptorPublicKey {
24 Single(SinglePub),
26 XPub(DescriptorXKey<bip32::ExtendedPubKey>),
28 MultiXPub(DescriptorMultiXKey<bip32::ExtendedPubKey>),
30}
31
32#[derive(Debug, Eq, PartialEq, Clone)]
34pub enum DescriptorSecretKey {
35 Single(SinglePriv),
37 XPrv(DescriptorXKey<bip32::ExtendedPrivKey>),
39 MultiXPrv(DescriptorMultiXKey<bip32::ExtendedPrivKey>),
41}
42
43#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
45pub struct SinglePub {
46 pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
48 pub key: SinglePubKey,
50}
51
52#[derive(Debug, Eq, PartialEq, Clone)]
54pub struct SinglePriv {
55 pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
57 pub key: bellscoin::PrivateKey,
59}
60
61#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
63pub struct DescriptorXKey<K: InnerXKey> {
64 pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
66 pub xkey: K,
68 pub derivation_path: bip32::DerivationPath,
70 pub wildcard: Wildcard,
72}
73
74#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
76pub struct DerivPaths(Vec<bip32::DerivationPath>);
77
78impl DerivPaths {
79 pub fn new(paths: Vec<bip32::DerivationPath>) -> Option<DerivPaths> {
81 if paths.is_empty() {
82 None
83 } else {
84 Some(DerivPaths(paths))
85 }
86 }
87
88 pub fn paths(&self) -> &Vec<bip32::DerivationPath> {
90 &self.0
91 }
92
93 pub fn into_paths(self) -> Vec<bip32::DerivationPath> {
95 self.0
96 }
97}
98
99#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
101pub struct DescriptorMultiXKey<K: InnerXKey> {
102 pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
104 pub xkey: K,
106 pub derivation_paths: DerivPaths,
108 pub wildcard: Wildcard,
110}
111
112#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
114pub enum SinglePubKey {
115 FullKey(bellscoin::PublicKey),
117 XOnly(XOnlyPublicKey),
119}
120
121#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
123pub struct DefiniteDescriptorKey(DescriptorPublicKey);
124
125impl fmt::Display for DescriptorSecretKey {
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 match self {
128 DescriptorSecretKey::Single(ref sk) => {
129 maybe_fmt_master_id(f, &sk.origin)?;
130 sk.key.fmt(f)?;
131 Ok(())
132 }
133 DescriptorSecretKey::XPrv(ref xprv) => {
134 maybe_fmt_master_id(f, &xprv.origin)?;
135 xprv.xkey.fmt(f)?;
136 fmt_derivation_path(f, &xprv.derivation_path)?;
137 match xprv.wildcard {
138 Wildcard::None => {}
139 Wildcard::Unhardened => write!(f, "/*")?,
140 Wildcard::Hardened => write!(f, "/*h")?,
141 }
142 Ok(())
143 }
144 DescriptorSecretKey::MultiXPrv(ref xprv) => {
145 maybe_fmt_master_id(f, &xprv.origin)?;
146 xprv.xkey.fmt(f)?;
147 fmt_derivation_paths(f, xprv.derivation_paths.paths())?;
148 match xprv.wildcard {
149 Wildcard::None => {}
150 Wildcard::Unhardened => write!(f, "/*")?,
151 Wildcard::Hardened => write!(f, "/*h")?,
152 }
153 Ok(())
154 }
155 }
156 }
157}
158
159pub trait InnerXKey: fmt::Display + FromStr {
162 fn xkey_fingerprint<C: Signing>(&self, secp: &Secp256k1<C>) -> bip32::Fingerprint;
164
165 fn can_derive_hardened() -> bool;
169}
170
171impl InnerXKey for bip32::ExtendedPubKey {
172 fn xkey_fingerprint<C: Signing>(&self, _secp: &Secp256k1<C>) -> bip32::Fingerprint {
173 self.fingerprint()
174 }
175
176 fn can_derive_hardened() -> bool {
177 false
178 }
179}
180
181impl InnerXKey for bip32::ExtendedPrivKey {
182 fn xkey_fingerprint<C: Signing>(&self, secp: &Secp256k1<C>) -> bip32::Fingerprint {
183 self.fingerprint(secp)
184 }
185
186 fn can_derive_hardened() -> bool {
187 true
188 }
189}
190
191#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
193pub enum Wildcard {
194 None,
196 Unhardened,
198 Hardened,
200}
201
202impl SinglePriv {
203 fn to_public<C: Signing>(&self, secp: &Secp256k1<C>) -> SinglePub {
205 let pub_key = self.key.public_key(secp);
206
207 SinglePub {
208 origin: self.origin.clone(),
209 key: SinglePubKey::FullKey(pub_key),
210 }
211 }
212}
213
214impl DescriptorXKey<bip32::ExtendedPrivKey> {
215 fn to_public<C: Signing>(
222 &self,
223 secp: &Secp256k1<C>,
224 ) -> Result<DescriptorXKey<bip32::ExtendedPubKey>, DescriptorKeyParseError> {
225 let unhardened = self
226 .derivation_path
227 .into_iter()
228 .rev()
229 .take_while(|c| c.is_normal())
230 .count();
231 let last_hardened_idx = self.derivation_path.len() - unhardened;
232
233 let hardened_path = &self.derivation_path[..last_hardened_idx];
234 let unhardened_path = &self.derivation_path[last_hardened_idx..];
235
236 let xprv = self
237 .xkey
238 .derive_priv(secp, &hardened_path)
239 .map_err(|_| DescriptorKeyParseError("Unable to derive the hardened steps"))?;
240 let xpub = bip32::ExtendedPubKey::from_priv(secp, &xprv);
241
242 let origin = match &self.origin {
243 Some((fingerprint, path)) => Some((
244 *fingerprint,
245 path.into_iter()
246 .chain(hardened_path.iter())
247 .cloned()
248 .collect(),
249 )),
250 None => {
251 if hardened_path.is_empty() {
252 None
253 } else {
254 Some((self.xkey.fingerprint(secp), hardened_path.into()))
255 }
256 }
257 };
258
259 Ok(DescriptorXKey {
260 origin,
261 xkey: xpub,
262 derivation_path: unhardened_path.into(),
263 wildcard: self.wildcard,
264 })
265 }
266}
267
268#[derive(Debug, PartialEq, Clone, Copy)]
271pub struct DescriptorKeyParseError(&'static str);
272
273impl fmt::Display for DescriptorKeyParseError {
274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275 f.write_str(self.0)
276 }
277}
278
279#[cfg(feature = "std")]
280impl error::Error for DescriptorKeyParseError {
281 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
282 None
283 }
284}
285
286impl fmt::Display for DescriptorPublicKey {
287 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
288 match *self {
289 DescriptorPublicKey::Single(ref pk) => {
290 maybe_fmt_master_id(f, &pk.origin)?;
291 match pk.key {
292 SinglePubKey::FullKey(full_key) => full_key.fmt(f),
293 SinglePubKey::XOnly(x_only_key) => x_only_key.fmt(f),
294 }?;
295 Ok(())
296 }
297 DescriptorPublicKey::XPub(ref xpub) => {
298 maybe_fmt_master_id(f, &xpub.origin)?;
299 xpub.xkey.fmt(f)?;
300 fmt_derivation_path(f, &xpub.derivation_path)?;
301 match xpub.wildcard {
302 Wildcard::None => {}
303 Wildcard::Unhardened => write!(f, "/*")?,
304 Wildcard::Hardened => write!(f, "/*h")?,
305 }
306 Ok(())
307 }
308 DescriptorPublicKey::MultiXPub(ref xpub) => {
309 maybe_fmt_master_id(f, &xpub.origin)?;
310 xpub.xkey.fmt(f)?;
311 fmt_derivation_paths(f, xpub.derivation_paths.paths())?;
312 match xpub.wildcard {
313 Wildcard::None => {}
314 Wildcard::Unhardened => write!(f, "/*")?,
315 Wildcard::Hardened => write!(f, "/*h")?,
316 }
317 Ok(())
318 }
319 }
320 }
321}
322
323impl DescriptorSecretKey {
324 pub fn to_public<C: Signing>(
333 &self,
334 secp: &Secp256k1<C>,
335 ) -> Result<DescriptorPublicKey, DescriptorKeyParseError> {
336 let pk = match self {
337 DescriptorSecretKey::Single(prv) => DescriptorPublicKey::Single(prv.to_public(secp)),
338 DescriptorSecretKey::XPrv(xprv) => DescriptorPublicKey::XPub(xprv.to_public(secp)?),
339 DescriptorSecretKey::MultiXPrv(_) => {
340 return Err(DescriptorKeyParseError(
341 "Can't make an extended private key with multiple paths into a public key.",
342 ))
343 }
344 };
345
346 Ok(pk)
347 }
348
349 pub fn is_multipath(&self) -> bool {
351 match *self {
352 DescriptorSecretKey::Single(..) | DescriptorSecretKey::XPrv(..) => false,
353 DescriptorSecretKey::MultiXPrv(_) => true,
354 }
355 }
356
357 pub fn into_single_keys(self) -> Vec<DescriptorSecretKey> {
363 match self {
364 DescriptorSecretKey::Single(..) | DescriptorSecretKey::XPrv(..) => vec![self],
365 DescriptorSecretKey::MultiXPrv(xpub) => {
366 let DescriptorMultiXKey {
367 origin,
368 xkey,
369 derivation_paths,
370 wildcard,
371 } = xpub;
372 derivation_paths
373 .into_paths()
374 .into_iter()
375 .map(|derivation_path| {
376 DescriptorSecretKey::XPrv(DescriptorXKey {
377 origin: origin.clone(),
378 xkey,
379 derivation_path,
380 wildcard,
381 })
382 })
383 .collect()
384 }
385 }
386 }
387}
388
389fn maybe_fmt_master_id(
391 f: &mut fmt::Formatter,
392 origin: &Option<(bip32::Fingerprint, bip32::DerivationPath)>,
393) -> fmt::Result {
394 if let Some((ref master_id, ref master_deriv)) = *origin {
395 fmt::Formatter::write_str(f, "[")?;
396 for byte in master_id.as_bytes().iter() {
397 write!(f, "{:02x}", byte)?;
398 }
399 fmt_derivation_path(f, master_deriv)?;
400 fmt::Formatter::write_str(f, "]")?;
401 }
402
403 Ok(())
404}
405
406fn fmt_derivation_path(f: &mut fmt::Formatter, path: &bip32::DerivationPath) -> fmt::Result {
408 for child in path {
409 write!(f, "/{}", child)?;
410 }
411 Ok(())
412}
413
414fn fmt_derivation_paths(f: &mut fmt::Formatter, paths: &[bip32::DerivationPath]) -> fmt::Result {
418 for (i, child) in paths[0].into_iter().enumerate() {
419 if paths.len() > 1 && child != &paths[1][i] {
420 write!(f, "/<")?;
421 for (j, p) in paths.iter().enumerate() {
422 write!(f, "{}", p[i])?;
423 if j != paths.len() - 1 {
424 write!(f, ";")?;
425 }
426 }
427 write!(f, ">")?;
428 } else {
429 write!(f, "/{}", child)?;
430 }
431 }
432 Ok(())
433}
434
435impl FromStr for DescriptorPublicKey {
436 type Err = DescriptorKeyParseError;
437
438 fn from_str(s: &str) -> Result<Self, Self::Err> {
439 if s.len() < 64 {
441 return Err(DescriptorKeyParseError(
442 "Key too short (<66 char), doesn't match any format",
443 ));
444 }
445
446 let (key_part, origin) = parse_key_origin(s)?;
447
448 if key_part.contains("pub") {
449 let (xpub, derivation_paths, wildcard) =
450 parse_xkey_deriv::<bip32::ExtendedPubKey>(key_part)?;
451 if derivation_paths.len() > 1 {
452 Ok(DescriptorPublicKey::MultiXPub(DescriptorMultiXKey {
453 origin,
454 xkey: xpub,
455 derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
456 wildcard,
457 }))
458 } else {
459 Ok(DescriptorPublicKey::XPub(DescriptorXKey {
460 origin,
461 xkey: xpub,
462 derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
463 wildcard,
464 }))
465 }
466 } else {
467 let key = match key_part.len() {
468 64 => {
469 let x_only_key = XOnlyPublicKey::from_str(key_part).map_err(|_| {
470 DescriptorKeyParseError("Error while parsing simple xonly key")
471 })?;
472 SinglePubKey::XOnly(x_only_key)
473 }
474 66 | 130 => {
475 if !(&key_part[0..2] == "02"
476 || &key_part[0..2] == "03"
477 || &key_part[0..2] == "04")
478 {
479 return Err(DescriptorKeyParseError(
480 "Only publickeys with prefixes 02/03/04 are allowed",
481 ));
482 }
483 let key = bellscoin::PublicKey::from_str(key_part).map_err(|_| {
484 DescriptorKeyParseError("Error while parsing simple public key")
485 })?;
486 SinglePubKey::FullKey(key)
487 }
488 _ => {
489 return Err(DescriptorKeyParseError(
490 "Public keys must be 64/66/130 characters in size",
491 ))
492 }
493 };
494 Ok(DescriptorPublicKey::Single(SinglePub { key, origin }))
495 }
496 }
497}
498
499#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
501pub enum ConversionError {
502 HardenedChild,
504 MultiKey,
506}
507
508impl fmt::Display for ConversionError {
509 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
510 f.write_str(match *self {
511 ConversionError::HardenedChild => "hardened child step in bip32 path",
512 ConversionError::MultiKey => "multiple existing keys",
513 })
514 }
515}
516
517#[cfg(feature = "std")]
518impl error::Error for ConversionError {
519 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
520 use self::ConversionError::*;
521
522 match self {
523 HardenedChild | MultiKey => None,
524 }
525 }
526}
527
528impl DescriptorPublicKey {
529 pub fn master_fingerprint(&self) -> bip32::Fingerprint {
531 match *self {
532 DescriptorPublicKey::XPub(ref xpub) => {
533 if let Some((fingerprint, _)) = xpub.origin {
534 fingerprint
535 } else {
536 xpub.xkey.fingerprint()
537 }
538 }
539 DescriptorPublicKey::MultiXPub(ref xpub) => {
540 if let Some((fingerprint, _)) = xpub.origin {
541 fingerprint
542 } else {
543 xpub.xkey.fingerprint()
544 }
545 }
546 DescriptorPublicKey::Single(ref single) => {
547 if let Some((fingerprint, _)) = single.origin {
548 fingerprint
549 } else {
550 let mut engine = XpubIdentifier::engine();
551 match single.key {
552 SinglePubKey::FullKey(pk) => {
553 pk.write_into(&mut engine).expect("engines don't error")
554 }
555 SinglePubKey::XOnly(x_only_pk) => engine.input(&x_only_pk.serialize()),
556 };
557 bip32::Fingerprint::from(
558 &XpubIdentifier::from_engine(engine)[..4]
559 .try_into()
560 .expect("4 byte slice"),
561 )
562 }
563 }
564 }
565 }
566
567 pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
575 match *self {
576 DescriptorPublicKey::XPub(ref xpub) => {
577 let origin_path = if let Some((_, ref path)) = xpub.origin {
578 path.clone()
579 } else {
580 bip32::DerivationPath::from(vec![])
581 };
582 Some(origin_path.extend(&xpub.derivation_path))
583 }
584 DescriptorPublicKey::Single(ref single) => {
585 Some(if let Some((_, ref path)) = single.origin {
586 path.clone()
587 } else {
588 bip32::DerivationPath::from(vec![])
589 })
590 }
591 DescriptorPublicKey::MultiXPub(_) => None,
592 }
593 }
594
595 #[deprecated(note = "use has_wildcard instead")]
597 pub fn is_deriveable(&self) -> bool {
598 self.has_wildcard()
599 }
600
601 pub fn has_wildcard(&self) -> bool {
603 match *self {
604 DescriptorPublicKey::Single(..) => false,
605 DescriptorPublicKey::XPub(ref xpub) => xpub.wildcard != Wildcard::None,
606 DescriptorPublicKey::MultiXPub(ref xpub) => xpub.wildcard != Wildcard::None,
607 }
608 }
609
610 #[deprecated(note = "use at_derivation_index instead")]
611 pub fn derive(self, index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
613 self.at_derivation_index(index)
614 }
615
616 pub fn at_derivation_index(self, index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
629 let definite = match self {
630 DescriptorPublicKey::Single(_) => self,
631 DescriptorPublicKey::XPub(xpub) => {
632 let derivation_path = match xpub.wildcard {
633 Wildcard::None => xpub.derivation_path,
634 Wildcard::Unhardened => xpub.derivation_path.into_child(
635 bip32::ChildNumber::from_normal_idx(index)
636 .ok()
637 .ok_or(ConversionError::HardenedChild)?,
638 ),
639 Wildcard::Hardened => xpub.derivation_path.into_child(
640 bip32::ChildNumber::from_hardened_idx(index)
641 .ok()
642 .ok_or(ConversionError::HardenedChild)?,
643 ),
644 };
645 DescriptorPublicKey::XPub(DescriptorXKey {
646 origin: xpub.origin,
647 xkey: xpub.xkey,
648 derivation_path,
649 wildcard: Wildcard::None,
650 })
651 }
652 DescriptorPublicKey::MultiXPub(_) => return Err(ConversionError::MultiKey),
653 };
654
655 Ok(DefiniteDescriptorKey::new(definite)
656 .expect("The key should not contain any wildcards at this point"))
657 }
658
659 pub fn is_multipath(&self) -> bool {
661 match *self {
662 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
663 DescriptorPublicKey::MultiXPub(_) => true,
664 }
665 }
666
667 pub fn into_single_keys(self) -> Vec<DescriptorPublicKey> {
673 match self {
674 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => vec![self],
675 DescriptorPublicKey::MultiXPub(xpub) => {
676 let DescriptorMultiXKey {
677 origin,
678 xkey,
679 derivation_paths,
680 wildcard,
681 } = xpub;
682 derivation_paths
683 .into_paths()
684 .into_iter()
685 .map(|derivation_path| {
686 DescriptorPublicKey::XPub(DescriptorXKey {
687 origin: origin.clone(),
688 xkey,
689 derivation_path,
690 wildcard,
691 })
692 })
693 .collect()
694 }
695 }
696 }
697}
698
699impl FromStr for DescriptorSecretKey {
700 type Err = DescriptorKeyParseError;
701
702 fn from_str(s: &str) -> Result<Self, Self::Err> {
703 let (key_part, origin) = parse_key_origin(s)?;
704
705 if key_part.len() <= 52 {
706 let sk = bellscoin::PrivateKey::from_str(key_part)
707 .map_err(|_| DescriptorKeyParseError("Error while parsing a WIF private key"))?;
708 Ok(DescriptorSecretKey::Single(SinglePriv {
709 key: sk,
710 origin: None,
711 }))
712 } else {
713 let (xpriv, derivation_paths, wildcard) =
714 parse_xkey_deriv::<bip32::ExtendedPrivKey>(key_part)?;
715 if derivation_paths.len() > 1 {
716 Ok(DescriptorSecretKey::MultiXPrv(DescriptorMultiXKey {
717 origin,
718 xkey: xpriv,
719 derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
720 wildcard,
721 }))
722 } else {
723 Ok(DescriptorSecretKey::XPrv(DescriptorXKey {
724 origin,
725 xkey: xpriv,
726 derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
727 wildcard,
728 }))
729 }
730 }
731 }
732}
733
734fn parse_key_origin(s: &str) -> Result<(&str, Option<bip32::KeySource>), DescriptorKeyParseError> {
736 for ch in s.as_bytes() {
737 if *ch < 20 || *ch > 127 {
738 return Err(DescriptorKeyParseError(
739 "Encountered an unprintable character",
740 ));
741 }
742 }
743
744 if s.is_empty() {
745 return Err(DescriptorKeyParseError("Empty key"));
746 }
747 let mut parts = s[1..].split(']');
748
749 if let Some('[') = s.chars().next() {
750 let mut raw_origin = parts
751 .next()
752 .ok_or(DescriptorKeyParseError("Unclosed '['"))?
753 .split('/');
754
755 let origin_id_hex = raw_origin.next().ok_or(DescriptorKeyParseError(
756 "No master fingerprint found after '['",
757 ))?;
758
759 if origin_id_hex.len() != 8 {
760 return Err(DescriptorKeyParseError(
761 "Master fingerprint should be 8 characters long",
762 ));
763 }
764 let parent_fingerprint = bip32::Fingerprint::from_hex(origin_id_hex).map_err(|_| {
765 DescriptorKeyParseError("Malformed master fingerprint, expected 8 hex chars")
766 })?;
767 let origin_path = raw_origin
768 .map(bip32::ChildNumber::from_str)
769 .collect::<Result<bip32::DerivationPath, bip32::Error>>()
770 .map_err(|_| DescriptorKeyParseError("Error while parsing master derivation path"))?;
771
772 let key = parts
773 .next()
774 .ok_or(DescriptorKeyParseError("No key after origin."))?;
775
776 if parts.next().is_some() {
777 Err(DescriptorKeyParseError(
778 "Multiple ']' in Descriptor Public Key",
779 ))
780 } else {
781 Ok((key, Some((parent_fingerprint, origin_path))))
782 }
783 } else {
784 Ok((s, None))
785 }
786}
787
788fn parse_xkey_deriv<K: InnerXKey>(
790 key_deriv: &str,
791) -> Result<(K, Vec<bip32::DerivationPath>, Wildcard), DescriptorKeyParseError> {
792 let mut key_deriv = key_deriv.split('/');
793 let xkey_str = key_deriv.next().ok_or(DescriptorKeyParseError(
794 "No key found after origin description",
795 ))?;
796 let xkey =
797 K::from_str(xkey_str).map_err(|_| DescriptorKeyParseError("Error while parsing xkey."))?;
798
799 let mut wildcard = Wildcard::None;
800 let mut multipath = false;
801 let derivation_paths = key_deriv
802 .filter_map(|p| {
803 if wildcard == Wildcard::None && p == "*" {
804 wildcard = Wildcard::Unhardened;
805 None
806 } else if wildcard == Wildcard::None && (p == "*'" || p == "*h") {
807 wildcard = Wildcard::Hardened;
808 None
809 } else if wildcard != Wildcard::None {
810 Some(Err(DescriptorKeyParseError(
811 "'*' may only appear as last element in a derivation path.",
812 )))
813 } else {
814 if p.starts_with('<') && p.ends_with('>') {
817 if multipath {
819 return Some(Err(DescriptorKeyParseError(
820 "'<' may only appear once in a derivation path.",
821 )));
822 }
823 multipath = true;
824
825 if p.len() < 5 || !p.contains(';') {
828 return Some(Err(DescriptorKeyParseError(
829 "Invalid multi index step in multipath descriptor.",
830 )));
831 }
832
833 let indexes = p[1..p.len() - 1].split(';');
835 Some(
836 indexes
837 .into_iter()
838 .map(|s| {
839 bip32::ChildNumber::from_str(s).map_err(|_| {
840 DescriptorKeyParseError(
841 "Error while parsing index in key derivation path.",
842 )
843 })
844 })
845 .collect::<Result<Vec<bip32::ChildNumber>, _>>(),
846 )
847 } else {
848 Some(
850 bip32::ChildNumber::from_str(p)
851 .map(|i| vec![i])
852 .map_err(|_| {
853 DescriptorKeyParseError("Error while parsing key derivation path")
854 }),
855 )
856 }
857 }
858 })
859 .fold(Ok(Vec::new()), |paths, index_list| {
865 let mut paths = paths?;
866 let mut index_list = index_list?.into_iter();
867 let first_index = index_list
868 .next()
869 .expect("There is always at least one element");
870
871 if paths.is_empty() {
872 paths.push(vec![first_index]);
873 } else {
874 for path in paths.iter_mut() {
875 path.push(first_index);
876 }
877 }
878
879 for (i, index) in index_list.enumerate() {
881 paths.push(paths[0].clone());
882 *paths[i + 1].last_mut().expect("Never empty") = index;
883 }
884
885 Ok(paths)
886 })?
887 .into_iter()
888 .map(|index_list| index_list.into_iter().collect::<bip32::DerivationPath>())
889 .collect::<Vec<bip32::DerivationPath>>();
890
891 Ok((xkey, derivation_paths, wildcard))
892}
893
894impl<K: InnerXKey> DescriptorXKey<K> {
895 pub fn matches<C: Signing>(
945 &self,
946 keysource: &bip32::KeySource,
947 secp: &Secp256k1<C>,
948 ) -> Option<bip32::DerivationPath> {
949 let (fingerprint, path) = keysource;
950
951 let (compare_fingerprint, compare_path) = match self.origin {
952 Some((fingerprint, ref path)) => (
953 fingerprint,
954 path.into_iter()
955 .chain(self.derivation_path.into_iter())
956 .collect(),
957 ),
958 None => (
959 self.xkey.xkey_fingerprint(secp),
960 self.derivation_path.into_iter().collect::<Vec<_>>(),
961 ),
962 };
963
964 let path_excluding_wildcard = if self.wildcard != Wildcard::None && !path.is_empty() {
965 path.into_iter()
966 .take(path.as_ref().len() - 1)
967 .cloned()
968 .collect()
969 } else {
970 path.clone()
971 };
972
973 if &compare_fingerprint == fingerprint
974 && compare_path
975 .into_iter()
976 .eq(path_excluding_wildcard.into_iter())
977 {
978 Some(path_excluding_wildcard)
979 } else {
980 None
981 }
982 }
983}
984
985impl MiniscriptKey for DescriptorPublicKey {
986 type Sha256 = sha256::Hash;
987 type Hash256 = hash256::Hash;
988 type Ripemd160 = ripemd160::Hash;
989 type Hash160 = hash160::Hash;
990
991 fn is_uncompressed(&self) -> bool {
992 match self {
993 DescriptorPublicKey::Single(SinglePub {
994 key: SinglePubKey::FullKey(ref key),
995 ..
996 }) => key.is_uncompressed(),
997 _ => false,
998 }
999 }
1000
1001 fn is_x_only_key(&self) -> bool {
1002 match self {
1003 DescriptorPublicKey::Single(SinglePub {
1004 key: SinglePubKey::XOnly(ref _key),
1005 ..
1006 }) => true,
1007 _ => false,
1008 }
1009 }
1010
1011 fn num_der_paths(&self) -> usize {
1012 match self {
1013 DescriptorPublicKey::Single(_) => 0,
1014 DescriptorPublicKey::XPub(_) => 1,
1015 DescriptorPublicKey::MultiXPub(xpub) => xpub.derivation_paths.paths().len(),
1016 }
1017 }
1018}
1019
1020impl DefiniteDescriptorKey {
1021 pub fn derive_public_key<C: Verification>(
1031 &self,
1032 secp: &Secp256k1<C>,
1033 ) -> Result<bellscoin::PublicKey, ConversionError> {
1034 match self.0 {
1035 DescriptorPublicKey::Single(ref pk) => match pk.key {
1036 SinglePubKey::FullKey(pk) => Ok(pk),
1037 SinglePubKey::XOnly(xpk) => Ok(xpk.to_public_key()),
1038 },
1039 DescriptorPublicKey::XPub(ref xpk) => match xpk.wildcard {
1040 Wildcard::Unhardened | Wildcard::Hardened => {
1041 unreachable!("we've excluded this error case")
1042 }
1043 Wildcard::None => match xpk.xkey.derive_pub(secp, &xpk.derivation_path.as_ref()) {
1044 Ok(xpub) => Ok(bellscoin::PublicKey::new(xpub.public_key)),
1045 Err(bip32::Error::CannotDeriveFromHardenedKey) => {
1046 Err(ConversionError::HardenedChild)
1047 }
1048 Err(e) => unreachable!("cryptographically unreachable: {}", e),
1049 },
1050 },
1051 DescriptorPublicKey::MultiXPub(_) => {
1052 unreachable!("A definite key cannot contain a multipath key.")
1053 }
1054 }
1055 }
1056
1057 fn new(key: DescriptorPublicKey) -> Option<Self> {
1061 if key.has_wildcard() {
1062 None
1063 } else {
1064 Some(Self(key))
1065 }
1066 }
1067
1068 pub fn master_fingerprint(&self) -> bip32::Fingerprint {
1070 self.0.master_fingerprint()
1071 }
1072
1073 pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
1075 self.0.full_derivation_path()
1076 }
1077
1078 pub fn as_descriptor_public_key(&self) -> &DescriptorPublicKey {
1080 &self.0
1081 }
1082
1083 pub fn into_descriptor_public_key(self) -> DescriptorPublicKey {
1085 self.0
1086 }
1087}
1088
1089impl FromStr for DefiniteDescriptorKey {
1090 type Err = DescriptorKeyParseError;
1091
1092 fn from_str(s: &str) -> Result<Self, Self::Err> {
1093 let inner = DescriptorPublicKey::from_str(s)?;
1094 DefiniteDescriptorKey::new(inner).ok_or(DescriptorKeyParseError(
1095 "cannot parse key with a wilcard as a DerivedDescriptorKey",
1096 ))
1097 }
1098}
1099
1100impl fmt::Display for DefiniteDescriptorKey {
1101 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1102 self.0.fmt(f)
1103 }
1104}
1105
1106impl MiniscriptKey for DefiniteDescriptorKey {
1107 type Sha256 = sha256::Hash;
1108 type Hash256 = hash256::Hash;
1109 type Ripemd160 = ripemd160::Hash;
1110 type Hash160 = hash160::Hash;
1111
1112 fn is_uncompressed(&self) -> bool {
1113 self.0.is_uncompressed()
1114 }
1115
1116 fn is_x_only_key(&self) -> bool {
1117 self.0.is_x_only_key()
1118 }
1119
1120 fn num_der_paths(&self) -> usize {
1121 self.0.num_der_paths()
1122 }
1123}
1124
1125impl ToPublicKey for DefiniteDescriptorKey {
1126 fn to_public_key(&self) -> bellscoin::PublicKey {
1127 let secp = Secp256k1::verification_only();
1128 self.derive_public_key(&secp).unwrap()
1129 }
1130
1131 fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
1132 *hash
1133 }
1134
1135 fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
1136 *hash
1137 }
1138
1139 fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash {
1140 *hash
1141 }
1142
1143 fn to_hash160(hash: &hash160::Hash) -> hash160::Hash {
1144 *hash
1145 }
1146}
1147
1148impl From<DefiniteDescriptorKey> for DescriptorPublicKey {
1149 fn from(d: DefiniteDescriptorKey) -> Self {
1150 d.0
1151 }
1152}
1153
1154impl Borrow<DescriptorPublicKey> for DefiniteDescriptorKey {
1155 fn borrow(&self) -> &DescriptorPublicKey {
1156 &self.0
1157 }
1158}
1159
1160#[cfg(feature = "serde")]
1161impl<'de> Deserialize<'de> for DescriptorPublicKey {
1162 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1163 where
1164 D: Deserializer<'de>,
1165 {
1166 let s = String::deserialize(deserializer)?;
1167 DescriptorPublicKey::from_str(&s).map_err(crate::serde::de::Error::custom)
1168 }
1169}
1170
1171#[cfg(feature = "serde")]
1172impl Serialize for DescriptorPublicKey {
1173 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1174 where
1175 S: Serializer,
1176 {
1177 serializer.serialize_str(&self.to_string())
1178 }
1179}
1180
1181#[cfg(test)]
1182mod test {
1183 use core::str::FromStr;
1184
1185 use bellscoin::{bip32, secp256k1};
1186 #[cfg(feature = "serde")]
1187 use serde_test::{assert_tokens, Token};
1188
1189 use super::{
1190 DescriptorKeyParseError, DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey,
1191 MiniscriptKey, Wildcard,
1192 };
1193 use crate::prelude::*;
1194
1195 #[test]
1196 fn parse_descriptor_key_errors() {
1197 let desc = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*/44";
1199 assert_eq!(
1200 DescriptorPublicKey::from_str(desc),
1201 Err(DescriptorKeyParseError(
1202 "\'*\' may only appear as last element in a derivation path."
1203 ))
1204 );
1205
1206 let desc = "[NonHexor]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*";
1208 assert_eq!(
1209 DescriptorPublicKey::from_str(desc),
1210 Err(DescriptorKeyParseError(
1211 "Malformed master fingerprint, expected 8 hex chars"
1212 ))
1213 );
1214
1215 let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*";
1217 assert_eq!(
1218 DescriptorPublicKey::from_str(desc),
1219 Err(DescriptorKeyParseError("Error while parsing xkey."))
1220 );
1221
1222 let desc = "[78412e3a]0208a117f3897c3a13c9384b8695eed98dc31bc2500feb19a1af424cd47a5d83/1/*";
1224 assert_eq!(
1225 DescriptorPublicKey::from_str(desc),
1226 Err(DescriptorKeyParseError(
1227 "Public keys must be 64/66/130 characters in size"
1228 ))
1229 );
1230
1231 let desc = "[78412e3a]]03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
1233 assert_eq!(
1234 DescriptorPublicKey::from_str(desc),
1235 Err(DescriptorKeyParseError(
1236 "Multiple \']\' in Descriptor Public Key"
1237 ))
1238 );
1239
1240 let desc = "[11111f11]033333333333333333333333333333323333333333333333333333333433333333]]333]]3]]101333333333333433333]]]10]333333mmmm";
1242 assert_eq!(
1243 DescriptorPublicKey::from_str(desc),
1244 Err(DescriptorKeyParseError(
1245 "Multiple \']\' in Descriptor Public Key"
1246 ))
1247 );
1248
1249 let desc = "0777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777";
1251 assert_eq!(
1252 DescriptorPublicKey::from_str(desc),
1253 Err(DescriptorKeyParseError(
1254 "Only publickeys with prefixes 02/03/04 are allowed"
1255 ))
1256 );
1257 }
1258
1259 #[test]
1260 fn parse_descriptor_secret_key_error() {
1261 let secret_key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
1263 assert_eq!(
1264 DescriptorSecretKey::from_str(secret_key),
1265 Err(DescriptorKeyParseError("Error while parsing xkey."))
1266 );
1267
1268 let desc = "[NonHexor]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/*";
1270 assert_eq!(
1271 DescriptorSecretKey::from_str(desc),
1272 Err(DescriptorKeyParseError(
1273 "Malformed master fingerprint, expected 8 hex chars"
1274 ))
1275 );
1276
1277 let desc = "[78412e3a]L32jTfVLei6BYTPUpwpJSkrHx8iL9GZzeErVS8y4Y/1/*";
1279 assert_eq!(
1280 DescriptorSecretKey::from_str(desc),
1281 Err(DescriptorKeyParseError(
1282 "Error while parsing a WIF private key"
1283 ))
1284 );
1285 }
1286
1287 #[test]
1288 fn test_wildcard() {
1289 let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2").unwrap();
1290 assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1291 assert_eq!(
1292 public_key.full_derivation_path().unwrap().to_string(),
1293 "m/0'/1'/2"
1294 );
1295 assert!(!public_key.has_wildcard());
1296
1297 let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*").unwrap();
1298 assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1299 assert_eq!(
1300 public_key.full_derivation_path().unwrap().to_string(),
1301 "m/0'/1'"
1302 );
1303 assert!(public_key.has_wildcard());
1304
1305 let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*h").unwrap();
1306 assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1307 assert_eq!(
1308 public_key.full_derivation_path().unwrap().to_string(),
1309 "m/0'/1'"
1310 );
1311 assert!(public_key.has_wildcard());
1312 }
1313
1314 #[test]
1315 fn test_deriv_on_xprv() {
1316 let secp = secp256k1::Secp256k1::signing_only();
1317
1318 let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2").unwrap();
1319 let public_key = secret_key.to_public(&secp).unwrap();
1320 assert_eq!(public_key.to_string(), "[2cbe2a6d/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2");
1321 assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1322 assert_eq!(
1323 public_key.full_derivation_path().unwrap().to_string(),
1324 "m/0'/1'/2"
1325 );
1326 assert!(!public_key.has_wildcard());
1327
1328 let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2'").unwrap();
1329 let public_key = secret_key.to_public(&secp).unwrap();
1330 assert_eq!(public_key.to_string(), "[2cbe2a6d/0'/1'/2']tpubDDPuH46rv4dbFtmF6FrEtJEy1CvLZonyBoVxF6xsesHdYDdTBrq2mHhm8AbsPh39sUwL2nZyxd6vo4uWNTU9v4t893CwxjqPnwMoUACLvMV");
1331 assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1332 assert_eq!(
1333 public_key.full_derivation_path().unwrap().to_string(),
1334 "m/0'/1'/2'"
1335 );
1336
1337 let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0/1/2").unwrap();
1338 let public_key = secret_key.to_public(&secp).unwrap();
1339 assert_eq!(public_key.to_string(), "tpubD6NzVbkrYhZ4WQdzxL7NmJN7b85ePo4p6RSj9QQHF7te2RR9iUeVSGgnGkoUsB9LBRosgvNbjRv9bcsJgzgBd7QKuxDm23ZewkTRzNSLEDr/0/1/2");
1340 assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1341 assert_eq!(
1342 public_key.full_derivation_path().unwrap().to_string(),
1343 "m/0/1/2"
1344 );
1345
1346 let secret_key = DescriptorSecretKey::from_str("[aabbccdd]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0/1/2").unwrap();
1347 let public_key = secret_key.to_public(&secp).unwrap();
1348 assert_eq!(public_key.to_string(), "[aabbccdd]tpubD6NzVbkrYhZ4WQdzxL7NmJN7b85ePo4p6RSj9QQHF7te2RR9iUeVSGgnGkoUsB9LBRosgvNbjRv9bcsJgzgBd7QKuxDm23ZewkTRzNSLEDr/0/1/2");
1349 assert_eq!(public_key.master_fingerprint().to_string(), "aabbccdd");
1350 assert_eq!(
1351 public_key.full_derivation_path().unwrap().to_string(),
1352 "m/0/1/2"
1353 );
1354
1355 let secret_key = DescriptorSecretKey::from_str("[aabbccdd/90']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2").unwrap();
1356 let public_key = secret_key.to_public(&secp).unwrap();
1357 assert_eq!(public_key.to_string(), "[aabbccdd/90'/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2");
1358 assert_eq!(public_key.master_fingerprint().to_string(), "aabbccdd");
1359 assert_eq!(
1360 public_key.full_derivation_path().unwrap().to_string(),
1361 "m/90'/0'/1'/2"
1362 );
1363 }
1364
1365 #[test]
1366 fn test_master_fingerprint() {
1367 assert_eq!(
1368 DescriptorPublicKey::from_str(
1369 "02a489e0ea42b56148d212d325b7c67c6460483ff931c303ea311edfef667c8f35",
1370 )
1371 .unwrap()
1372 .master_fingerprint()
1373 .as_bytes(),
1374 b"\xb0\x59\x11\x6a"
1375 );
1376 }
1377
1378 fn get_multipath_xpub(
1379 key_str: &str,
1380 num_paths: usize,
1381 ) -> DescriptorMultiXKey<bip32::ExtendedPubKey> {
1382 let desc_key = DescriptorPublicKey::from_str(key_str).unwrap();
1383 assert_eq!(desc_key.num_der_paths(), num_paths);
1384 match desc_key {
1385 DescriptorPublicKey::MultiXPub(xpub) => xpub,
1386 _ => unreachable!(),
1387 }
1388 }
1389
1390 fn get_multipath_xprv(key_str: &str) -> DescriptorMultiXKey<bip32::ExtendedPrivKey> {
1391 let desc_key = DescriptorSecretKey::from_str(key_str).unwrap();
1392 match desc_key {
1393 DescriptorSecretKey::MultiXPrv(xprv) => xprv,
1394 _ => unreachable!(),
1395 }
1396 }
1397
1398 #[test]
1399 fn multipath_extended_keys() {
1400 let secp = secp256k1::Secp256k1::signing_only();
1401
1402 let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;42;9854>", 4);
1404 assert_eq!(
1405 xpub.derivation_paths.paths(),
1406 &vec![
1407 bip32::DerivationPath::from_str("m/2/0").unwrap(),
1408 bip32::DerivationPath::from_str("m/2/1").unwrap(),
1409 bip32::DerivationPath::from_str("m/2/42").unwrap(),
1410 bip32::DerivationPath::from_str("m/2/9854").unwrap()
1411 ],
1412 );
1413 assert_eq!(
1414 xpub,
1415 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 4)
1416 );
1417 let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;9854>/0/5/10", 3);
1419 assert_eq!(
1420 xpub.derivation_paths.paths(),
1421 &vec![
1422 bip32::DerivationPath::from_str("m/2/0/0/5/10").unwrap(),
1423 bip32::DerivationPath::from_str("m/2/1/0/5/10").unwrap(),
1424 bip32::DerivationPath::from_str("m/2/9854/0/5/10").unwrap()
1425 ],
1426 );
1427 assert_eq!(
1428 xpub,
1429 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 3)
1430 );
1431 let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;9854>/3456/9876/*", 3);
1433 assert_eq!(xpub.wildcard, Wildcard::Unhardened);
1434 assert_eq!(
1435 xpub.derivation_paths.paths(),
1436 &vec![
1437 bip32::DerivationPath::from_str("m/2/0/3456/9876").unwrap(),
1438 bip32::DerivationPath::from_str("m/2/1/3456/9876").unwrap(),
1439 bip32::DerivationPath::from_str("m/2/9854/3456/9876").unwrap()
1440 ],
1441 );
1442 assert_eq!(
1443 xpub,
1444 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 3)
1445 );
1446 let xpub = get_multipath_xpub("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/<0;1>/*", 2);
1448 assert_eq!(xpub.wildcard, Wildcard::Unhardened);
1449 assert_eq!(
1450 xpub.derivation_paths.paths(),
1451 &vec![
1452 bip32::DerivationPath::from_str("m/0").unwrap(),
1453 bip32::DerivationPath::from_str("m/1").unwrap(),
1454 ],
1455 );
1456 assert_eq!(
1457 xpub,
1458 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 2)
1459 );
1460 let xpub = get_multipath_xpub("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1h>/8h/*'", 2);
1463 assert_eq!(xpub.wildcard, Wildcard::Hardened);
1464 assert_eq!(
1465 xpub.derivation_paths.paths(),
1466 &vec![
1467 bip32::DerivationPath::from_str("m/9478'/0'/8'").unwrap(),
1468 bip32::DerivationPath::from_str("m/9478h/1h/8h").unwrap(),
1469 ],
1470 );
1471 assert_eq!(
1472 xpub,
1473 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 2)
1474 );
1475 let desc_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1>/8h/*'").unwrap();
1477 assert!(desc_key.full_derivation_path().is_none());
1478 assert!(desc_key.is_multipath());
1479 assert_eq!(desc_key.into_single_keys(), vec![DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/0'/8h/*'").unwrap(), DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/1/8h/*'").unwrap()]);
1480
1481 let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;42;9854>");
1483 assert_eq!(
1484 xprv.derivation_paths.paths(),
1485 &vec![
1486 bip32::DerivationPath::from_str("m/2/0").unwrap(),
1487 bip32::DerivationPath::from_str("m/2/1").unwrap(),
1488 bip32::DerivationPath::from_str("m/2/42").unwrap(),
1489 bip32::DerivationPath::from_str("m/2/9854").unwrap()
1490 ],
1491 );
1492 assert_eq!(
1493 xprv,
1494 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1495 );
1496 let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;9854>/0/5/10");
1497 assert_eq!(
1498 xprv.derivation_paths.paths(),
1499 &vec![
1500 bip32::DerivationPath::from_str("m/2/0/0/5/10").unwrap(),
1501 bip32::DerivationPath::from_str("m/2/1/0/5/10").unwrap(),
1502 bip32::DerivationPath::from_str("m/2/9854/0/5/10").unwrap()
1503 ],
1504 );
1505 assert_eq!(
1506 xprv,
1507 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1508 );
1509 let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;9854>/3456/9876/*");
1510 assert_eq!(xprv.wildcard, Wildcard::Unhardened);
1511 assert_eq!(
1512 xprv.derivation_paths.paths(),
1513 &vec![
1514 bip32::DerivationPath::from_str("m/2/0/3456/9876").unwrap(),
1515 bip32::DerivationPath::from_str("m/2/1/3456/9876").unwrap(),
1516 bip32::DerivationPath::from_str("m/2/9854/3456/9876").unwrap()
1517 ],
1518 );
1519 assert_eq!(
1520 xprv,
1521 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1522 );
1523 let xprv = get_multipath_xprv("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/<0;1>/*");
1524 assert_eq!(xprv.wildcard, Wildcard::Unhardened);
1525 assert_eq!(
1526 xprv.derivation_paths.paths(),
1527 &vec![
1528 bip32::DerivationPath::from_str("m/0").unwrap(),
1529 bip32::DerivationPath::from_str("m/1").unwrap(),
1530 ],
1531 );
1532 assert_eq!(
1533 xprv,
1534 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1535 );
1536 let xprv = get_multipath_xprv("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1h>/8h/*'");
1537 assert_eq!(xprv.wildcard, Wildcard::Hardened);
1538 assert_eq!(
1539 xprv.derivation_paths.paths(),
1540 &vec![
1541 bip32::DerivationPath::from_str("m/9478'/0'/8'").unwrap(),
1542 bip32::DerivationPath::from_str("m/9478h/1h/8h").unwrap(),
1543 ],
1544 );
1545 assert_eq!(
1546 xprv,
1547 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1548 );
1549 let desc_key = DescriptorSecretKey::from_str("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1>/8h/*'").unwrap();
1550 assert!(desc_key.to_public(&secp).is_err());
1551 assert!(desc_key.is_multipath());
1552 assert_eq!(desc_key.into_single_keys(), vec![DescriptorSecretKey::from_str("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/0'/8h/*'").unwrap(), DescriptorSecretKey::from_str("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/1/8h/*'").unwrap()]);
1553
1554 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;42;9854").unwrap_err();
1559 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/0;1;42;9854>").unwrap_err();
1560 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;1>/96/<0;1>").unwrap_err();
1561 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0>").unwrap_err();
1562 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;>").unwrap_err();
1563 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<;1>").unwrap_err();
1564 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;1;>").unwrap_err();
1565 }
1566
1567 #[test]
1568 #[cfg(feature = "serde")]
1569 fn test_descriptor_public_key_serde() {
1570 let desc = "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2";
1571 let public_key = DescriptorPublicKey::from_str(desc).unwrap();
1572 assert_tokens(&public_key, &[Token::String(desc)]);
1573 }
1574}