1use core::convert::TryInto;
4use core::fmt;
5use core::str::FromStr;
6#[cfg(feature = "std")]
7use std::error;
8
9use bitcoin::bip32::{self, XKeyIdentifier};
10use bitcoin::hashes::{hash160, ripemd160, sha256, Hash, HashEngine};
11use bitcoin::key::{PublicKey, XOnlyPublicKey};
12use bitcoin::secp256k1::{Secp256k1, Signing, Verification};
13use bitcoin::NetworkKind;
14
15use super::WalletPolicyError;
16use crate::prelude::*;
17#[cfg(feature = "serde")]
18use crate::serde::{Deserialize, Deserializer, Serialize, Serializer};
19use crate::{hash256, MiniscriptKey, ToPublicKey};
20
21#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
23pub enum DescriptorPublicKey {
24 Single(SinglePub),
26 XPub(DescriptorXKey<bip32::Xpub>),
28 MultiXPub(DescriptorMultiXKey<bip32::Xpub>),
30}
31
32#[derive(Debug, Eq, PartialEq, Clone)]
34pub enum DescriptorSecretKey {
35 Single(SinglePriv),
37 XPrv(DescriptorXKey<bip32::Xpriv>),
39 MultiXPrv(DescriptorMultiXKey<bip32::Xpriv>),
41}
42
43#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
45pub struct SinglePub {
46 pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
48 pub key: SinglePubKey,
50}
51
52#[derive(Debug, Eq, PartialEq, Clone)]
54pub struct SinglePriv {
55 pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
57 pub key: bitcoin::PrivateKey,
59}
60
61#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
63pub struct DescriptorXKey<K: InnerXKey> {
64 pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
66 pub xkey: K,
68 pub derivation_path: bip32::DerivationPath,
70 pub wildcard: Wildcard,
72}
73
74#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
76pub struct DerivPaths(Vec<bip32::DerivationPath>);
77
78impl DerivPaths {
79 pub fn new(paths: Vec<bip32::DerivationPath>) -> Option<DerivPaths> {
81 if paths.is_empty() {
82 None
83 } else {
84 Some(DerivPaths(paths))
85 }
86 }
87
88 pub fn single(path: bip32::DerivationPath) -> Self { Self(vec![path]) }
90
91 pub fn paths(&self) -> &Vec<bip32::DerivationPath> { &self.0 }
93
94 pub fn into_paths(self) -> Vec<bip32::DerivationPath> { self.0 }
96}
97
98#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
100pub struct DescriptorMultiXKey<K: InnerXKey> {
101 pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
103 pub xkey: K,
105 pub derivation_paths: DerivPaths,
107 pub wildcard: Wildcard,
109}
110
111#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
113pub enum SinglePubKey {
114 FullKey(bitcoin::PublicKey),
116 XOnly(XOnlyPublicKey),
118}
119
120#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
122pub struct DefiniteDescriptorKey(DescriptorPublicKey);
123
124#[derive(Debug, Eq, PartialEq, Clone)]
126pub enum XKeyNetwork {
127 NoXKeys,
129 Mixed,
131 Single(NetworkKind),
133}
134
135impl fmt::Display for DescriptorSecretKey {
136 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137 match self {
138 DescriptorSecretKey::Single(ref sk) => {
139 maybe_fmt_master_id(f, &sk.origin)?;
140 sk.key.fmt(f)?;
141 Ok(())
142 }
143 DescriptorSecretKey::XPrv(ref xprv) => {
144 maybe_fmt_master_id(f, &xprv.origin)?;
145 xprv.xkey.fmt(f)?;
146 fmt_derivation_path(f, &xprv.derivation_path)?;
147 match xprv.wildcard {
148 Wildcard::None => {}
149 Wildcard::Unhardened => write!(f, "/*")?,
150 Wildcard::Hardened => write!(f, "/*h")?,
151 }
152 Ok(())
153 }
154 DescriptorSecretKey::MultiXPrv(ref xprv) => {
155 maybe_fmt_master_id(f, &xprv.origin)?;
156 xprv.xkey.fmt(f)?;
157 fmt_derivation_paths(f, xprv.derivation_paths.paths())?;
158 match xprv.wildcard {
159 Wildcard::None => {}
160 Wildcard::Unhardened => write!(f, "/*")?,
161 Wildcard::Hardened => write!(f, "/*h")?,
162 }
163 Ok(())
164 }
165 }
166 }
167}
168
169pub trait InnerXKey: fmt::Display + FromStr {
172 fn xkey_fingerprint<C: Signing>(&self, secp: &Secp256k1<C>) -> bip32::Fingerprint;
174
175 fn can_derive_hardened() -> bool;
179}
180
181impl InnerXKey for bip32::Xpub {
182 fn xkey_fingerprint<C: Signing>(&self, _secp: &Secp256k1<C>) -> bip32::Fingerprint {
183 self.fingerprint()
184 }
185
186 fn can_derive_hardened() -> bool { false }
187}
188
189impl InnerXKey for bip32::Xpriv {
190 fn xkey_fingerprint<C: Signing>(&self, secp: &Secp256k1<C>) -> bip32::Fingerprint {
191 self.fingerprint(secp)
192 }
193
194 fn can_derive_hardened() -> bool { true }
195}
196
197#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
199pub enum Wildcard {
200 None,
202 Unhardened,
204 Hardened,
206}
207
208impl fmt::Display for Wildcard {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 match self {
211 Wildcard::None => write!(f, ""),
212 Wildcard::Unhardened => write!(f, "/*"),
213 Wildcard::Hardened => write!(f, "/*h"),
214 }
215 }
216}
217
218impl SinglePriv {
219 fn to_public<C: Signing>(&self, secp: &Secp256k1<C>) -> SinglePub {
221 let pub_key = self.key.public_key(secp);
222
223 SinglePub { origin: self.origin.clone(), key: SinglePubKey::FullKey(pub_key) }
224 }
225}
226
227impl DescriptorXKey<bip32::Xpriv> {
228 fn to_public<C: Signing>(
235 &self,
236 secp: &Secp256k1<C>,
237 ) -> Result<DescriptorXKey<bip32::Xpub>, DescriptorKeyParseError> {
238 let unhardened = self
239 .derivation_path
240 .into_iter()
241 .rev()
242 .take_while(|c| c.is_normal())
243 .count();
244 let last_hardened_idx = self.derivation_path.len() - unhardened;
245
246 let hardened_path = &self.derivation_path[..last_hardened_idx];
247 let unhardened_path = &self.derivation_path[last_hardened_idx..];
248
249 let xprv = self
250 .xkey
251 .derive_priv(secp, &hardened_path)
252 .map_err(DescriptorKeyParseError::DeriveHardenedKey)?;
253
254 let xpub = bip32::Xpub::from_priv(secp, &xprv);
255
256 let origin = match &self.origin {
257 Some((fingerprint, path)) => {
258 Some((*fingerprint, path.into_iter().chain(hardened_path).copied().collect()))
259 }
260 None if !hardened_path.is_empty() => {
261 Some((self.xkey.fingerprint(secp), hardened_path.into()))
262 }
263 None => None,
264 };
265
266 Ok(DescriptorXKey {
267 origin,
268 xkey: xpub,
269 derivation_path: unhardened_path.into(),
270 wildcard: self.wildcard,
271 })
272 }
273}
274
275impl DescriptorMultiXKey<bip32::Xpriv> {
276 fn to_public<C: Signing>(
281 &self,
282 secp: &Secp256k1<C>,
283 ) -> Result<DescriptorMultiXKey<bip32::Xpub>, DescriptorKeyParseError> {
284 let deriv_paths = self.derivation_paths.paths();
285
286 let shared_prefix: Vec<_> = deriv_paths[0]
287 .into_iter()
288 .enumerate()
289 .take_while(|(index, child_num)| {
290 deriv_paths[1..].iter().all(|other_path| {
291 other_path.len() > *index && other_path[*index] == **child_num
292 })
293 })
294 .map(|(_, child_num)| *child_num)
295 .collect();
296
297 let suffixes: Vec<Vec<_>> = deriv_paths
298 .iter()
299 .map(|path| {
300 path.into_iter()
301 .skip(shared_prefix.len())
302 .map(|child_num| {
303 if child_num.is_normal() {
304 Ok(*child_num)
305 } else {
306 Err(DescriptorKeyParseError::MalformedKeyData(
307 MalformedKeyDataKind::InvalidMultiXKeyDerivation,
308 ))
309 }
310 })
311 .collect()
312 })
313 .collect::<Result<_, _>>()?;
314
315 let unhardened = shared_prefix
316 .iter()
317 .rev()
318 .take_while(|c| c.is_normal())
319 .count();
320 let last_hardened_idx = shared_prefix.len() - unhardened;
321 let hardened_path = &shared_prefix[..last_hardened_idx];
322 let unhardened_path = &shared_prefix[last_hardened_idx..];
323
324 let xprv = self
325 .xkey
326 .derive_priv(secp, &hardened_path)
327 .map_err(DescriptorKeyParseError::DeriveHardenedKey)?;
328 let xpub = bip32::Xpub::from_priv(secp, &xprv);
329
330 let origin = match &self.origin {
331 Some((fingerprint, path)) => {
332 Some((*fingerprint, path.into_iter().chain(hardened_path).copied().collect()))
333 }
334 None if !hardened_path.is_empty() => {
335 Some((self.xkey.fingerprint(secp), hardened_path.into()))
336 }
337 None => None,
338 };
339 let new_deriv_paths = suffixes
340 .into_iter()
341 .map(|suffix| {
342 let path = unhardened_path.iter().copied().chain(suffix);
343 path.collect::<Vec<_>>().into()
344 })
345 .collect();
346
347 Ok(DescriptorMultiXKey {
348 origin,
349 xkey: xpub,
350 derivation_paths: DerivPaths::new(new_deriv_paths).expect("not empty"),
351 wildcard: self.wildcard,
352 })
353 }
354}
355
356#[derive(Debug, PartialEq, Eq, Clone)]
358#[non_exhaustive]
359#[allow(missing_docs)]
360pub enum NonDefiniteKeyError {
361 Wildcard,
362 Multipath,
363 HardenedStep,
364 MaximumDepthExceeded,
365}
366
367impl fmt::Display for NonDefiniteKeyError {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 match *self {
370 Self::Wildcard => f.write_str("key with a wildcard cannot be a DerivedDescriptorKey"),
371 Self::Multipath => f.write_str("multipath key cannot be a DerivedDescriptorKey"),
372 Self::HardenedStep => {
373 f.write_str("key with hardened derivation steps cannot be a DerivedDescriptorKey")
374 }
375 Self::MaximumDepthExceeded => f.write_str(
376 "key deeper than BIP32's maximum depth of 255 cannot be a DerivedDescriptorKey",
377 ),
378 }
379 }
380}
381
382#[cfg(feature = "std")]
383impl error::Error for NonDefiniteKeyError {}
384
385#[derive(Debug, PartialEq, Eq, Clone)]
387#[non_exhaustive]
388#[allow(missing_docs)]
389pub enum MalformedKeyDataKind {
390 EmptyKey,
391 EncounteredUnprintableCharacter,
392 InvalidFullPublicKeyPrefix,
393 InvalidMasterFingerprintLength,
394 InvalidMultiIndexStep,
395 InvalidMultiXKeyDerivation,
396 InvalidPublicKeyLength,
397 InvalidWildcardInDerivationPath,
398 KeyTooShort,
399 MaximumDepthExceeded,
400 MultipleFingerprintsInPublicKey,
401 MultipleDerivationPathIndexSteps,
402 NoKeyAfterOrigin,
403 NoMasterFingerprintFound,
404 UnclosedSquareBracket,
405}
406
407impl fmt::Display for MalformedKeyDataKind {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 let err = match self {
410 Self::EmptyKey => "empty key",
411 Self::EncounteredUnprintableCharacter => "encountered an unprintable character",
412 Self::InvalidFullPublicKeyPrefix => "only full public keys with prefixes '02', '03' or '04' are allowed",
413 Self::InvalidMasterFingerprintLength => "master fingerprint should be 8 characters long",
414 Self::InvalidMultiIndexStep => "invalid multi index step in multipath descriptor",
415 Self::InvalidMultiXKeyDerivation => "can't make a multi-xpriv with hardened derivation steps that are not shared among all paths into a public key",
416 Self::InvalidPublicKeyLength => "public keys must be 64, 66 or 130 characters in size",
417 Self::InvalidWildcardInDerivationPath => "'*' may only appear as last element in a derivation path",
418 Self::KeyTooShort => "key too short",
419 Self::MaximumDepthExceeded => {
420 "key derivation would go deeper than BIP32's maximum depth of 255"
421 }
422 Self::MultipleFingerprintsInPublicKey => "multiple ']' in Descriptor Public Key",
423 Self::MultipleDerivationPathIndexSteps => "'<' may only appear once in a derivation path",
424 Self::NoKeyAfterOrigin => "no key after origin",
425 Self::NoMasterFingerprintFound => "no master fingerprint found after '['",
426 Self::UnclosedSquareBracket => "unclosed '['",
427 };
428
429 f.write_str(err)
430 }
431}
432
433#[derive(Debug, PartialEq, Eq, Clone)]
435#[non_exhaustive]
436pub enum DescriptorKeyParseError {
437 DerivationIndexError {
439 index: String,
441 err: bip32::Error,
443 },
444 DeriveHardenedKey(bip32::Error),
446 MalformedKeyData(MalformedKeyDataKind),
448 MasterDerivationPath(bip32::Error),
450 MasterFingerprint {
452 fingerprint: String,
454 err: bitcoin::hex::HexToArrayError,
456 },
457 NonDefiniteKey(NonDefiniteKeyError),
459 FullPublicKey(bitcoin::key::ParsePublicKeyError),
461 WifPrivateKey(bitcoin::key::FromWifError),
463 XonlyPublicKey(bitcoin::secp256k1::Error),
465 XKeyParseError(XKeyParseError),
467}
468
469impl fmt::Display for DescriptorKeyParseError {
470 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
471 match self {
472 Self::DerivationIndexError { index, err } => {
473 write!(f, "at derivation index '{index}': {err}")
474 }
475 Self::DeriveHardenedKey(err) => err.fmt(f),
476 Self::MalformedKeyData(err) => err.fmt(f),
477 Self::MasterDerivationPath(err) => err.fmt(f),
478 Self::MasterFingerprint { fingerprint, err } => {
479 write!(f, "on master fingerprint '{fingerprint}': {err}")
480 }
481 Self::NonDefiniteKey(err) => err.fmt(f),
482 Self::FullPublicKey(err) => err.fmt(f),
483 Self::WifPrivateKey(err) => err.fmt(f),
484 Self::XonlyPublicKey(err) => err.fmt(f),
485 Self::XKeyParseError(err) => err.fmt(f),
486 }
487 }
488}
489
490#[cfg(feature = "std")]
491impl error::Error for DescriptorKeyParseError {
492 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
493 match self {
494 Self::DerivationIndexError { err, .. }
495 | Self::DeriveHardenedKey(err)
496 | Self::MasterDerivationPath(err) => Some(err),
497 Self::MasterFingerprint { err, .. } => Some(err),
498 Self::NonDefiniteKey(err) => Some(err),
499 Self::FullPublicKey(err) => Some(err),
500 Self::WifPrivateKey(err) => Some(err),
501 Self::XonlyPublicKey(err) => Some(err),
502 Self::XKeyParseError(err) => Some(err),
503 Self::MalformedKeyData(_) => None,
504 }
505 }
506}
507
508#[derive(Debug, PartialEq, Eq, Clone)]
510pub enum XKeyParseError {
511 Bip32(bip32::Error),
512 Bip388(WalletPolicyError),
513}
514
515#[cfg(feature = "std")]
516impl error::Error for XKeyParseError {
517 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
518 match self {
519 Self::Bip32(err) => Some(err),
520 Self::Bip388(err) => Some(err),
521 }
522 }
523}
524
525impl fmt::Display for XKeyParseError {
526 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527 match self {
528 Self::Bip32(err) => err.fmt(f),
529 Self::Bip388(err) => err.fmt(f),
530 }
531 }
532}
533
534impl From<bip32::Error> for XKeyParseError {
535 fn from(err: bip32::Error) -> Self { Self::Bip32(err) }
536}
537
538impl fmt::Display for DescriptorPublicKey {
539 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
540 match *self {
541 Self::Single(ref pk) => {
542 maybe_fmt_master_id(f, &pk.origin)?;
543 match pk.key {
544 SinglePubKey::FullKey(full_key) => full_key.fmt(f),
545 SinglePubKey::XOnly(x_only_key) => x_only_key.fmt(f),
546 }?;
547 Ok(())
548 }
549 Self::XPub(ref xpub) => {
550 maybe_fmt_master_id(f, &xpub.origin)?;
551 xpub.xkey.fmt(f)?;
552 fmt_derivation_path(f, &xpub.derivation_path)?;
553 xpub.wildcard.fmt(f)?;
554 Ok(())
555 }
556 Self::MultiXPub(ref xpub) => {
557 maybe_fmt_master_id(f, &xpub.origin)?;
558 xpub.xkey.fmt(f)?;
559 fmt_derivation_paths(f, xpub.derivation_paths.paths())?;
560 xpub.wildcard.fmt(f)?;
561 Ok(())
562 }
563 }
564 }
565}
566
567impl DescriptorSecretKey {
568 pub fn to_public<C: Signing>(
576 &self,
577 secp: &Secp256k1<C>,
578 ) -> Result<DescriptorPublicKey, DescriptorKeyParseError> {
579 let pk = match self {
580 DescriptorSecretKey::Single(prv) => DescriptorPublicKey::Single(prv.to_public(secp)),
581 DescriptorSecretKey::XPrv(xprv) => DescriptorPublicKey::XPub(xprv.to_public(secp)?),
582 DescriptorSecretKey::MultiXPrv(xprv) => {
583 DescriptorPublicKey::MultiXPub(xprv.to_public(secp)?)
584 }
585 };
586
587 Ok(pk)
588 }
589
590 pub fn is_multipath(&self) -> bool {
592 match *self {
593 DescriptorSecretKey::Single(..) | DescriptorSecretKey::XPrv(..) => false,
594 DescriptorSecretKey::MultiXPrv(_) => true,
595 }
596 }
597
598 pub fn into_single_keys(self) -> Vec<DescriptorSecretKey> {
604 match self {
605 DescriptorSecretKey::Single(..) | DescriptorSecretKey::XPrv(..) => vec![self],
606 DescriptorSecretKey::MultiXPrv(xpub) => {
607 let DescriptorMultiXKey { origin, xkey, derivation_paths, wildcard } = xpub;
608 derivation_paths
609 .into_paths()
610 .into_iter()
611 .map(|derivation_path| {
612 DescriptorSecretKey::XPrv(DescriptorXKey {
613 origin: origin.clone(),
614 xkey,
615 derivation_path,
616 wildcard,
617 })
618 })
619 .collect()
620 }
621 }
622 }
623}
624
625pub(crate) fn maybe_fmt_master_id(
627 f: &mut fmt::Formatter,
628 origin: &Option<(bip32::Fingerprint, bip32::DerivationPath)>,
629) -> fmt::Result {
630 if let Some((ref master_id, ref master_deriv)) = *origin {
631 fmt::Formatter::write_str(f, "[")?;
632 for byte in master_id.as_bytes().iter() {
633 write!(f, "{:02x}", byte)?;
634 }
635 fmt_derivation_path(f, master_deriv)?;
636 fmt::Formatter::write_str(f, "]")?;
637 }
638
639 Ok(())
640}
641
642fn fmt_derivation_path(f: &mut fmt::Formatter, path: &bip32::DerivationPath) -> fmt::Result {
644 for child in path {
645 write!(f, "/{}", child)?;
646 }
647 Ok(())
648}
649
650pub(crate) fn fmt_derivation_paths<W: fmt::Write>(
654 f: &mut W,
655 paths: &[bip32::DerivationPath],
656) -> fmt::Result {
657 for (i, child) in paths[0].into_iter().enumerate() {
658 if paths.len() > 1 && child != &paths[1][i] {
659 write!(f, "/<")?;
660 for (j, p) in paths.iter().enumerate() {
661 write!(f, "{}", p[i])?;
662 if j != paths.len() - 1 {
663 write!(f, ";")?;
664 }
665 }
666 write!(f, ">")?;
667 } else {
668 write!(f, "/{}", child)?;
669 }
670 }
671 Ok(())
672}
673
674impl FromStr for DescriptorPublicKey {
675 type Err = DescriptorKeyParseError;
676
677 fn from_str(s: &str) -> Result<Self, Self::Err> {
678 if s.len() < 64 {
680 return Err(DescriptorKeyParseError::MalformedKeyData(
681 MalformedKeyDataKind::KeyTooShort,
682 ));
683 }
684
685 let (key_part, origin) = parse_key_origin(s)?;
686
687 if key_part.contains("pub") {
688 let (xpub, derivation_paths, wildcard) = parse_xkey_deriv::<bip32::Xpub, _>(key_part)?;
689 if derivation_exceeds_max_depth(xpub.depth, &derivation_paths, wildcard) {
690 return Err(DescriptorKeyParseError::MalformedKeyData(
691 MalformedKeyDataKind::MaximumDepthExceeded,
692 ));
693 }
694 if derivation_paths.len() > 1 {
695 Ok(DescriptorPublicKey::MultiXPub(DescriptorMultiXKey {
696 origin,
697 xkey: xpub,
698 derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
699 wildcard,
700 }))
701 } else {
702 Ok(DescriptorPublicKey::XPub(DescriptorXKey {
703 origin,
704 xkey: xpub,
705 derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
706 wildcard,
707 }))
708 }
709 } else {
710 let key = match key_part.len() {
711 64 => {
712 let x_only_key = XOnlyPublicKey::from_str(key_part)
713 .map_err(DescriptorKeyParseError::XonlyPublicKey)?;
714 SinglePubKey::XOnly(x_only_key)
715 }
716 66 | 130 => {
717 if !(&key_part[0..2] == "02"
718 || &key_part[0..2] == "03"
719 || &key_part[0..2] == "04")
720 {
721 return Err(DescriptorKeyParseError::MalformedKeyData(
722 MalformedKeyDataKind::InvalidFullPublicKeyPrefix,
723 ));
724 }
725 let key = bitcoin::PublicKey::from_str(key_part)
726 .map_err(DescriptorKeyParseError::FullPublicKey)?;
727 SinglePubKey::FullKey(key)
728 }
729 _ => {
730 return Err(DescriptorKeyParseError::MalformedKeyData(
731 MalformedKeyDataKind::InvalidPublicKeyLength,
732 ))
733 }
734 };
735 Ok(DescriptorPublicKey::Single(SinglePub { key, origin }))
736 }
737 }
738}
739
740impl From<XOnlyPublicKey> for DescriptorPublicKey {
741 fn from(key: XOnlyPublicKey) -> Self {
742 DescriptorPublicKey::Single(SinglePub { origin: None, key: SinglePubKey::XOnly(key) })
743 }
744}
745
746impl From<PublicKey> for DescriptorPublicKey {
747 fn from(key: PublicKey) -> Self {
748 DescriptorPublicKey::Single(SinglePub { origin: None, key: SinglePubKey::FullKey(key) })
749 }
750}
751
752impl DescriptorPublicKey {
753 pub fn master_fingerprint(&self) -> bip32::Fingerprint {
755 match *self {
756 DescriptorPublicKey::XPub(ref xpub) => {
757 if let Some((fingerprint, _)) = xpub.origin {
758 fingerprint
759 } else {
760 xpub.xkey.fingerprint()
761 }
762 }
763 DescriptorPublicKey::MultiXPub(ref xpub) => {
764 if let Some((fingerprint, _)) = xpub.origin {
765 fingerprint
766 } else {
767 xpub.xkey.fingerprint()
768 }
769 }
770 DescriptorPublicKey::Single(ref single) => {
771 if let Some((fingerprint, _)) = single.origin {
772 fingerprint
773 } else {
774 let mut engine = XKeyIdentifier::engine();
775 match single.key {
776 SinglePubKey::FullKey(pk) => {
777 pk.write_into(&mut engine).expect("engines don't error")
778 }
779 SinglePubKey::XOnly(x_only_pk) => engine.input(&x_only_pk.serialize()),
780 };
781 bip32::Fingerprint::from(
782 &XKeyIdentifier::from_engine(engine)[..4]
783 .try_into()
784 .expect("4 byte slice"),
785 )
786 }
787 }
788 }
789 }
790
791 pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
799 match *self {
800 DescriptorPublicKey::XPub(ref xpub) => {
801 let origin_path = if let Some((_, ref path)) = xpub.origin {
802 path.clone()
803 } else {
804 bip32::DerivationPath::from(vec![])
805 };
806 Some(origin_path.extend(&xpub.derivation_path))
807 }
808 DescriptorPublicKey::Single(ref single) => {
809 Some(if let Some((_, ref path)) = single.origin {
810 path.clone()
811 } else {
812 bip32::DerivationPath::from(vec![])
813 })
814 }
815 DescriptorPublicKey::MultiXPub(_) => None,
816 }
817 }
818
819 pub fn full_derivation_paths(&self) -> Vec<bip32::DerivationPath> {
827 match self {
828 DescriptorPublicKey::MultiXPub(xpub) => {
829 let origin_path = if let Some((_, ref path)) = xpub.origin {
830 path.clone()
831 } else {
832 bip32::DerivationPath::from(vec![])
833 };
834 xpub.derivation_paths
835 .paths()
836 .iter()
837 .map(|p| origin_path.extend(p))
838 .collect()
839 }
840 _ => vec![self
841 .full_derivation_path()
842 .expect("Must be Some for non-multipath keys")],
843 }
844 }
845
846 pub fn derivation_path(&self) -> Option<bip32::DerivationPath> {
854 match *self {
855 DescriptorPublicKey::XPub(ref xpub) => Some(xpub.derivation_path.clone()),
856 DescriptorPublicKey::Single(_) => Some(bip32::DerivationPath::from(vec![])),
857 DescriptorPublicKey::MultiXPub(_) => None,
858 }
859 }
860
861 pub fn derivation_paths(&self) -> Vec<bip32::DerivationPath> {
867 match &self {
868 DescriptorPublicKey::XPub(xpub) => {
869 vec![xpub.derivation_path.clone()]
870 }
871 DescriptorPublicKey::Single(_) => {
872 vec![bip32::DerivationPath::from(vec![])]
873 }
874 DescriptorPublicKey::MultiXPub(xpub) => xpub.derivation_paths.paths().clone(),
875 }
876 }
877
878 pub fn has_wildcard(&self) -> bool {
880 match *self {
881 DescriptorPublicKey::Single(..) => false,
882 DescriptorPublicKey::XPub(ref xpub) => xpub.wildcard != Wildcard::None,
883 DescriptorPublicKey::MultiXPub(ref xpub) => xpub.wildcard != Wildcard::None,
884 }
885 }
886
887 pub fn wildcard(&self) -> Option<Wildcard> {
889 match *self {
890 DescriptorPublicKey::Single(..) => None,
891 DescriptorPublicKey::XPub(ref xpub) => Some(xpub.wildcard),
892 DescriptorPublicKey::MultiXPub(ref xpub) => Some(xpub.wildcard),
893 }
894 }
895
896 pub fn has_hardened_step(&self) -> bool {
898 let paths = match self {
899 DescriptorPublicKey::Single(..) => &[],
900 DescriptorPublicKey::XPub(xpub) => core::slice::from_ref(&xpub.derivation_path),
901 DescriptorPublicKey::MultiXPub(xpub) => &xpub.derivation_paths.paths()[..],
902 };
903 for p in paths {
904 for step in p.into_iter() {
905 if step.is_hardened() {
906 return true;
907 }
908 }
909 }
910 false
911 }
912
913 fn exceeds_max_depth(&self) -> bool {
916 match self {
917 Self::Single(..) => false,
918 Self::XPub(xpub) => derivation_exceeds_max_depth(
919 xpub.xkey.depth,
920 core::slice::from_ref(&xpub.derivation_path),
921 xpub.wildcard,
922 ),
923 Self::MultiXPub(xpub) => derivation_exceeds_max_depth(
924 xpub.xkey.depth,
925 xpub.derivation_paths.paths(),
926 xpub.wildcard,
927 ),
928 }
929 }
930
931 pub fn at_derivation_index(
947 self,
948 index: u32,
949 ) -> Result<DefiniteDescriptorKey, NonDefiniteKeyError> {
950 let definite = match self {
951 DescriptorPublicKey::Single(_) => self,
952 DescriptorPublicKey::XPub(xpub) => {
953 let derivation_path = match xpub.wildcard {
954 Wildcard::None => xpub.derivation_path,
955 Wildcard::Unhardened => xpub.derivation_path.into_child(
956 bip32::ChildNumber::from_normal_idx(index)
957 .ok()
958 .ok_or(NonDefiniteKeyError::HardenedStep)?,
959 ),
960 Wildcard::Hardened => xpub.derivation_path.into_child(
961 bip32::ChildNumber::from_hardened_idx(index)
962 .ok()
963 .ok_or(NonDefiniteKeyError::HardenedStep)?,
964 ),
965 };
966 DescriptorPublicKey::XPub(DescriptorXKey {
967 origin: xpub.origin,
968 xkey: xpub.xkey,
969 derivation_path,
970 wildcard: Wildcard::None,
971 })
972 }
973 DescriptorPublicKey::MultiXPub(_) => return Err(NonDefiniteKeyError::Multipath),
974 };
975
976 DefiniteDescriptorKey::new(definite)
977 }
978
979 pub fn is_multipath(&self) -> bool {
981 match *self {
982 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
983 DescriptorPublicKey::MultiXPub(_) => true,
984 }
985 }
986
987 pub fn into_single_keys(self) -> Vec<DescriptorPublicKey> {
993 match self {
994 DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => vec![self],
995 DescriptorPublicKey::MultiXPub(xpub) => {
996 let DescriptorMultiXKey { origin, xkey, derivation_paths, wildcard } = xpub;
997 derivation_paths
998 .into_paths()
999 .into_iter()
1000 .map(|derivation_path| {
1001 DescriptorPublicKey::XPub(DescriptorXKey {
1002 origin: origin.clone(),
1003 xkey,
1004 derivation_path,
1005 wildcard,
1006 })
1007 })
1008 .collect()
1009 }
1010 }
1011 }
1012
1013 pub fn xkey_network(&self) -> Option<NetworkKind> {
1017 match self {
1018 DescriptorPublicKey::Single(_) => None,
1019 DescriptorPublicKey::XPub(xpub) => Some(xpub.xkey.network),
1020 DescriptorPublicKey::MultiXPub(multi_xpub) => Some(multi_xpub.xkey.network),
1021 }
1022 }
1023}
1024
1025impl FromStr for DescriptorSecretKey {
1026 type Err = DescriptorKeyParseError;
1027
1028 fn from_str(s: &str) -> Result<Self, Self::Err> {
1029 let (key_part, origin) = parse_key_origin(s)?;
1030
1031 if key_part.len() <= 52 {
1032 let sk = bitcoin::PrivateKey::from_str(key_part)
1033 .map_err(DescriptorKeyParseError::WifPrivateKey)?;
1034 Ok(DescriptorSecretKey::Single(SinglePriv { key: sk, origin }))
1035 } else {
1036 let (xpriv, derivation_paths, wildcard) =
1037 parse_xkey_deriv::<bip32::Xpriv, _>(key_part)?;
1038 if derivation_exceeds_max_depth(xpriv.depth, &derivation_paths, wildcard) {
1039 return Err(DescriptorKeyParseError::MalformedKeyData(
1040 MalformedKeyDataKind::MaximumDepthExceeded,
1041 ));
1042 }
1043 if derivation_paths.len() > 1 {
1044 Ok(DescriptorSecretKey::MultiXPrv(DescriptorMultiXKey {
1045 origin,
1046 xkey: xpriv,
1047 derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
1048 wildcard,
1049 }))
1050 } else {
1051 Ok(DescriptorSecretKey::XPrv(DescriptorXKey {
1052 origin,
1053 xkey: xpriv,
1054 derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
1055 wildcard,
1056 }))
1057 }
1058 }
1059 }
1060}
1061
1062fn parse_key_origin(s: &str) -> Result<(&str, Option<bip32::KeySource>), DescriptorKeyParseError> {
1064 for ch in s.as_bytes() {
1065 if *ch < 20 || *ch > 127 {
1066 return Err(DescriptorKeyParseError::MalformedKeyData(
1067 MalformedKeyDataKind::EncounteredUnprintableCharacter,
1068 ));
1069 }
1070 }
1071
1072 if s.is_empty() {
1073 return Err(DescriptorKeyParseError::MalformedKeyData(MalformedKeyDataKind::EmptyKey));
1074 }
1075 let mut parts = s[1..].split(']');
1076
1077 if let Some('[') = s.chars().next() {
1078 let mut raw_origin = parts
1079 .next()
1080 .ok_or(DescriptorKeyParseError::MalformedKeyData(
1081 MalformedKeyDataKind::UnclosedSquareBracket,
1082 ))?
1083 .split('/');
1084
1085 let origin_id_hex = raw_origin
1086 .next()
1087 .ok_or(DescriptorKeyParseError::MalformedKeyData(
1088 MalformedKeyDataKind::NoMasterFingerprintFound,
1089 ))?;
1090
1091 if origin_id_hex.len() != 8 {
1092 return Err(DescriptorKeyParseError::MalformedKeyData(
1093 MalformedKeyDataKind::InvalidMasterFingerprintLength,
1094 ));
1095 }
1096 let parent_fingerprint = bip32::Fingerprint::from_hex(origin_id_hex).map_err(|err| {
1097 DescriptorKeyParseError::MasterFingerprint {
1098 fingerprint: origin_id_hex.to_owned(),
1099 err,
1100 }
1101 })?;
1102 let origin_path = raw_origin
1103 .map(bip32::ChildNumber::from_str)
1104 .collect::<Result<bip32::DerivationPath, bip32::Error>>()
1105 .map_err(DescriptorKeyParseError::MasterDerivationPath)?;
1106
1107 let key = parts
1108 .next()
1109 .ok_or(DescriptorKeyParseError::MalformedKeyData(
1110 MalformedKeyDataKind::NoKeyAfterOrigin,
1111 ))?;
1112
1113 if parts.next().is_some() {
1114 Err(DescriptorKeyParseError::MalformedKeyData(
1115 MalformedKeyDataKind::MultipleFingerprintsInPublicKey,
1116 ))
1117 } else {
1118 Ok((key, Some((parent_fingerprint, origin_path))))
1119 }
1120 } else {
1121 Ok((s, None))
1122 }
1123}
1124
1125fn derivation_exceeds_max_depth(
1131 depth: u8,
1132 paths: &[bip32::DerivationPath],
1133 wildcard: Wildcard,
1134) -> bool {
1135 let longest = paths.iter().map(|path| path.len()).max().unwrap_or(0);
1136 longest + usize::from(wildcard != Wildcard::None) > usize::from(u8::MAX - depth)
1137}
1138
1139pub(crate) fn parse_xkey_deriv<Key, E>(
1140 key_deriv: &str,
1141) -> Result<(Key, Vec<bip32::DerivationPath>, Wildcard), DescriptorKeyParseError>
1142where
1143 Key: FromStr<Err = E>,
1144 E: Into<XKeyParseError>,
1145{
1146 let mut key_deriv = key_deriv.split('/');
1147 let xkey_str = key_deriv
1148 .next()
1149 .ok_or(DescriptorKeyParseError::MalformedKeyData(
1150 MalformedKeyDataKind::NoKeyAfterOrigin,
1151 ))?;
1152
1153 let xkey =
1154 Key::from_str(xkey_str).map_err(|e| DescriptorKeyParseError::XKeyParseError(e.into()))?;
1155
1156 let mut wildcard = Wildcard::None;
1157 let mut multipath = false;
1158 let derivation_paths = key_deriv
1159 .filter_map(|p| {
1160 if wildcard == Wildcard::None && p == "*" {
1161 wildcard = Wildcard::Unhardened;
1162 None
1163 } else if wildcard == Wildcard::None && (p == "*'" || p == "*h") {
1164 wildcard = Wildcard::Hardened;
1165 None
1166 } else if wildcard != Wildcard::None {
1167 Some(Err(DescriptorKeyParseError::MalformedKeyData(
1168 MalformedKeyDataKind::InvalidWildcardInDerivationPath,
1169 )))
1170 } else {
1171 if p.starts_with('<') && p.ends_with('>') {
1174 if multipath {
1176 return Some(Err(DescriptorKeyParseError::MalformedKeyData(
1177 MalformedKeyDataKind::MultipleDerivationPathIndexSteps,
1178 )));
1179 }
1180 multipath = true;
1181
1182 if p.len() < 5 || !p.contains(';') {
1185 return Some(Err(DescriptorKeyParseError::MalformedKeyData(
1186 MalformedKeyDataKind::InvalidMultiIndexStep,
1187 )));
1188 }
1189
1190 let indexes = p[1..p.len() - 1].split(';');
1192 Some(
1193 indexes
1194 .into_iter()
1195 .map(|s| {
1196 bip32::ChildNumber::from_str(s).map_err(|err| {
1197 DescriptorKeyParseError::DerivationIndexError {
1198 index: s.to_owned(),
1199 err,
1200 }
1201 })
1202 })
1203 .collect::<Result<Vec<bip32::ChildNumber>, _>>(),
1204 )
1205 } else {
1206 Some(
1208 bip32::ChildNumber::from_str(p)
1209 .map(|i| vec![i])
1210 .map_err(|err| DescriptorKeyParseError::DerivationIndexError {
1211 index: p.to_owned(),
1212 err,
1213 }),
1214 )
1215 }
1216 }
1217 })
1218 .try_fold(Vec::new(), |mut paths, index_list| -> Result<_, DescriptorKeyParseError> {
1224 let mut index_list = index_list?.into_iter();
1225 let first_index = index_list
1226 .next()
1227 .expect("There is always at least one element");
1228
1229 if paths.is_empty() {
1230 paths.push(vec![first_index]);
1231 } else {
1232 for path in paths.iter_mut() {
1233 path.push(first_index);
1234 }
1235 }
1236
1237 for (i, index) in index_list.enumerate() {
1239 paths.push(paths[0].clone());
1240 *paths[i + 1].last_mut().expect("Never empty") = index;
1241 }
1242
1243 Ok(paths)
1244 })?
1245 .into_iter()
1246 .map(|index_list| index_list.into_iter().collect::<bip32::DerivationPath>())
1247 .collect::<Vec<bip32::DerivationPath>>();
1248
1249 Ok((xkey, derivation_paths, wildcard))
1250}
1251
1252impl<K: InnerXKey> DescriptorXKey<K> {
1253 pub fn matches<C: Signing>(
1303 &self,
1304 keysource: &bip32::KeySource,
1305 secp: &Secp256k1<C>,
1306 ) -> Option<bip32::DerivationPath> {
1307 let (fingerprint, path) = keysource;
1308
1309 let (compare_fingerprint, compare_path) = match self.origin {
1310 Some((fingerprint, ref path)) => {
1311 (fingerprint, path.into_iter().chain(&self.derivation_path).collect())
1312 }
1313 None => (
1314 self.xkey.xkey_fingerprint(secp),
1315 self.derivation_path.into_iter().collect::<Vec<_>>(),
1316 ),
1317 };
1318
1319 let path_excluding_wildcard = if self.wildcard != Wildcard::None && !path.is_empty() {
1320 path.into_iter()
1321 .take(path.as_ref().len() - 1)
1322 .cloned()
1323 .collect()
1324 } else {
1325 path.clone()
1326 };
1327
1328 if &compare_fingerprint == fingerprint
1329 && compare_path.into_iter().eq(&path_excluding_wildcard)
1330 {
1331 Some(path_excluding_wildcard)
1332 } else {
1333 None
1334 }
1335 }
1336}
1337
1338impl MiniscriptKey for DescriptorPublicKey {
1339 type Sha256 = sha256::Hash;
1340 type Hash256 = hash256::Hash;
1341 type Ripemd160 = ripemd160::Hash;
1342 type Hash160 = hash160::Hash;
1343
1344 fn is_uncompressed(&self) -> bool {
1345 match self {
1346 DescriptorPublicKey::Single(SinglePub {
1347 key: SinglePubKey::FullKey(ref key), ..
1348 }) => key.is_uncompressed(),
1349 _ => false,
1350 }
1351 }
1352
1353 fn is_x_only_key(&self) -> bool {
1354 matches!(
1355 self,
1356 DescriptorPublicKey::Single(SinglePub { key: SinglePubKey::XOnly(ref _key), .. })
1357 )
1358 }
1359
1360 fn num_der_paths(&self) -> usize {
1361 match self {
1362 DescriptorPublicKey::Single(_) => 0,
1363 DescriptorPublicKey::XPub(_) => 1,
1364 DescriptorPublicKey::MultiXPub(xpub) => xpub.derivation_paths.paths().len(),
1365 }
1366 }
1367}
1368
1369impl DefiniteDescriptorKey {
1370 pub fn derive_public_key<C: Verification>(&self, secp: &Secp256k1<C>) -> bitcoin::PublicKey {
1378 match self.0 {
1379 DescriptorPublicKey::Single(ref pk) => match pk.key {
1380 SinglePubKey::FullKey(pk) => pk,
1381 SinglePubKey::XOnly(xpk) => xpk.to_public_key(),
1382 },
1383 DescriptorPublicKey::XPub(ref xpk) => match xpk.wildcard {
1384 Wildcard::Unhardened | Wildcard::Hardened => {
1385 unreachable!("impossible by construction of DefiniteDescriptorKey")
1386 }
1387 Wildcard::None => match xpk.xkey.derive_pub(secp, &xpk.derivation_path.as_ref()) {
1388 Ok(xpub) => bitcoin::PublicKey::new(xpub.public_key),
1389 Err(bip32::Error::CannotDeriveFromHardenedKey) => {
1390 unreachable!("impossible by construction of DefiniteDescriptorKey")
1391 }
1392 Err(e) => unreachable!("cryptographically unreachable: {}", e),
1393 },
1394 },
1395 DescriptorPublicKey::MultiXPub(_) => {
1396 unreachable!("impossible by construction of DefiniteDescriptorKey")
1397 }
1398 }
1399 }
1400
1401 pub fn new(key: DescriptorPublicKey) -> Result<Self, NonDefiniteKeyError> {
1406 if key.has_wildcard() {
1407 Err(NonDefiniteKeyError::Wildcard)
1408 } else if key.has_hardened_step() {
1409 Err(NonDefiniteKeyError::HardenedStep)
1410 } else if key.is_multipath() {
1411 Err(NonDefiniteKeyError::Multipath)
1412 } else if key.exceeds_max_depth() {
1413 Err(NonDefiniteKeyError::MaximumDepthExceeded)
1414 } else {
1415 Ok(Self(key))
1416 }
1417 }
1418
1419 pub fn master_fingerprint(&self) -> bip32::Fingerprint { self.0.master_fingerprint() }
1421
1422 pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
1424 self.0.full_derivation_path()
1425 }
1426
1427 pub fn full_derivation_paths(&self) -> Vec<bip32::DerivationPath> {
1430 self.0.full_derivation_paths()
1431 }
1432
1433 pub fn as_descriptor_public_key(&self) -> &DescriptorPublicKey { &self.0 }
1435
1436 pub fn into_descriptor_public_key(self) -> DescriptorPublicKey { self.0 }
1438}
1439
1440impl FromStr for DefiniteDescriptorKey {
1441 type Err = DescriptorKeyParseError;
1442
1443 fn from_str(s: &str) -> Result<Self, Self::Err> {
1444 let d = DescriptorPublicKey::from_str(s)?;
1445 DefiniteDescriptorKey::new(d).map_err(DescriptorKeyParseError::NonDefiniteKey)
1446 }
1447}
1448
1449impl fmt::Display for DefiniteDescriptorKey {
1450 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) }
1451}
1452
1453impl MiniscriptKey for DefiniteDescriptorKey {
1454 type Sha256 = sha256::Hash;
1455 type Hash256 = hash256::Hash;
1456 type Ripemd160 = ripemd160::Hash;
1457 type Hash160 = hash160::Hash;
1458
1459 fn is_uncompressed(&self) -> bool { self.0.is_uncompressed() }
1460
1461 fn is_x_only_key(&self) -> bool { self.0.is_x_only_key() }
1462
1463 fn num_der_paths(&self) -> usize { self.0.num_der_paths() }
1464}
1465
1466impl ToPublicKey for DefiniteDescriptorKey {
1467 fn to_public_key(&self) -> bitcoin::PublicKey {
1468 let secp = Secp256k1::verification_only();
1469 self.derive_public_key(&secp)
1470 }
1471
1472 fn to_sha256(hash: &sha256::Hash) -> sha256::Hash { *hash }
1473
1474 fn to_hash256(hash: &hash256::Hash) -> hash256::Hash { *hash }
1475
1476 fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash { *hash }
1477
1478 fn to_hash160(hash: &hash160::Hash) -> hash160::Hash { *hash }
1479}
1480
1481impl From<DefiniteDescriptorKey> for DescriptorPublicKey {
1482 fn from(d: DefiniteDescriptorKey) -> Self { d.0 }
1483}
1484
1485impl Borrow<DescriptorPublicKey> for DefiniteDescriptorKey {
1486 fn borrow(&self) -> &DescriptorPublicKey { &self.0 }
1487}
1488
1489#[cfg(feature = "serde")]
1490impl<'de> Deserialize<'de> for DescriptorPublicKey {
1491 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1492 where
1493 D: Deserializer<'de>,
1494 {
1495 let s = String::deserialize(deserializer)?;
1496 DescriptorPublicKey::from_str(&s).map_err(crate::serde::de::Error::custom)
1497 }
1498}
1499
1500#[cfg(feature = "serde")]
1501impl Serialize for DescriptorPublicKey {
1502 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1503 where
1504 S: Serializer,
1505 {
1506 serializer.serialize_str(&self.to_string())
1507 }
1508}
1509
1510#[cfg(test)]
1511mod test {
1512 use core::str::FromStr;
1513
1514 use bitcoin::bip32;
1515 #[cfg(feature = "serde")]
1516 use serde_test::{assert_tokens, Token};
1517
1518 use super::{
1519 DescriptorKeyParseError, DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey,
1520 DescriptorXKey, MalformedKeyDataKind, MiniscriptKey, Wildcard,
1521 };
1522 use crate::descriptor::key::NonDefiniteKeyError;
1523 use crate::prelude::*;
1524 use crate::{DefiniteDescriptorKey, Descriptor};
1525
1526 #[test]
1527 fn parse_descriptor_key_errors() {
1528 let desc = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*/44";
1530 assert_eq!(
1531 DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1532 "\'*\' may only appear as last element in a derivation path"
1533 );
1534
1535 let desc = "[NonHexor]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*";
1537 assert_eq!(
1538 DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1539 "on master fingerprint 'NonHexor': failed to parse hex digit"
1540 );
1541
1542 let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*";
1544 assert_eq!(
1545 DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1546 "base58 encoding error"
1547 );
1548
1549 let desc = "[78412e3a]0208a117f3897c3a13c9384b8695eed98dc31bc2500feb19a1af424cd47a5d83/1/*";
1551 assert_eq!(
1552 DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1553 "public keys must be 64, 66 or 130 characters in size",
1554 );
1555
1556 let desc = "[78412e3a]]03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
1558 assert_eq!(
1559 DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1560 "multiple \']\' in Descriptor Public Key"
1561 );
1562
1563 let desc = "[11111f11]033333333333333333333333333333323333333333333333333333333433333333]]333]]3]]101333333333333433333]]]10]333333mmmm";
1565 assert_eq!(
1566 DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1567 "multiple \']\' in Descriptor Public Key"
1568 );
1569
1570 let desc = "0777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777";
1572 assert_eq!(
1573 DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1574 "only full public keys with prefixes '02', '03' or '04' are allowed"
1575 );
1576 }
1577
1578 #[test]
1579 fn parse_descriptor_secret_key_error() {
1580 let secret_key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
1582 assert_eq!(
1583 DescriptorSecretKey::from_str(secret_key)
1584 .unwrap_err()
1585 .to_string(),
1586 "unknown version magic bytes: [4, 136, 178, 30]"
1587 );
1588
1589 let desc = "[NonHexor]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/*";
1591 assert_eq!(
1592 DescriptorSecretKey::from_str(desc).unwrap_err().to_string(),
1593 "on master fingerprint 'NonHexor': failed to parse hex digit"
1594 );
1595
1596 let desc = "[78412e3a]L32jTfVLei6BYTPUpwpJSkrHx8iL9GZzeErVS8y4Y/1/*";
1598 assert_eq!(DescriptorSecretKey::from_str(desc).unwrap_err().to_string(), "invalid base58");
1599 }
1600
1601 #[test]
1602 fn test_wildcard() {
1603 let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2").unwrap();
1604 assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1605 assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'/2");
1606 assert!(!public_key.has_wildcard());
1607
1608 let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*").unwrap();
1609 assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1610 assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'");
1611 assert!(public_key.has_wildcard());
1612
1613 let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*h").unwrap();
1614 assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1615 assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'");
1616 assert!(public_key.has_wildcard());
1617 }
1618
1619 #[test]
1620 fn test_deriv_on_xprv() {
1621 let secp = secp256k1::Secp256k1::signing_only();
1622
1623 let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2").unwrap();
1624 let public_key = secret_key.to_public(&secp).unwrap();
1625 assert_eq!(public_key.to_string(), "[2cbe2a6d/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2");
1626 assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1627 assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'/2");
1628 assert!(!public_key.has_wildcard());
1629
1630 let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2'").unwrap();
1631 let public_key = secret_key.to_public(&secp).unwrap();
1632 assert_eq!(public_key.to_string(), "[2cbe2a6d/0'/1'/2']tpubDDPuH46rv4dbFtmF6FrEtJEy1CvLZonyBoVxF6xsesHdYDdTBrq2mHhm8AbsPh39sUwL2nZyxd6vo4uWNTU9v4t893CwxjqPnwMoUACLvMV");
1633 assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1634 assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'/2'");
1635
1636 let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0/1/2").unwrap();
1637 let public_key = secret_key.to_public(&secp).unwrap();
1638 assert_eq!(public_key.to_string(), "tpubD6NzVbkrYhZ4WQdzxL7NmJN7b85ePo4p6RSj9QQHF7te2RR9iUeVSGgnGkoUsB9LBRosgvNbjRv9bcsJgzgBd7QKuxDm23ZewkTRzNSLEDr/0/1/2");
1639 assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1640 assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0/1/2");
1641
1642 let secret_key = DescriptorSecretKey::from_str("[aabbccdd]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0/1/2").unwrap();
1643 let public_key = secret_key.to_public(&secp).unwrap();
1644 assert_eq!(public_key.to_string(), "[aabbccdd]tpubD6NzVbkrYhZ4WQdzxL7NmJN7b85ePo4p6RSj9QQHF7te2RR9iUeVSGgnGkoUsB9LBRosgvNbjRv9bcsJgzgBd7QKuxDm23ZewkTRzNSLEDr/0/1/2");
1645 assert_eq!(public_key.master_fingerprint().to_string(), "aabbccdd");
1646 assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0/1/2");
1647
1648 let secret_key = DescriptorSecretKey::from_str("[aabbccdd/90']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2").unwrap();
1649 let public_key = secret_key.to_public(&secp).unwrap();
1650 assert_eq!(public_key.to_string(), "[aabbccdd/90'/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2");
1651 assert_eq!(public_key.master_fingerprint().to_string(), "aabbccdd");
1652 assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "90'/0'/1'/2");
1653 }
1654
1655 #[test]
1656 fn test_master_fingerprint() {
1657 assert_eq!(
1658 DescriptorPublicKey::from_str(
1659 "02a489e0ea42b56148d212d325b7c67c6460483ff931c303ea311edfef667c8f35",
1660 )
1661 .unwrap()
1662 .master_fingerprint()
1663 .as_bytes(),
1664 b"\xb0\x59\x11\x6a"
1665 );
1666 }
1667
1668 fn get_multipath_xpub(key_str: &str, num_paths: usize) -> DescriptorMultiXKey<bip32::Xpub> {
1669 let desc_key = DescriptorPublicKey::from_str(key_str).unwrap();
1670 assert_eq!(desc_key.num_der_paths(), num_paths);
1671 match desc_key {
1672 DescriptorPublicKey::MultiXPub(xpub) => xpub,
1673 _ => unreachable!(),
1674 }
1675 }
1676
1677 fn get_multipath_xprv(key_str: &str) -> DescriptorMultiXKey<bip32::Xpriv> {
1678 let desc_key = DescriptorSecretKey::from_str(key_str).unwrap();
1679 match desc_key {
1680 DescriptorSecretKey::MultiXPrv(xprv) => xprv,
1681 _ => unreachable!(),
1682 }
1683 }
1684
1685 #[test]
1686 fn multipath_extended_keys() {
1687 let secp = secp256k1::Secp256k1::signing_only();
1688
1689 let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;42;9854>", 4);
1691 assert_eq!(
1692 xpub.derivation_paths.paths(),
1693 &vec![
1694 bip32::DerivationPath::from_str("m/2/0").unwrap(),
1695 bip32::DerivationPath::from_str("m/2/1").unwrap(),
1696 bip32::DerivationPath::from_str("m/2/42").unwrap(),
1697 bip32::DerivationPath::from_str("m/2/9854").unwrap()
1698 ],
1699 );
1700 assert_eq!(
1701 xpub,
1702 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 4)
1703 );
1704 let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;9854>/0/5/10", 3);
1706 assert_eq!(
1707 xpub.derivation_paths.paths(),
1708 &vec![
1709 bip32::DerivationPath::from_str("m/2/0/0/5/10").unwrap(),
1710 bip32::DerivationPath::from_str("m/2/1/0/5/10").unwrap(),
1711 bip32::DerivationPath::from_str("m/2/9854/0/5/10").unwrap()
1712 ],
1713 );
1714 assert_eq!(
1715 xpub,
1716 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 3)
1717 );
1718 let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;9854>/3456/9876/*", 3);
1720 assert_eq!(xpub.wildcard, Wildcard::Unhardened);
1721 assert_eq!(
1722 xpub.derivation_paths.paths(),
1723 &vec![
1724 bip32::DerivationPath::from_str("m/2/0/3456/9876").unwrap(),
1725 bip32::DerivationPath::from_str("m/2/1/3456/9876").unwrap(),
1726 bip32::DerivationPath::from_str("m/2/9854/3456/9876").unwrap()
1727 ],
1728 );
1729 assert_eq!(
1730 xpub,
1731 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 3)
1732 );
1733 let xpub = get_multipath_xpub("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/<0;1>/*", 2);
1735 assert_eq!(xpub.wildcard, Wildcard::Unhardened);
1736 assert_eq!(
1737 xpub.derivation_paths.paths(),
1738 &vec![
1739 bip32::DerivationPath::from_str("m/0").unwrap(),
1740 bip32::DerivationPath::from_str("m/1").unwrap(),
1741 ],
1742 );
1743 assert_eq!(
1744 xpub,
1745 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 2)
1746 );
1747 let xpub = get_multipath_xpub("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1h>/8h/*'", 2);
1750 assert_eq!(xpub.wildcard, Wildcard::Hardened);
1751 assert_eq!(
1752 xpub.derivation_paths.paths(),
1753 &vec![
1754 bip32::DerivationPath::from_str("m/9478'/0'/8'").unwrap(),
1755 bip32::DerivationPath::from_str("m/9478h/1h/8h").unwrap(),
1756 ],
1757 );
1758 assert_eq!(
1759 xpub,
1760 get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 2)
1761 );
1762 let desc_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1>/8h/*'").unwrap();
1764 assert!(desc_key.full_derivation_path().is_none());
1765 assert!(desc_key.is_multipath());
1766 assert_eq!(
1768 desc_key.full_derivation_paths(),
1769 vec![
1770 bip32::DerivationPath::from_str("m/0'/1'/9478'/0'/8'").unwrap(),
1771 bip32::DerivationPath::from_str("m/0'/1'/9478'/1/8'").unwrap(),
1772 ],
1773 );
1774 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()]);
1775
1776 let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;42;9854>");
1778 assert_eq!(
1779 xprv.derivation_paths.paths(),
1780 &vec![
1781 bip32::DerivationPath::from_str("m/2/0").unwrap(),
1782 bip32::DerivationPath::from_str("m/2/1").unwrap(),
1783 bip32::DerivationPath::from_str("m/2/42").unwrap(),
1784 bip32::DerivationPath::from_str("m/2/9854").unwrap()
1785 ],
1786 );
1787 assert_eq!(
1788 xprv,
1789 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1790 );
1791 let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;9854>/0/5/10");
1792 assert_eq!(
1793 xprv.derivation_paths.paths(),
1794 &vec![
1795 bip32::DerivationPath::from_str("m/2/0/0/5/10").unwrap(),
1796 bip32::DerivationPath::from_str("m/2/1/0/5/10").unwrap(),
1797 bip32::DerivationPath::from_str("m/2/9854/0/5/10").unwrap()
1798 ],
1799 );
1800 assert_eq!(
1801 xprv,
1802 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1803 );
1804 let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;9854>/3456/9876/*");
1805 assert_eq!(xprv.wildcard, Wildcard::Unhardened);
1806 assert_eq!(
1807 xprv.derivation_paths.paths(),
1808 &vec![
1809 bip32::DerivationPath::from_str("m/2/0/3456/9876").unwrap(),
1810 bip32::DerivationPath::from_str("m/2/1/3456/9876").unwrap(),
1811 bip32::DerivationPath::from_str("m/2/9854/3456/9876").unwrap()
1812 ],
1813 );
1814 assert_eq!(
1815 xprv,
1816 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1817 );
1818 let xprv = get_multipath_xprv("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/<0;1>/*");
1819 assert_eq!(xprv.wildcard, Wildcard::Unhardened);
1820 assert_eq!(
1821 xprv.derivation_paths.paths(),
1822 &vec![
1823 bip32::DerivationPath::from_str("m/0").unwrap(),
1824 bip32::DerivationPath::from_str("m/1").unwrap(),
1825 ],
1826 );
1827 assert_eq!(
1828 xprv,
1829 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1830 );
1831 let xprv = get_multipath_xprv("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1h>/8h/*'");
1832 assert_eq!(xprv.wildcard, Wildcard::Hardened);
1833 assert_eq!(
1834 xprv.derivation_paths.paths(),
1835 &vec![
1836 bip32::DerivationPath::from_str("m/9478'/0'/8'").unwrap(),
1837 bip32::DerivationPath::from_str("m/9478h/1h/8h").unwrap(),
1838 ],
1839 );
1840 assert_eq!(
1841 xprv,
1842 get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1843 );
1844 let desc_key = DescriptorSecretKey::from_str("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1>/8h/*'").unwrap();
1845 assert!(desc_key.to_public(&secp).is_err());
1846 assert!(desc_key.is_multipath());
1847 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()]);
1848
1849 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;42;9854").unwrap_err();
1854 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/0;1;42;9854>").unwrap_err();
1855 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;1>/96/<0;1>").unwrap_err();
1856 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0>").unwrap_err();
1857 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;>").unwrap_err();
1858 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<;1>").unwrap_err();
1859 DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;1;>").unwrap_err();
1860 }
1861
1862 #[test]
1863 fn test_multixprv_to_public() {
1864 let secp = secp256k1::Secp256k1::signing_only();
1865
1866 let xprv = get_multipath_xprv("[01020304/5]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1'/2'/3/<4;5>/6");
1868 let xpub = DescriptorPublicKey::MultiXPub(xprv.to_public(&secp).unwrap()); assert_eq!(xpub.to_string(), "[01020304/5/1'/2']tpubDBTRkEMEFkUbk3WTz6CFSULyswkTPpPr38AWibf5TVkB5GxuBxbSbmdFGr3jmswwemknyYxAGoX7BJnKfyPy4WXaHmcrxZhfzFwoUFvFtm5/3/<4;5>/6");
1870
1871 get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/2/<3';4'>/5").to_public(&secp).unwrap_err();
1873 get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/2/<3;4>/5/6'").to_public(&secp).unwrap_err();
1874 }
1875
1876 #[test]
1877 fn test_parse_wif() {
1878 let secret_key = "[0dd03d09/0'/1/2']5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ"
1879 .parse()
1880 .unwrap();
1881 if let DescriptorSecretKey::Single(single) = secret_key {
1882 assert_eq!(
1883 single.key.inner,
1884 "0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D"
1885 .parse()
1886 .unwrap()
1887 );
1888 assert_eq!(
1889 single.origin,
1890 Some(("0dd03d09".parse().unwrap(), "m/0'/1/2'".parse().unwrap()))
1891 );
1892 } else {
1893 panic!("expected a DescriptorSecretKey::Single");
1894 }
1895 }
1896
1897 #[test]
1898 #[cfg(feature = "serde")]
1899 fn test_descriptor_public_key_serde() {
1900 let desc = "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2";
1901 let public_key = DescriptorPublicKey::from_str(desc).unwrap();
1902 assert_tokens(&public_key, &[Token::String(desc)]);
1903 }
1904
1905 #[test]
1906 fn definite_keys() {
1907 let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
1909 .parse::<DescriptorPublicKey>()
1910 .unwrap();
1911 assert!(matches!(DefiniteDescriptorKey::new(desc), Ok(..)));
1912 let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/*"
1914 .parse::<DescriptorPublicKey>()
1915 .unwrap();
1916 assert!(matches!(DefiniteDescriptorKey::new(desc), Err(NonDefiniteKeyError::Wildcard)));
1917 let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/<0;1>"
1919 .parse::<DescriptorPublicKey>()
1920 .unwrap();
1921 assert!(matches!(DefiniteDescriptorKey::new(desc), Err(NonDefiniteKeyError::Multipath)));
1922 let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/1'/2"
1924 .parse::<DescriptorPublicKey>()
1925 .unwrap();
1926 assert!(matches!(
1927 DefiniteDescriptorKey::new(desc),
1928 Err(NonDefiniteKeyError::HardenedStep)
1929 ));
1930 }
1931
1932 #[test]
1933 fn definite_key_maximum_depth() {
1934 let key = |depth: u8, steps: usize, wildcard: Wildcard| {
1935 let mut xkey = bip32::Xpub::from_str("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8").unwrap();
1936 xkey.depth = depth;
1937 DescriptorPublicKey::XPub(DescriptorXKey {
1938 origin: None,
1939 xkey,
1940 derivation_path: vec![bip32::ChildNumber::from(0); steps].into(),
1941 wildcard,
1942 })
1943 };
1944 let new = |key| DefiniteDescriptorKey::new(key).map(|_| ());
1945 let too_deep = Err(NonDefiniteKeyError::MaximumDepthExceeded);
1946
1947 assert_eq!(new(key(0, 255, Wildcard::None)), Ok(()));
1949 assert_eq!(new(key(0, 256, Wildcard::None)), too_deep);
1950 assert_eq!(new(key(200, 55, Wildcard::None)), Ok(()));
1951 assert_eq!(new(key(200, 56, Wildcard::None)), too_deep);
1952
1953 assert!(key(200, 54, Wildcard::Unhardened)
1955 .at_derivation_index(7)
1956 .is_ok());
1957 assert_eq!(
1958 key(200, 55, Wildcard::Unhardened)
1959 .at_derivation_index(7)
1960 .map(|_| ()),
1961 too_deep
1962 );
1963
1964 let mut key_with_origin = key(0, 255, Wildcard::None);
1966 if let DescriptorPublicKey::XPub(ref mut xpub) = key_with_origin {
1967 xpub.origin = Some((
1968 bip32::Fingerprint::default(),
1969 vec![bip32::ChildNumber::from(0); 300].into(),
1970 ));
1971 }
1972 assert_eq!(new(key_with_origin), Ok(()));
1973
1974 let desc = Descriptor::new_tr(key(0, 256, Wildcard::None), None).unwrap();
1977 assert_eq!(desc.at_derivation_index(0).map(|_| ()), too_deep);
1978 }
1979
1980 #[test]
1981 fn parse_key_maximum_depth() {
1982 let xpub = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8";
1984 let xprv = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi";
1985 let steps = |n: usize| "/0".repeat(n);
1986 let public = |s: String| DescriptorPublicKey::from_str(&s).map(|_| ());
1987 let secret = |s: String| DescriptorSecretKey::from_str(&s).map(|_| ());
1988 let too_deep = Err(DescriptorKeyParseError::MalformedKeyData(
1989 MalformedKeyDataKind::MaximumDepthExceeded,
1990 ));
1991
1992 assert_eq!(public(format!("{xpub}{}", steps(255))), Ok(()));
1994 assert_eq!(public(format!("{xpub}{}", steps(256))), too_deep);
1995 assert_eq!(public(format!("{xpub}{}/*", steps(254))), Ok(()));
1996 assert_eq!(public(format!("{xpub}{}/*", steps(255))), too_deep);
1997 assert_eq!(public(format!("{xpub}{}/<0;1>", steps(254))), Ok(()));
1998 assert_eq!(public(format!("{xpub}{}/<0;1>", steps(255))), too_deep);
1999 assert_eq!(secret(format!("{xprv}{}/*", steps(254))), Ok(()));
2000 assert_eq!(secret(format!("{xprv}{}/*", steps(255))), too_deep);
2001
2002 let mut xkey = bip32::Xpub::from_str(xpub).unwrap();
2004 xkey.depth = 200;
2005 assert_eq!(public(format!("{xkey}{}", steps(55))), Ok(()));
2006 assert_eq!(public(format!("{xkey}{}", steps(56))), too_deep);
2007
2008 assert_eq!(public(format!("[d34db33f{}]{xpub}{}", steps(300), steps(255))), Ok(()));
2010
2011 let desc = format!("tr({xpub}{})", steps(256));
2013 assert!(Descriptor::<DescriptorPublicKey>::from_str(&desc).is_err());
2014 }
2015
2016 #[test]
2017 fn test_xkey_network() {
2018 use bitcoin::NetworkKind;
2019
2020 let mainnet_xpub = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
2022 .parse::<DescriptorPublicKey>()
2023 .unwrap();
2024 assert_eq!(mainnet_xpub.xkey_network(), Some(NetworkKind::Main));
2025
2026 let testnet_xpub = "tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi"
2028 .parse::<DescriptorPublicKey>()
2029 .unwrap();
2030 assert_eq!(testnet_xpub.xkey_network(), Some(NetworkKind::Test));
2031
2032 let single_key = "021d4ea7132d4e1a362ee5efd8d0b59dd4d1fe8906eefa7dd812b05a46b73d829b"
2034 .parse::<DescriptorPublicKey>()
2035 .unwrap();
2036 assert_eq!(single_key.xkey_network(), None);
2037 }
2038}