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