1use std::borrow::Borrow;
3use std::convert::TryInto;
4use std::str::FromStr;
5use std::{error, fmt, hash};
6
7use bitcoin::bip32::XKeyIdentifier;
8use bitcoin::hashes::{hash160, ripemd160, sha256, Hash, HashEngine};
9use bitcoin::hex::FromHex;
10use bitcoin::{self, bip32};
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 fmt::Display for Wildcard {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 match self {
202 Wildcard::None => write!(f, ""),
203 Wildcard::Unhardened => write!(f, "/*"),
204 Wildcard::Hardened => write!(f, "/*h"),
205 }
206 }
207}
208
209impl fmt::Display for SinglePub {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 maybe_fmt_master_id(f, &self.origin)?;
212 match self.key {
213 SinglePubKey::FullKey(full_key) => full_key.fmt(f),
214 SinglePubKey::XOnly(x_only_key) => x_only_key.fmt(f),
215 }?;
216 Ok(())
217 }
218}
219
220impl MiniscriptKey for SinglePub {
221 type Sha256 = sha256::Hash;
222 type Hash256 = hash256::Hash;
223 type Ripemd160 = ripemd160::Hash;
224 type Hash160 = hash160::Hash;
225
226 fn is_x_only_key(&self) -> bool {
227 matches!(self.key, SinglePubKey::XOnly(_))
228 }
229
230 fn num_der_paths(&self) -> usize {
231 0
232 }
233
234 fn is_uncompressed(&self) -> bool {
235 match self.key {
236 SinglePubKey::FullKey(ref key) => key.is_uncompressed(),
237 _ => false,
238 }
239 }
240}
241
242impl SinglePriv {
243 fn to_public<C: Signing>(&self, secp: &Secp256k1<C>) -> SinglePub {
245 let pub_key = self.key.public_key(secp);
246
247 SinglePub {
248 origin: self.origin.clone(),
249 key: SinglePubKey::FullKey(pub_key),
250 }
251 }
252}
253
254impl DescriptorXKey<bip32::Xpriv> {
255 fn to_public<C: Signing>(
262 &self,
263 secp: &Secp256k1<C>,
264 ) -> Result<DescriptorXKey<bip32::Xpub>, DescriptorKeyParseError> {
265 let unhardened = self
266 .derivation_path
267 .into_iter()
268 .rev()
269 .take_while(|c| c.is_normal())
270 .count();
271 let last_hardened_idx = self.derivation_path.len() - unhardened;
272
273 let hardened_path = &self.derivation_path[..last_hardened_idx];
274 let unhardened_path = &self.derivation_path[last_hardened_idx..];
275
276 let xprv = self
277 .xkey
278 .derive_priv(secp, &hardened_path)
279 .map_err(|_| DescriptorKeyParseError("Unable to derive the hardened steps"))?;
280 let xpub = bip32::Xpub::from_priv(secp, &xprv);
281
282 let origin = match &self.origin {
283 Some((fingerprint, path)) => Some((
284 *fingerprint,
285 path.into_iter()
286 .chain(hardened_path.iter())
287 .cloned()
288 .collect(),
289 )),
290 None => {
291 if hardened_path.is_empty() {
292 None
293 } else {
294 Some((self.xkey.fingerprint(secp), hardened_path.into()))
295 }
296 }
297 };
298
299 Ok(DescriptorXKey {
300 origin,
301 xkey: xpub,
302 derivation_path: unhardened_path.into(),
303 wildcard: self.wildcard,
304 })
305 }
306}
307
308impl<K: InnerXKey> fmt::Display for DescriptorXKey<K> {
309 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310 maybe_fmt_master_id(f, &self.origin)?;
311 self.xkey.fmt(f)?;
312 fmt_derivation_path(f, &self.derivation_path)?;
313 self.wildcard.fmt(f)?;
314 Ok(())
315 }
316}
317
318impl<K> MiniscriptKey for DescriptorXKey<K>
319where
320 K: InnerXKey + Clone + Ord + Eq + hash::Hash + fmt::Debug,
321{
322 type Sha256 = sha256::Hash;
323 type Hash256 = hash256::Hash;
324 type Ripemd160 = ripemd160::Hash;
325 type Hash160 = hash160::Hash;
326
327 fn is_x_only_key(&self) -> bool {
328 false
329 }
330
331 fn num_der_paths(&self) -> usize {
332 1
333 }
334}
335
336impl<K: InnerXKey> fmt::Display for DescriptorMultiXKey<K> {
337 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
338 maybe_fmt_master_id(f, &self.origin)?;
339 self.xkey.fmt(f)?;
340 fmt_derivation_paths(f, self.derivation_paths.paths())?;
341 self.wildcard.fmt(f)?;
342 Ok(())
343 }
344}
345
346impl<K> MiniscriptKey for DescriptorMultiXKey<K>
347where
348 K: InnerXKey + Clone + Ord + Eq + hash::Hash + fmt::Debug,
349{
350 type Sha256 = sha256::Hash;
351 type Hash256 = hash256::Hash;
352 type Ripemd160 = ripemd160::Hash;
353 type Hash160 = hash160::Hash;
354
355 fn is_x_only_key(&self) -> bool {
356 false
357 }
358
359 fn num_der_paths(&self) -> usize {
360 self.derivation_paths.paths().len()
361 }
362}
363
364#[derive(Debug, PartialEq, Clone, Copy)]
367pub struct DescriptorKeyParseError(&'static str);
368
369impl fmt::Display for DescriptorKeyParseError {
370 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371 f.write_str(self.0)
372 }
373}
374
375impl error::Error for DescriptorKeyParseError {
376 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
377 None
378 }
379}
380
381impl fmt::Display for DescriptorPublicKey {
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 match *self {
384 Self::Single(ref pk) => pk.fmt(f),
385 Self::XPub(ref xpub) => xpub.fmt(f),
386 Self::MultiXPub(ref xpub) => xpub.fmt(f),
387 }
388 }
389}
390
391impl DescriptorSecretKey {
392 pub fn to_public<C: Signing>(
401 &self,
402 secp: &Secp256k1<C>,
403 ) -> Result<DescriptorPublicKey, DescriptorKeyParseError> {
404 let pk = match self {
405 DescriptorSecretKey::Single(prv) => DescriptorPublicKey::Single(prv.to_public(secp)),
406 DescriptorSecretKey::XPrv(xprv) => DescriptorPublicKey::XPub(xprv.to_public(secp)?),
407 DescriptorSecretKey::MultiXPrv(_) => {
408 return Err(DescriptorKeyParseError(
409 "Can't make an extended private key with multiple paths into a public key.",
410 ))
411 }
412 };
413
414 Ok(pk)
415 }
416
417 pub fn is_multipath(&self) -> bool {
419 match *self {
420 DescriptorSecretKey::Single(..) | DescriptorSecretKey::XPrv(..) => false,
421 DescriptorSecretKey::MultiXPrv(_) => true,
422 }
423 }
424
425 pub fn into_single_keys(self) -> Vec<DescriptorSecretKey> {
431 match self {
432 DescriptorSecretKey::Single(..) | DescriptorSecretKey::XPrv(..) => vec![self],
433 DescriptorSecretKey::MultiXPrv(xpub) => {
434 let DescriptorMultiXKey {
435 origin,
436 xkey,
437 derivation_paths,
438 wildcard,
439 } = xpub;
440 derivation_paths
441 .into_paths()
442 .into_iter()
443 .map(|derivation_path| {
444 DescriptorSecretKey::XPrv(DescriptorXKey {
445 origin: origin.clone(),
446 xkey,
447 derivation_path,
448 wildcard,
449 })
450 })
451 .collect()
452 }
453 }
454 }
455}
456
457pub(crate) fn maybe_fmt_master_id(
459 f: &mut fmt::Formatter<'_>,
460 origin: &Option<(bip32::Fingerprint, bip32::DerivationPath)>,
461) -> fmt::Result {
462 if let Some((ref master_id, ref master_deriv)) = *origin {
463 fmt::Formatter::write_str(f, "[")?;
464 for byte in master_id.as_bytes() {
465 write!(f, "{:02x}", byte)?;
466 }
467 fmt_derivation_path(f, master_deriv)?;
468 fmt::Formatter::write_str(f, "]")?;
469 }
470
471 Ok(())
472}
473
474fn fmt_derivation_path(f: &mut fmt::Formatter<'_>, path: &bip32::DerivationPath) -> fmt::Result {
476 for child in path {
477 write!(f, "/{}", child)?;
478 }
479 Ok(())
480}
481
482fn fmt_derivation_paths(f: &mut fmt::Formatter, paths: &[bip32::DerivationPath]) -> fmt::Result {
486 for (i, child) in paths[0].into_iter().enumerate() {
487 if paths.len() > 1 && child != &paths[1][i] {
488 write!(f, "/<")?;
489 for (j, p) in paths.iter().enumerate() {
490 write!(f, "{}", p[i])?;
491 if j != paths.len() - 1 {
492 write!(f, ";")?;
493 }
494 }
495 write!(f, ">")?;
496 } else {
497 write!(f, "/{}", child)?;
498 }
499 }
500 Ok(())
501}
502
503impl FromStr for DescriptorPublicKey {
504 type Err = DescriptorKeyParseError;
505
506 fn from_str(s: &str) -> Result<Self, Self::Err> {
507 if s.len() < 64 {
509 return Err(DescriptorKeyParseError(
510 "Key too short (<66 char), doesn't match any format",
511 ));
512 }
513
514 let (key_part, origin) = parse_key_origin(s)?;
515
516 if key_part.contains("pub") {
517 let (xpub, derivation_paths, wildcard) = parse_xkey_deriv::<bip32::Xpub>(key_part)?;
518 if derivation_paths.len() > 1 {
519 Ok(DescriptorPublicKey::MultiXPub(DescriptorMultiXKey {
520 origin,
521 xkey: xpub,
522 derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
523 wildcard,
524 }))
525 } else {
526 Ok(DescriptorPublicKey::XPub(DescriptorXKey {
527 origin,
528 xkey: xpub,
529 derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
530 wildcard,
531 }))
532 }
533 } else {
534 let key = match key_part.len() {
535 64 => {
536 let x_only_key =
537 bitcoin::key::XOnlyPublicKey::from_str(key_part).map_err(|_| {
538 DescriptorKeyParseError("Error while parsing simple xonly key")
539 })?;
540 SinglePubKey::XOnly(x_only_key)
541 }
542 66 | 130 => {
543 if !(&key_part[0..2] == "02"
544 || &key_part[0..2] == "03"
545 || &key_part[0..2] == "04")
546 {
547 return Err(DescriptorKeyParseError(
548 "Only publickeys with prefixes 02/03/04 are allowed",
549 ));
550 }
551 let key = bitcoin::PublicKey::from_str(key_part).map_err(|_| {
552 DescriptorKeyParseError("Error while parsing simple public key")
553 })?;
554 SinglePubKey::FullKey(key)
555 }
556 _ => {
557 return Err(DescriptorKeyParseError(
558 "Public keys must be 64/66/130 characters in size",
559 ))
560 }
561 };
562 Ok(DescriptorPublicKey::Single(SinglePub { key, origin }))
563 }
564 }
565}
566
567#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
569pub enum ConversionError {
570 HardenedChild,
572 MultiKey,
574}
575
576impl fmt::Display for ConversionError {
577 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
578 f.write_str(match *self {
579 ConversionError::HardenedChild => "hardened child step in bip32 path",
580 ConversionError::MultiKey => "multiple existing keys",
581 })
582 }
583}
584
585impl error::Error for ConversionError {
586 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
587 use self::ConversionError::*;
588
589 match self {
590 HardenedChild | MultiKey => None,
591 }
592 }
593}
594
595impl DescriptorPublicKey {
596 pub fn master_fingerprint(&self) -> bip32::Fingerprint {
598 match *self {
599 DescriptorPublicKey::XPub(ref xpub) => {
600 if let Some((fingerprint, _)) = xpub.origin {
601 fingerprint
602 } else {
603 xpub.xkey.fingerprint()
604 }
605 }
606 DescriptorPublicKey::MultiXPub(ref xpub) => {
607 if let Some((fingerprint, _)) = xpub.origin {
608 fingerprint
609 } else {
610 xpub.xkey.fingerprint()
611 }
612 }
613 DescriptorPublicKey::Single(ref single) => {
614 if let Some((fingerprint, _)) = single.origin {
615 fingerprint
616 } else {
617 let mut engine = XKeyIdentifier::engine();
618 match single.key {
619 SinglePubKey::FullKey(pk) => {
620 pk.write_into(&mut engine).expect("engines don't error")
621 }
622 SinglePubKey::XOnly(x_only_pk) => engine.input(&x_only_pk.serialize()),
623 };
624 bip32::Fingerprint::from(
625 &XKeyIdentifier::from_engine(engine)[..4]
626 .try_into()
627 .expect("4 byte slice"),
628 )
629 }
630 }
631 }
632 }
633
634 pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
642 match *self {
643 DescriptorPublicKey::XPub(ref xpub) => {
644 let origin_path = if let Some((_, ref path)) = xpub.origin {
645 path.clone()
646 } else {
647 bip32::DerivationPath::from(vec![])
648 };
649 Some(origin_path.extend(&xpub.derivation_path))
650 }
651 DescriptorPublicKey::Single(ref single) => {
652 Some(if let Some((_, ref path)) = single.origin {
653 path.clone()
654 } else {
655 bip32::DerivationPath::from(vec![])
656 })
657 }
658 DescriptorPublicKey::MultiXPub(_) => None,
659 }
660 }
661
662 #[deprecated(note = "use has_wildcard instead")]
664 pub fn is_deriveable(&self) -> bool {
665 self.has_wildcard()
666 }
667
668 pub fn has_wildcard(&self) -> bool {
670 match *self {
671 DescriptorPublicKey::Single(..) => false,
672 DescriptorPublicKey::XPub(ref xpub) => xpub.wildcard != Wildcard::None,
673 DescriptorPublicKey::MultiXPub(ref xpub) => xpub.wildcard != Wildcard::None,
674 }
675 }
676
677 #[deprecated(note = "use at_derivation_index instead")]
678 pub fn derive(self, index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
680 self.at_derivation_index(index)
681 }
682
683 pub fn at_derivation_index(self, index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
696 let definite = match self {
697 DescriptorPublicKey::Single(_) => self,
698 DescriptorPublicKey::XPub(xpub) => {
699 let derivation_path = match xpub.wildcard {
700 Wildcard::None => xpub.derivation_path,
701 Wildcard::Unhardened => xpub.derivation_path.into_child(
702 bip32::ChildNumber::from_normal_idx(index)
703 .ok()
704 .ok_or(ConversionError::HardenedChild)?,
705 ),
706 Wildcard::Hardened => xpub.derivation_path.into_child(
707 bip32::ChildNumber::from_hardened_idx(index)
708 .ok()
709 .ok_or(ConversionError::HardenedChild)?,
710 ),
711 };
712 DescriptorPublicKey::XPub(DescriptorXKey {
713 origin: xpub.origin,
714 xkey: xpub.xkey,
715 derivation_path,
716 wildcard: Wildcard::None,
717 })
718 }
719 DescriptorPublicKey::MultiXPub(_) => return Err(ConversionError::MultiKey),
720 };
721
722 Ok(DefiniteDescriptorKey::new(definite)
723 .expect("The key should not contain any wildcards at this point"))
724 }
725
726 pub fn is_multipath(&self) -> bool {
728 match *self {
729 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
730 DescriptorPublicKey::MultiXPub(_) => true,
731 }
732 }
733
734 pub fn into_single_keys(self) -> Vec<DescriptorPublicKey> {
740 match self {
741 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => vec![self],
742 DescriptorPublicKey::MultiXPub(xpub) => {
743 let DescriptorMultiXKey {
744 origin,
745 xkey,
746 derivation_paths,
747 wildcard,
748 } = xpub;
749 derivation_paths
750 .into_paths()
751 .into_iter()
752 .map(|derivation_path| {
753 DescriptorPublicKey::XPub(DescriptorXKey {
754 origin: origin.clone(),
755 xkey,
756 derivation_path,
757 wildcard,
758 })
759 })
760 .collect()
761 }
762 }
763 }
764}
765
766impl DescriptorSecretKey {
767 pub(crate) fn from_str_inner(
768 s: &str,
769 single_hex: bool,
770 ) -> Result<Self, DescriptorKeyParseError> {
771 let (key_part, origin) = parse_key_origin(s)?;
772
773 if single_hex && key_part.len() == 64 {
774 let bytes = Vec::<u8>::from_hex(key_part)
775 .map_err(|_| DescriptorKeyParseError("Error while parsing a HEX private key"))?;
776 let network = bitcoin::network::Network::Bitcoin; let sk = bitcoin::PrivateKey::from_slice(&bytes, network)
778 .map_err(|_| DescriptorKeyParseError("Error while parsing a HEX private key"))?;
779 Ok(DescriptorSecretKey::Single(SinglePriv {
780 key: sk,
781 origin: None,
782 }))
783 } else if !single_hex && key_part.len() <= 52 {
784 let sk = bitcoin::PrivateKey::from_str(key_part)
785 .map_err(|_| DescriptorKeyParseError("Error while parsing a WIF private key"))?;
786 Ok(DescriptorSecretKey::Single(SinglePriv {
787 key: sk,
788 origin: None,
789 }))
790 } else {
791 let (xpriv, derivation_paths, wildcard) = parse_xkey_deriv::<bip32::Xpriv>(key_part)?;
792 if derivation_paths.len() > 1 {
793 Ok(DescriptorSecretKey::MultiXPrv(DescriptorMultiXKey {
794 origin,
795 xkey: xpriv,
796 derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
797 wildcard,
798 }))
799 } else {
800 Ok(DescriptorSecretKey::XPrv(DescriptorXKey {
801 origin,
802 xkey: xpriv,
803 derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
804 wildcard,
805 }))
806 }
807 }
808 }
809}
810
811impl FromStr for DescriptorSecretKey {
812 type Err = DescriptorKeyParseError;
813
814 fn from_str(s: &str) -> Result<Self, Self::Err> {
815 Self::from_str_inner(s, false)
816 }
817}
818
819fn parse_key_origin(s: &str) -> Result<(&str, Option<bip32::KeySource>), DescriptorKeyParseError> {
821 for ch in s.as_bytes() {
822 if *ch < 20 || *ch > 127 {
823 return Err(DescriptorKeyParseError(
824 "Encountered an unprintable character",
825 ));
826 }
827 }
828
829 if s.is_empty() {
830 return Err(DescriptorKeyParseError("Empty key"));
831 }
832 let mut parts = s[1..].split(']');
833
834 if let Some('[') = s.chars().next() {
835 let mut raw_origin = parts
836 .next()
837 .ok_or(DescriptorKeyParseError("Unclosed '['"))?
838 .split('/');
839
840 let origin_id_hex = raw_origin.next().ok_or(DescriptorKeyParseError(
841 "No master fingerprint found after '['",
842 ))?;
843
844 if origin_id_hex.len() != 8 {
845 return Err(DescriptorKeyParseError(
846 "Master fingerprint should be 8 characters long",
847 ));
848 }
849 let parent_fingerprint = bip32::Fingerprint::from_str(origin_id_hex).map_err(|_| {
850 DescriptorKeyParseError("Malformed master fingerprint, expected 8 hex chars")
851 })?;
852 let origin_path = raw_origin
853 .map(bip32::ChildNumber::from_str)
854 .collect::<Result<bip32::DerivationPath, bip32::Error>>()
855 .map_err(|_| DescriptorKeyParseError("Error while parsing master derivation path"))?;
856
857 let key = parts
858 .next()
859 .ok_or(DescriptorKeyParseError("No key after origin."))?;
860
861 if parts.next().is_some() {
862 Err(DescriptorKeyParseError(
863 "Multiple ']' in Descriptor Public Key",
864 ))
865 } else {
866 Ok((key, Some((parent_fingerprint, origin_path))))
867 }
868 } else {
869 Ok((s, None))
870 }
871}
872
873fn parse_xkey_deriv<K: InnerXKey>(
875 key_deriv: &str,
876) -> Result<(K, Vec<bip32::DerivationPath>, Wildcard), DescriptorKeyParseError> {
877 let mut key_deriv = key_deriv.split('/');
878 let xkey_str = key_deriv.next().ok_or(DescriptorKeyParseError(
879 "No key found after origin description",
880 ))?;
881 let xkey =
882 K::from_str(xkey_str).map_err(|_| DescriptorKeyParseError("Error while parsing xkey."))?;
883
884 let mut wildcard = Wildcard::None;
885 let mut multipath = false;
886 let derivation_paths = key_deriv
887 .filter_map(|p| {
888 if wildcard == Wildcard::None && p == "*" {
889 wildcard = Wildcard::Unhardened;
890 None
891 } else if wildcard == Wildcard::None && (p == "*'" || p == "*h") {
892 wildcard = Wildcard::Hardened;
893 None
894 } else if wildcard != Wildcard::None {
895 Some(Err(DescriptorKeyParseError(
896 "'*' may only appear as last element in a derivation path.",
897 )))
898 } else {
899 if p.starts_with('<') && p.ends_with('>') {
902 if multipath {
904 return Some(Err(DescriptorKeyParseError(
905 "'<' may only appear once in a derivation path.",
906 )));
907 }
908 multipath = true;
909
910 if p.len() < 5 || !p.contains(';') {
913 return Some(Err(DescriptorKeyParseError(
914 "Invalid multi index step in multipath descriptor.",
915 )));
916 }
917
918 let indexes = p[1..p.len() - 1].split(';');
920 Some(
921 indexes
922 .into_iter()
923 .map(|s| {
924 bip32::ChildNumber::from_str(s).map_err(|_| {
925 DescriptorKeyParseError(
926 "Error while parsing index in key derivation path.",
927 )
928 })
929 })
930 .collect::<Result<Vec<bip32::ChildNumber>, _>>(),
931 )
932 } else {
933 Some(
935 bip32::ChildNumber::from_str(p)
936 .map(|i| vec![i])
937 .map_err(|_| {
938 DescriptorKeyParseError("Error while parsing key derivation path")
939 }),
940 )
941 }
942 }
943 })
944 .try_fold(Vec::new(), |mut paths, index_list| {
950 let mut index_list = index_list?.into_iter();
951 let first_index = index_list
952 .next()
953 .expect("There is always at least one element");
954
955 if paths.is_empty() {
956 paths.push(vec![first_index]);
957 } else {
958 for path in paths.iter_mut() {
959 path.push(first_index);
960 }
961 }
962
963 for (i, index) in index_list.enumerate() {
965 paths.push(paths[0].clone());
966 *paths[i + 1].last_mut().expect("Never empty") = index;
967 }
968
969 Ok(paths)
970 })?
971 .into_iter()
972 .map(|index_list| index_list.into_iter().collect::<bip32::DerivationPath>())
973 .collect::<Vec<bip32::DerivationPath>>();
974
975 Ok((xkey, derivation_paths, wildcard))
976}
977
978impl<K: InnerXKey> DescriptorXKey<K> {
979 pub fn matches<C: Signing>(
1012 &self,
1013 keysource: &bip32::KeySource,
1014 secp: &Secp256k1<C>,
1015 ) -> Option<bip32::DerivationPath> {
1016 let (fingerprint, path) = keysource;
1017
1018 let (compare_fingerprint, compare_path) = match self.origin {
1019 Some((fingerprint, ref path)) => (
1020 fingerprint,
1021 path.into_iter()
1022 .chain(&self.derivation_path)
1023 .collect(),
1024 ),
1025 None => (
1026 self.xkey.xkey_fingerprint(secp),
1027 self.derivation_path.into_iter().collect::<Vec<_>>(),
1028 ),
1029 };
1030
1031 let path_excluding_wildcard =
1032 if self.wildcard != Wildcard::None && !path.as_ref().is_empty() {
1033 path.into_iter()
1034 .take(path.as_ref().len() - 1)
1035 .cloned()
1036 .collect()
1037 } else {
1038 path.clone()
1039 };
1040
1041 if &compare_fingerprint == fingerprint
1042 && compare_path
1043 .into_iter()
1044 .eq(&path_excluding_wildcard)
1045 {
1046 Some(path_excluding_wildcard)
1047 } else {
1048 None
1049 }
1050 }
1051}
1052
1053impl MiniscriptKey for DescriptorPublicKey {
1054 type Sha256 = sha256::Hash;
1055 type Hash256 = hash256::Hash;
1056 type Ripemd160 = ripemd160::Hash;
1057 type Hash160 = hash160::Hash;
1058
1059 fn is_uncompressed(&self) -> bool {
1060 match self {
1061 DescriptorPublicKey::Single(SinglePub {
1062 key: SinglePubKey::FullKey(ref key),
1063 ..
1064 }) => key.is_uncompressed(),
1065 _ => false,
1066 }
1067 }
1068
1069 fn is_x_only_key(&self) -> bool {
1070 matches!(
1071 self,
1072 DescriptorPublicKey::Single(SinglePub {
1073 key: SinglePubKey::XOnly(ref _key),
1074 ..
1075 }),
1076 )
1077 }
1078
1079 fn num_der_paths(&self) -> usize {
1080 match self {
1081 DescriptorPublicKey::Single(single) => single.num_der_paths(),
1082 DescriptorPublicKey::XPub(xpub) => xpub.num_der_paths(),
1083 DescriptorPublicKey::MultiXPub(xpub) => xpub.num_der_paths(),
1084 }
1085 }
1086}
1087
1088impl DefiniteDescriptorKey {
1089 pub fn derive_public_key<C: Verification>(
1099 &self,
1100 secp: &Secp256k1<C>,
1101 ) -> Result<bitcoin::PublicKey, ConversionError> {
1102 match self.0 {
1103 DescriptorPublicKey::Single(ref pk) => match pk.key {
1104 SinglePubKey::FullKey(pk) => Ok(pk),
1105 SinglePubKey::XOnly(xpk) => Ok(xpk.to_public_key()),
1106 },
1107 DescriptorPublicKey::XPub(ref xpk) => match xpk.wildcard {
1108 Wildcard::Unhardened | Wildcard::Hardened => {
1109 unreachable!("we've excluded this error case")
1110 }
1111 Wildcard::None => match xpk.xkey.derive_pub(secp, &xpk.derivation_path.as_ref()) {
1112 Ok(xpub) => Ok(bitcoin::PublicKey::new(xpub.public_key)),
1113 Err(bip32::Error::CannotDeriveFromHardenedKey) => {
1114 Err(ConversionError::HardenedChild)
1115 }
1116 Err(e) => unreachable!("cryptographically unreachable: {}", e),
1117 },
1118 },
1119 DescriptorPublicKey::MultiXPub(_) => {
1120 unreachable!("A definite key cannot contain a multipath key.")
1121 }
1122 }
1123 }
1124
1125 fn new(key: DescriptorPublicKey) -> Option<Self> {
1129 if key.has_wildcard() {
1130 None
1131 } else {
1132 Some(Self(key))
1133 }
1134 }
1135
1136 pub fn master_fingerprint(&self) -> bip32::Fingerprint {
1138 self.0.master_fingerprint()
1139 }
1140
1141 pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
1143 self.0.full_derivation_path()
1144 }
1145
1146 pub fn as_descriptor_public_key(&self) -> &DescriptorPublicKey {
1148 &self.0
1149 }
1150
1151 pub fn into_descriptor_public_key(self) -> DescriptorPublicKey {
1153 self.0
1154 }
1155}
1156
1157impl FromStr for DefiniteDescriptorKey {
1158 type Err = DescriptorKeyParseError;
1159
1160 fn from_str(s: &str) -> Result<Self, Self::Err> {
1161 let inner = DescriptorPublicKey::from_str(s)?;
1162 DefiniteDescriptorKey::new(inner).ok_or(DescriptorKeyParseError(
1163 "cannot parse key with a wilcard as a DerivedDescriptorKey",
1164 ))
1165 }
1166}
1167
1168impl fmt::Display for DefiniteDescriptorKey {
1169 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1170 self.0.fmt(f)
1171 }
1172}
1173
1174impl MiniscriptKey for DefiniteDescriptorKey {
1175 type Sha256 = sha256::Hash;
1176 type Hash256 = hash256::Hash;
1177 type Ripemd160 = ripemd160::Hash;
1178 type Hash160 = hash160::Hash;
1179
1180 fn is_uncompressed(&self) -> bool {
1181 self.0.is_uncompressed()
1182 }
1183
1184 fn is_x_only_key(&self) -> bool {
1185 self.0.is_x_only_key()
1186 }
1187
1188 fn num_der_paths(&self) -> usize {
1189 self.0.num_der_paths()
1190 }
1191}
1192
1193impl ToPublicKey for DefiniteDescriptorKey {
1194 fn to_public_key(&self) -> bitcoin::PublicKey {
1195 let secp = Secp256k1::verification_only();
1196 self.derive_public_key(&secp).unwrap()
1197 }
1198
1199 fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
1200 *hash
1201 }
1202
1203 fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
1204 *hash
1205 }
1206
1207 fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash {
1208 *hash
1209 }
1210
1211 fn to_hash160(hash: &hash160::Hash) -> hash160::Hash {
1212 *hash
1213 }
1214}
1215
1216impl From<DefiniteDescriptorKey> for DescriptorPublicKey {
1217 fn from(d: DefiniteDescriptorKey) -> Self {
1218 d.0
1219 }
1220}
1221
1222impl Borrow<DescriptorPublicKey> for DefiniteDescriptorKey {
1223 fn borrow(&self) -> &DescriptorPublicKey {
1224 &self.0
1225 }
1226}
1227
1228#[cfg(feature = "serde")]
1229impl<'de> Deserialize<'de> for DescriptorPublicKey {
1230 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1231 where
1232 D: Deserializer<'de>,
1233 {
1234 let s = String::deserialize(deserializer)?;
1235 DescriptorPublicKey::from_str(&s).map_err(crate::serde::de::Error::custom)
1236 }
1237}
1238
1239#[cfg(feature = "serde")]
1240impl Serialize for DescriptorPublicKey {
1241 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1242 where
1243 S: Serializer,
1244 {
1245 serializer.serialize_str(&self.to_string())
1246 }
1247}
1248
1249#[cfg(test)]
1250mod test {
1251 use std::str::FromStr;
1252
1253 use bitcoin::{bip32, secp256k1};
1254 use elements::secp256k1_zkp;
1255 #[cfg(feature = "serde")]
1256 use serde_test::{assert_tokens, Token};
1257
1258 use super::{
1259 DescriptorKeyParseError, DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey,
1260 MiniscriptKey, Wildcard,
1261 };
1262
1263 #[test]
1264 fn parse_descriptor_key_errors() {
1265 let desc = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*/44";
1267 assert_eq!(
1268 DescriptorPublicKey::from_str(desc),
1269 Err(DescriptorKeyParseError(
1270 "\'*\' may only appear as last element in a derivation path."
1271 ))
1272 );
1273
1274 let desc = "[NonHexor]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*";
1276 assert_eq!(
1277 DescriptorPublicKey::from_str(desc),
1278 Err(DescriptorKeyParseError(
1279 "Malformed master fingerprint, expected 8 hex chars"
1280 ))
1281 );
1282
1283 let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*";
1285 assert_eq!(
1286 DescriptorPublicKey::from_str(desc),
1287 Err(DescriptorKeyParseError("Error while parsing xkey."))
1288 );
1289
1290 let desc = "[78412e3a]0208a117f3897c3a13c9384b8695eed98dc31bc2500feb19a1af424cd47a5d83/1/*";
1292 assert_eq!(
1293 DescriptorPublicKey::from_str(desc),
1294 Err(DescriptorKeyParseError(
1295 "Public keys must be 64/66/130 characters in size"
1296 ))
1297 );
1298
1299 let desc = "[78412e3a]]03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
1301 assert_eq!(
1302 DescriptorPublicKey::from_str(desc),
1303 Err(DescriptorKeyParseError(
1304 "Multiple \']\' in Descriptor Public Key"
1305 ))
1306 );
1307
1308 let desc = "[11111f11]033333333333333333333333333333323333333333333333333333333433333333]]333]]3]]101333333333333433333]]]10]333333mmmm";
1310 assert_eq!(
1311 DescriptorPublicKey::from_str(desc),
1312 Err(DescriptorKeyParseError(
1313 "Multiple \']\' in Descriptor Public Key"
1314 ))
1315 );
1316
1317 let desc = "0777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777";
1319 assert_eq!(
1320 DescriptorPublicKey::from_str(desc),
1321 Err(DescriptorKeyParseError(
1322 "Only publickeys with prefixes 02/03/04 are allowed"
1323 ))
1324 );
1325 }
1326
1327 #[test]
1328 fn parse_descriptor_secret_key_error() {
1329 let secret_key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
1331 assert_eq!(
1332 DescriptorSecretKey::from_str(secret_key),
1333 Err(DescriptorKeyParseError("Error while parsing xkey."))
1334 );
1335
1336 let desc = "[NonHexor]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/*";
1338 assert_eq!(
1339 DescriptorSecretKey::from_str(desc),
1340 Err(DescriptorKeyParseError(
1341 "Malformed master fingerprint, expected 8 hex chars"
1342 ))
1343 );
1344
1345 let desc = "[78412e3a]L32jTfVLei6BYTPUpwpJSkrHx8iL9GZzeErVS8y4Y/1/*";
1347 assert_eq!(
1348 DescriptorSecretKey::from_str(desc),
1349 Err(DescriptorKeyParseError(
1350 "Error while parsing a WIF private key"
1351 ))
1352 );
1353 }
1354
1355 #[test]
1356 fn test_wildcard() {
1357 let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2").unwrap();
1358 assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1359 assert_eq!(
1360 public_key.full_derivation_path().unwrap().to_string(),
1361 "0'/1'/2"
1362 );
1363 assert!(!public_key.has_wildcard());
1364
1365 let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*").unwrap();
1366 assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1367 assert_eq!(
1368 public_key.full_derivation_path().unwrap().to_string(),
1369 "0'/1'"
1370 );
1371 assert!(public_key.has_wildcard());
1372
1373 let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*h").unwrap();
1374 assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1375 assert_eq!(
1376 public_key.full_derivation_path().unwrap().to_string(),
1377 "0'/1'"
1378 );
1379 assert!(public_key.has_wildcard());
1380 }
1381
1382 #[test]
1383 fn test_deriv_on_xprv() {
1384 let secp = secp256k1_zkp::Secp256k1::signing_only();
1385
1386 let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2").unwrap();
1387 let public_key = secret_key.to_public(&secp).unwrap();
1388 assert_eq!(public_key.to_string(), "[2cbe2a6d/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2");
1389 assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1390 assert_eq!(
1391 public_key.full_derivation_path().unwrap().to_string(),
1392 "0'/1'/2"
1393 );
1394 assert!(!public_key.has_wildcard());
1395
1396 let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2'").unwrap();
1397 let public_key = secret_key.to_public(&secp).unwrap();
1398 assert_eq!(public_key.to_string(), "[2cbe2a6d/0'/1'/2']tpubDDPuH46rv4dbFtmF6FrEtJEy1CvLZonyBoVxF6xsesHdYDdTBrq2mHhm8AbsPh39sUwL2nZyxd6vo4uWNTU9v4t893CwxjqPnwMoUACLvMV");
1399 assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1400 assert_eq!(
1401 public_key.full_derivation_path().unwrap().to_string(),
1402 "0'/1'/2'"
1403 );
1404
1405 let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0/1/2").unwrap();
1406 let public_key = secret_key.to_public(&secp).unwrap();
1407 assert_eq!(public_key.to_string(), "tpubD6NzVbkrYhZ4WQdzxL7NmJN7b85ePo4p6RSj9QQHF7te2RR9iUeVSGgnGkoUsB9LBRosgvNbjRv9bcsJgzgBd7QKuxDm23ZewkTRzNSLEDr/0/1/2");
1408 assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1409 assert_eq!(
1410 public_key.full_derivation_path().unwrap().to_string(),
1411 "0/1/2"
1412 );
1413
1414 let secret_key = DescriptorSecretKey::from_str("[aabbccdd]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0/1/2").unwrap();
1415 let public_key = secret_key.to_public(&secp).unwrap();
1416 assert_eq!(public_key.to_string(), "[aabbccdd]tpubD6NzVbkrYhZ4WQdzxL7NmJN7b85ePo4p6RSj9QQHF7te2RR9iUeVSGgnGkoUsB9LBRosgvNbjRv9bcsJgzgBd7QKuxDm23ZewkTRzNSLEDr/0/1/2");
1417 assert_eq!(public_key.master_fingerprint().to_string(), "aabbccdd");
1418 assert_eq!(
1419 public_key.full_derivation_path().unwrap().to_string(),
1420 "0/1/2"
1421 );
1422
1423 let secret_key = DescriptorSecretKey::from_str("[aabbccdd/90']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2").unwrap();
1424 let public_key = secret_key.to_public(&secp).unwrap();
1425 assert_eq!(public_key.to_string(), "[aabbccdd/90'/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2");
1426 assert_eq!(public_key.master_fingerprint().to_string(), "aabbccdd");
1427 assert_eq!(
1428 public_key.full_derivation_path().unwrap().to_string(),
1429 "90'/0'/1'/2"
1430 );
1431 }
1432
1433 #[test]
1434 fn test_master_fingerprint() {
1435 assert_eq!(
1436 DescriptorPublicKey::from_str(
1437 "02a489e0ea42b56148d212d325b7c67c6460483ff931c303ea311edfef667c8f35",
1438 )
1439 .unwrap()
1440 .master_fingerprint()
1441 .as_bytes(),
1442 b"\xb0\x59\x11\x6a"
1443 );
1444 }
1445
1446 fn get_multipath_xpub(key_str: &str, num_paths: usize) -> DescriptorMultiXKey<bip32::Xpub> {
1447 let desc_key = DescriptorPublicKey::from_str(key_str).unwrap();
1448 assert_eq!(desc_key.num_der_paths(), num_paths);
1449 match desc_key {
1450 DescriptorPublicKey::MultiXPub(xpub) => xpub,
1451 _ => unreachable!(),
1452 }
1453 }
1454
1455 fn get_multipath_xprv(key_str: &str) -> DescriptorMultiXKey<bip32::Xpriv> {
1456 let desc_key = DescriptorSecretKey::from_str(key_str).unwrap();
1457 match desc_key {
1458 DescriptorSecretKey::MultiXPrv(xprv) => xprv,
1459 _ => unreachable!(),
1460 }
1461 }
1462
1463 #[test]
1464 fn multipath_extended_keys() {
1465 let secp = secp256k1::Secp256k1::signing_only();
1466
1467 let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;42;9854>", 4);
1469 assert_eq!(
1470 xpub.derivation_paths.paths(),
1471 &vec![
1472 bip32::DerivationPath::from_str("m/2/0").unwrap(),
1473 bip32::DerivationPath::from_str("m/2/1").unwrap(),
1474 bip32::DerivationPath::from_str("m/2/42").unwrap(),
1475 bip32::DerivationPath::from_str("m/2/9854").unwrap()
1476 ],
1477 );
1478 assert_eq!(
1479 xpub,
1480 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 4)
1481 );
1482 let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;9854>/0/5/10", 3);
1484 assert_eq!(
1485 xpub.derivation_paths.paths(),
1486 &vec![
1487 bip32::DerivationPath::from_str("m/2/0/0/5/10").unwrap(),
1488 bip32::DerivationPath::from_str("m/2/1/0/5/10").unwrap(),
1489 bip32::DerivationPath::from_str("m/2/9854/0/5/10").unwrap()
1490 ],
1491 );
1492 assert_eq!(
1493 xpub,
1494 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 3)
1495 );
1496 let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;9854>/3456/9876/*", 3);
1498 assert_eq!(xpub.wildcard, Wildcard::Unhardened);
1499 assert_eq!(
1500 xpub.derivation_paths.paths(),
1501 &vec![
1502 bip32::DerivationPath::from_str("m/2/0/3456/9876").unwrap(),
1503 bip32::DerivationPath::from_str("m/2/1/3456/9876").unwrap(),
1504 bip32::DerivationPath::from_str("m/2/9854/3456/9876").unwrap()
1505 ],
1506 );
1507 assert_eq!(
1508 xpub,
1509 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 3)
1510 );
1511 let xpub = get_multipath_xpub("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/<0;1>/*", 2);
1513 assert_eq!(xpub.wildcard, Wildcard::Unhardened);
1514 assert_eq!(
1515 xpub.derivation_paths.paths(),
1516 &vec![
1517 bip32::DerivationPath::from_str("m/0").unwrap(),
1518 bip32::DerivationPath::from_str("m/1").unwrap(),
1519 ],
1520 );
1521 assert_eq!(
1522 xpub,
1523 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 2)
1524 );
1525 let xpub = get_multipath_xpub("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1h>/8h/*'", 2);
1528 assert_eq!(xpub.wildcard, Wildcard::Hardened);
1529 assert_eq!(
1530 xpub.derivation_paths.paths(),
1531 &vec![
1532 bip32::DerivationPath::from_str("m/9478'/0'/8'").unwrap(),
1533 bip32::DerivationPath::from_str("m/9478h/1h/8h").unwrap(),
1534 ],
1535 );
1536 assert_eq!(
1537 xpub,
1538 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 2)
1539 );
1540 let desc_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1>/8h/*'").unwrap();
1542 assert!(desc_key.full_derivation_path().is_none());
1543 assert!(desc_key.is_multipath());
1544 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()]);
1545
1546 let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;42;9854>");
1548 assert_eq!(
1549 xprv.derivation_paths.paths(),
1550 &vec![
1551 bip32::DerivationPath::from_str("m/2/0").unwrap(),
1552 bip32::DerivationPath::from_str("m/2/1").unwrap(),
1553 bip32::DerivationPath::from_str("m/2/42").unwrap(),
1554 bip32::DerivationPath::from_str("m/2/9854").unwrap()
1555 ],
1556 );
1557 assert_eq!(
1558 xprv,
1559 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1560 );
1561 let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;9854>/0/5/10");
1562 assert_eq!(
1563 xprv.derivation_paths.paths(),
1564 &vec![
1565 bip32::DerivationPath::from_str("m/2/0/0/5/10").unwrap(),
1566 bip32::DerivationPath::from_str("m/2/1/0/5/10").unwrap(),
1567 bip32::DerivationPath::from_str("m/2/9854/0/5/10").unwrap()
1568 ],
1569 );
1570 assert_eq!(
1571 xprv,
1572 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1573 );
1574 let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;9854>/3456/9876/*");
1575 assert_eq!(xprv.wildcard, Wildcard::Unhardened);
1576 assert_eq!(
1577 xprv.derivation_paths.paths(),
1578 &vec![
1579 bip32::DerivationPath::from_str("m/2/0/3456/9876").unwrap(),
1580 bip32::DerivationPath::from_str("m/2/1/3456/9876").unwrap(),
1581 bip32::DerivationPath::from_str("m/2/9854/3456/9876").unwrap()
1582 ],
1583 );
1584 assert_eq!(
1585 xprv,
1586 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1587 );
1588 let xprv = get_multipath_xprv("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/<0;1>/*");
1589 assert_eq!(xprv.wildcard, Wildcard::Unhardened);
1590 assert_eq!(
1591 xprv.derivation_paths.paths(),
1592 &vec![
1593 bip32::DerivationPath::from_str("m/0").unwrap(),
1594 bip32::DerivationPath::from_str("m/1").unwrap(),
1595 ],
1596 );
1597 assert_eq!(
1598 xprv,
1599 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1600 );
1601 let xprv = get_multipath_xprv("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1h>/8h/*'");
1602 assert_eq!(xprv.wildcard, Wildcard::Hardened);
1603 assert_eq!(
1604 xprv.derivation_paths.paths(),
1605 &vec![
1606 bip32::DerivationPath::from_str("m/9478'/0'/8'").unwrap(),
1607 bip32::DerivationPath::from_str("m/9478h/1h/8h").unwrap(),
1608 ],
1609 );
1610 assert_eq!(
1611 xprv,
1612 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1613 );
1614 let desc_key = DescriptorSecretKey::from_str("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1>/8h/*'").unwrap();
1615 assert!(desc_key.to_public(&secp).is_err());
1616 assert!(desc_key.is_multipath());
1617 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()]);
1618
1619 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;42;9854").unwrap_err();
1624 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/0;1;42;9854>").unwrap_err();
1625 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;1>/96/<0;1>").unwrap_err();
1626 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0>").unwrap_err();
1627 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;>").unwrap_err();
1628 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<;1>").unwrap_err();
1629 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;1;>").unwrap_err();
1630 }
1631
1632 #[test]
1633 #[cfg(feature = "serde")]
1634 fn test_descriptor_public_key_serde() {
1635 let desc = "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2";
1636 let public_key = DescriptorPublicKey::from_str(desc).unwrap();
1637 assert_tokens(&public_key, &[Token::String(desc)]);
1638 }
1639}