Skip to main content

miniscript/descriptor/
key.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use 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/// The descriptor pubkey, either a single pubkey or an xpub.
22#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
23pub enum DescriptorPublicKey {
24    /// Single public key.
25    Single(SinglePub),
26    /// Extended public key (xpub).
27    XPub(DescriptorXKey<bip32::Xpub>),
28    /// Multiple extended public keys.
29    MultiXPub(DescriptorMultiXKey<bip32::Xpub>),
30}
31
32/// The descriptor secret key, either a single private key or an xprv.
33#[derive(Debug, Eq, PartialEq, Clone)]
34pub enum DescriptorSecretKey {
35    /// Single private key.
36    Single(SinglePriv),
37    /// Extended private key (xpriv).
38    XPrv(DescriptorXKey<bip32::Xpriv>),
39    /// Multiple extended private keys.
40    MultiXPrv(DescriptorMultiXKey<bip32::Xpriv>),
41}
42
43/// A descriptor [`SinglePubKey`] with optional origin information.
44#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
45pub struct SinglePub {
46    /// Origin information (fingerprint and derivation path).
47    pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
48    /// The public key.
49    pub key: SinglePubKey,
50}
51
52/// A descriptor [`bitcoin::PrivateKey`] with optional origin information.
53#[derive(Debug, Eq, PartialEq, Clone)]
54pub struct SinglePriv {
55    /// Origin information (fingerprint and derivation path).
56    pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
57    /// The private key.
58    pub key: bitcoin::PrivateKey,
59}
60
61/// An extended key with origin, derivation path, and wildcard.
62#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
63pub struct DescriptorXKey<K: InnerXKey> {
64    /// Origin information
65    pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
66    /// The extended key
67    pub xkey: K,
68    /// The derivation path
69    pub derivation_path: bip32::DerivationPath,
70    /// Whether the descriptor is wildcard
71    pub wildcard: Wildcard,
72}
73
74/// The derivation paths in a multipath key expression.
75#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
76pub struct DerivPaths(Vec<bip32::DerivationPath>);
77
78impl DerivPaths {
79    /// Create a non empty derivation paths list.
80    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    /// Create a derivation paths list containing a single path.
89    pub fn single(path: bip32::DerivationPath) -> Self { Self(vec![path]) }
90
91    /// Get the list of derivation paths.
92    pub fn paths(&self) -> &Vec<bip32::DerivationPath> { &self.0 }
93
94    /// Get the list of derivation paths.
95    pub fn into_paths(self) -> Vec<bip32::DerivationPath> { self.0 }
96}
97
98/// Instance of one or more extended keys, as specified in BIP 389.
99#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
100pub struct DescriptorMultiXKey<K: InnerXKey> {
101    /// Origin information
102    pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
103    /// The extended key
104    pub xkey: K,
105    /// The derivation paths. Never empty.
106    pub derivation_paths: DerivPaths,
107    /// Whether the descriptor is wildcard
108    pub wildcard: Wildcard,
109}
110
111/// Single public key without any origin or range information.
112#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
113pub enum SinglePubKey {
114    /// A bitcoin public key (compressed or uncompressed).
115    FullKey(bitcoin::PublicKey),
116    /// An xonly public key.
117    XOnly(XOnlyPublicKey),
118}
119
120/// A [`DescriptorPublicKey`] without any wildcards.
121#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
122pub struct DefiniteDescriptorKey(DescriptorPublicKey);
123
124/// Network information extracted from extended keys in a descriptor.
125#[derive(Debug, Eq, PartialEq, Clone)]
126pub enum XKeyNetwork {
127    /// No extended keys are present in the descriptor.
128    NoXKeys,
129    /// Extended keys are present but have conflicting network prefixes.
130    Mixed,
131    /// Extended key(s) are present and all have the same network prefix.
132    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
169/// Trait for "extended key" types like `xpub` and `xprv`. Used internally to generalize parsing and
170/// handling of `bip32::Xpub` and `bip32::Xpriv`.
171pub trait InnerXKey: fmt::Display + FromStr {
172    /// Returns the fingerprint of the key
173    fn xkey_fingerprint<C: Signing>(&self, secp: &Secp256k1<C>) -> bip32::Fingerprint;
174
175    /// Returns whether hardened steps can be derived on the key
176    ///
177    /// `true` for `bip32::Xpriv` and `false` for `bip32::Xpub`.
178    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/// Whether a descriptor has a wildcard in it
198#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
199pub enum Wildcard {
200    /// No wildcard
201    None,
202    /// Unhardened wildcard, e.g. *
203    Unhardened,
204    /// Hardened wildcard, e.g. *h
205    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    /// Returns the public key of this key.
220    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    /// Returns the public version of this key, applying all the hardened derivation steps on the
229    /// private key before turning it into a public key.
230    ///
231    /// If the key already has an origin, the derivation steps applied will be appended to the path
232    /// already present, otherwise this key will be treated as a master key and an origin will be
233    /// added with this key's fingerprint and the derivation steps applied.
234    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    /// Returns the public version of this multi-key, applying all the hardened derivation steps that
277    /// are shared among all derivation paths before turning it into a public key.
278    ///
279    /// Errors if there are hardened derivation steps that are not shared among all paths.
280    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/// Kinds of malformed key data
357#[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/// Kinds of malformed key data
386#[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/// Descriptor Key parsing errors
434#[derive(Debug, PartialEq, Eq, Clone)]
435#[non_exhaustive]
436pub enum DescriptorKeyParseError {
437    /// Error while parsing a derivation index
438    DerivationIndexError {
439        /// The invalid index
440        index: String,
441        /// The underlying parse error
442        err: bip32::Error,
443    },
444    /// Error deriving the hardened private key.
445    DeriveHardenedKey(bip32::Error),
446    /// Error indicating the key data was malformed
447    MalformedKeyData(MalformedKeyDataKind),
448    /// Error while parsing the master derivation path.
449    MasterDerivationPath(bip32::Error),
450    /// Error indicating a malformed master fingerprint (invalid hex).
451    MasterFingerprint {
452        /// The invalid fingerprint
453        fingerprint: String,
454        /// The underlying parse error
455        err: bitcoin::hex::HexToArrayError,
456    },
457    /// Attempt to construct a [`DefiniteDescriptorKey`] from an ambiguous key.
458    NonDefiniteKey(NonDefiniteKeyError),
459    /// Error while parsing a simple public key.
460    FullPublicKey(bitcoin::key::ParsePublicKeyError),
461    /// Error while parsing a WIF private key.
462    WifPrivateKey(bitcoin::key::FromWifError),
463    /// Error while parsing an X-only public key (Secp256k1 error).
464    XonlyPublicKey(bitcoin::secp256k1::Error),
465    /// XKey parsing error
466    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/// An error when parsing an extended key.
509#[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    /// Returns the public version of this key.
569    ///
570    /// If the key is an "XPrv", the hardened derivation steps will be applied
571    /// before converting it to a public key.
572    ///
573    /// It will return an error if the key is a "multi-xpriv" that includes
574    /// hardened derivation steps not shared for all paths.
575    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    /// Whether or not this key has multiple derivation paths.
591    pub fn is_multipath(&self) -> bool {
592        match *self {
593            DescriptorSecretKey::Single(..) | DescriptorSecretKey::XPrv(..) => false,
594            DescriptorSecretKey::MultiXPrv(_) => true,
595        }
596    }
597
598    /// Get as many keys as derivation paths in this key.
599    ///
600    /// For raw keys and single-path extended keys it will return the key itself.
601    /// For multipath extended keys it will return a single-path extended key per derivation
602    /// path.
603    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
625/// Writes the fingerprint of the origin, if there is one.
626pub(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
642/// Writes a derivation path to the formatter, no leading 'm'
643fn 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
650/// Writes multiple derivation paths to the formatter, no leading 'm'.
651/// NOTE: we assume paths only differ at a single index, as prescribed by BIP389.
652/// Will panic if the list of paths is empty.
653pub(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        // A "raw" public key without any origin is the least we accept.
679        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    /// The fingerprint of the master key associated with this key, `0x00000000` if none.
754    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    /// Full path, from the master key
792    ///
793    /// For wildcard keys this will return the path up to the wildcard, so you
794    /// can get full paths by appending one additional derivation step, according
795    /// to the wildcard type (hardened or normal).
796    ///
797    /// For multipath extended keys, this returns `None`.
798    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    /// Returns a vector containing the full derivation paths from the master key.
820    /// The vector will contain just one element for single keys, and multiple elements
821    /// for multipath extended keys.
822    ///
823    /// For wildcard keys this will return the path up to the wildcard, so you
824    /// can get full paths by appending one additional derivation step, according
825    /// to the wildcard type (hardened or normal).
826    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    /// Derivation path without the origin prefix.
847    ///
848    /// For wildcard keys this will return the path up to the wildcard, so you
849    /// can get full paths by appending one additional derivation step, according
850    /// to the wildcard type (hardened or normal).
851    ///
852    /// For multipath extended keys, this returns `None`.
853    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    /// Returns a vector of derivation paths without the origin prefix.
862    ///
863    /// For wildcard keys this will return the path up to the wildcard, so you
864    /// can get full paths by appending one additional derivation step, according
865    /// to the wildcard type (hardened or normal).
866    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    /// Whether or not the key has a wildcard
879    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    /// Return a Wildcard if key is a XKey
888    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    /// Whether or not the key has a hardened step in path
897    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    /// Whether deriving this key, including a wildcard step, would go deeper than BIP32's maximum
914    /// depth of 255.
915    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    /// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
932    /// *definite* key (i.e. one where all the derivation paths are set).
933    ///
934    /// # Returns
935    ///
936    /// - If this key is not an xpub, returns `self`.
937    /// - If this key is an xpub but does not have a wildcard, returns `self`.
938    /// - Otherwise, returns the xpub at derivation `index` (removing the wildcard).
939    ///
940    /// # Errors
941    ///
942    /// - If `index` is hardened.
943    /// - If derivation path contains a hardened step.
944    /// - If the key contains multi-path derivations
945    /// - If deriving the key would go deeper than BIP32's maximum depth of 255
946    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    /// Whether or not this key has multiple derivation paths.
980    pub fn is_multipath(&self) -> bool {
981        match *self {
982            DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
983            DescriptorPublicKey::MultiXPub(_) => true,
984        }
985    }
986
987    /// Get as many keys as derivation paths in this key.
988    ///
989    /// For raw public key and single-path extended keys it will return the key itself.
990    /// For multipath extended keys it will return a single-path extended key per derivation
991    /// path.
992    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    /// Get the network of this key, if it's an extended key.
1014    ///
1015    /// Returns `None` for single keys (non-extended keys), `Some(NetworkKind)` for extended keys.
1016    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
1062// Parse the origin information part of a descriptor key.
1063fn 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
1125/// Whether deriving from an extended key at `depth` along any of `paths`, plus one more step for a
1126/// wildcard, would go deeper than BIP32's maximum depth of 255.
1127///
1128/// The paths hold only the steps after the extended key. Its depth already includes the steps of
1129/// its origin, so those are not counted again.
1130fn 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                // BIP389 defines a new step in the derivation path. This step contains two or more
1172                // derivation indexes in the form '<1;2;3';4h;5H;6>'.
1173                if p.starts_with('<') && p.ends_with('>') {
1174                    // There may only be one occurrence of this step.
1175                    if multipath {
1176                        return Some(Err(DescriptorKeyParseError::MalformedKeyData(
1177                            MalformedKeyDataKind::MultipleDerivationPathIndexSteps,
1178                        )));
1179                    }
1180                    multipath = true;
1181
1182                    // The step must contain at least two derivation indexes.
1183                    // So it's at least '<' + a number + ';' + a number + '>'.
1184                    if p.len() < 5 || !p.contains(';') {
1185                        return Some(Err(DescriptorKeyParseError::MalformedKeyData(
1186                            MalformedKeyDataKind::InvalidMultiIndexStep,
1187                        )));
1188                    }
1189
1190                    // Collect all derivation indexes at this step.
1191                    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                    // Not a BIP389 step, just a regular derivation index.
1207                    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        // Now we've got all derivation indexes in a list of vectors of indexes. If the derivation
1219        // path was empty then this list is empty. If the derivation path didn't contain any BIP389
1220        // step all the vectors of indexes contain a single element. If it did though, one of the
1221        // vectors contains more than one element.
1222        // Now transform this list of vectors of steps into distinct derivation paths.
1223        .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            // If the step is a BIP389 one, create as many paths as there is indexes.
1238            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    /// Compares this key with a `keysource` and returns the matching derivation path, if any.
1254    ///
1255    /// For keys that have an origin, the `keysource`'s fingerprint will be compared
1256    /// with the origin's fingerprint, and the `keysource`'s path will be compared with the concatenation of the
1257    /// origin's and key's paths.
1258    ///
1259    /// If the key `wildcard`, the last item of the `keysource`'s path will be ignored,
1260    ///
1261    /// ## Examples
1262    ///
1263    /// ```
1264    /// # use std::str::FromStr;
1265    /// # fn body() -> Result<(), ()> {
1266    /// use miniscript::bitcoin::bip32;
1267    /// use miniscript::descriptor::DescriptorPublicKey;
1268    ///
1269    /// let ctx = miniscript::bitcoin::secp256k1::Secp256k1::signing_only();
1270    ///
1271    /// let key = DescriptorPublicKey::from_str("[d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*").or(Err(()))?;
1272    /// let xpub = match key {
1273    ///     DescriptorPublicKey::XPub(xpub) => xpub,
1274    ///     _ => panic!("Parsing Error"),
1275    /// };
1276    ///
1277    /// assert_eq!(
1278    ///     xpub.matches(&(
1279    ///         bip32::Fingerprint::from_str("d34db33f").or(Err(()))?,
1280    ///         bip32::DerivationPath::from_str("m/44'/0'/0'/1/42").or(Err(()))?
1281    ///     ), &ctx),
1282    ///     Some(bip32::DerivationPath::from_str("m/44'/0'/0'/1").or(Err(()))?)
1283    /// );
1284    /// assert_eq!(
1285    ///     xpub.matches(&(
1286    ///         bip32::Fingerprint::from_str("ffffffff").or(Err(()))?,
1287    ///         bip32::DerivationPath::from_str("m/44'/0'/0'/1/42").or(Err(()))?
1288    ///     ), &ctx),
1289    ///     None
1290    /// );
1291    /// assert_eq!(
1292    ///     xpub.matches(&(
1293    ///         bip32::Fingerprint::from_str("d34db33f").or(Err(()))?,
1294    ///         bip32::DerivationPath::from_str("m/44'/0'/0'/100/0").or(Err(()))?
1295    ///     ), &ctx),
1296    ///     None
1297    /// );
1298    /// # Ok(())
1299    /// # }
1300    /// # body().unwrap()
1301    /// ```
1302    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    /// Computes the public key corresponding to this descriptor key.
1371    /// When deriving from an XOnlyPublicKey, it adds the default 0x02 y-coordinate
1372    /// and returns the obtained full [`bitcoin::PublicKey`]. All BIP32 derivations
1373    /// always return a compressed key
1374    ///
1375    /// Will return an error if the descriptor key has any hardened derivation steps in its path. To
1376    /// avoid this error you should replace any such public keys first with [`crate::Descriptor::translate_pk`].
1377    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    /// Constructs an instance from a descriptor key.
1402    ///
1403    /// Returns an error if the key has a wildcard, a hardened derivation step or several derivation
1404    /// paths, or if deriving it would go deeper than BIP32's maximum depth of 255.
1405    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    /// The fingerprint of the master key associated with this key, `0x00000000` if none.
1420    pub fn master_fingerprint(&self) -> bip32::Fingerprint { self.0.master_fingerprint() }
1421
1422    /// Full path from the master key if not a multipath extended key.
1423    pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
1424        self.0.full_derivation_path()
1425    }
1426
1427    /// Full paths from the master key. The vector will contain just one path for single
1428    /// keys, and multiple ones for multipath extended keys
1429    pub fn full_derivation_paths(&self) -> Vec<bip32::DerivationPath> {
1430        self.0.full_derivation_paths()
1431    }
1432
1433    /// Reference to the underlying `DescriptorPublicKey`
1434    pub fn as_descriptor_public_key(&self) -> &DescriptorPublicKey { &self.0 }
1435
1436    /// Converts the definite key into a generic one
1437    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        // And ones with misplaced wildcard
1529        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        // And ones with invalid fingerprints
1536        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        // And ones with invalid xpubs..
1543        let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*";
1544        assert_eq!(
1545            DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1546            "base58 encoding error"
1547        );
1548
1549        // ..or invalid raw keys
1550        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        // ..or invalid separators
1557        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        // fuzzer errors
1564        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        // fuzz failure, hybrid keys
1571        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        // Xpubs are invalid
1581        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        // And ones with invalid fingerprints
1590        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        // ..or invalid raw keys
1597        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        // We can have a key in a descriptor that has multiple paths
1690        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        // Even if it's in the middle of the derivation path.
1705        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        // Even if it is a wildcard extended key.
1719        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        // Also even if it has an origin.
1734        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        // Also if it has hardened steps in the derivation path. In fact, it can also have hardened
1748        // indexes even at the step with multiple indexes!
1749        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        // You can't get the "full derivation path" for a multipath extended public key.
1763        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        // But you can get all the derivation paths
1767        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        // All the same but with extended private keys instead of xpubs.
1777        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        // It's invalid to:
1850        // - Not have opening or closing brackets
1851        // - Have multiple steps with different indexes
1852        // - Only have one index within the brackets
1853        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        // Works if all hardended derivation steps are part of the shared path
1867        let xprv = get_multipath_xprv("[01020304/5]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1'/2'/3/<4;5>/6");
1868        let xpub = DescriptorPublicKey::MultiXPub(xprv.to_public(&secp).unwrap()); // wrap in a DescriptorPublicKey to have Display
1869        assert_eq!(xpub.to_string(), "[01020304/5/1'/2']tpubDBTRkEMEFkUbk3WTz6CFSULyswkTPpPr38AWibf5TVkB5GxuBxbSbmdFGr3jmswwemknyYxAGoX7BJnKfyPy4WXaHmcrxZhfzFwoUFvFtm5/3/<4;5>/6");
1870
1871        // Fails if they're part of the multi-path specifier or following it
1872        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        // basic xpub
1908        let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
1909            .parse::<DescriptorPublicKey>()
1910            .unwrap();
1911        assert!(matches!(DefiniteDescriptorKey::new(desc), Ok(..)));
1912        // xpub with wildcard
1913        let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/*"
1914            .parse::<DescriptorPublicKey>()
1915            .unwrap();
1916        assert!(matches!(DefiniteDescriptorKey::new(desc), Err(NonDefiniteKeyError::Wildcard)));
1917        // multipath xpub
1918        let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/<0;1>"
1919            .parse::<DescriptorPublicKey>()
1920            .unwrap();
1921        assert!(matches!(DefiniteDescriptorKey::new(desc), Err(NonDefiniteKeyError::Multipath)));
1922        // xpub with hardened path
1923        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        // BIP32 depth stops at 255, so an xpub at `depth` can take 255 - depth more steps.
1948        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        // Deriving at an index turns the wildcard into one more step.
1954        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        // Origin steps don't count, since the xpub's depth already includes them.
1965        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        // A descriptor with such a key doesn't become definite, so it can't panic later when
1975        // deriving its script pubkey.
1976        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        // BIP32 test vector 1 master keys, at depth 0.
1983        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        // BIP32 depth stops at 255. A wildcard or a multipath step counts as one more step.
1993        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        // An xpub at depth 200 can take 55 more steps.
2003        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        // Origin steps don't count, since the xpub's depth already includes them.
2009        assert_eq!(public(format!("[d34db33f{}]{xpub}{}", steps(300), steps(255))), Ok(()));
2010
2011        // A descriptor with such a key fails to parse, before anything can be derived from it.
2012        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        // Test mainnet xpub
2021        let mainnet_xpub = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
2022            .parse::<DescriptorPublicKey>()
2023            .unwrap();
2024        assert_eq!(mainnet_xpub.xkey_network(), Some(NetworkKind::Main));
2025
2026        // Test testnet xpub
2027        let testnet_xpub = "tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi"
2028            .parse::<DescriptorPublicKey>()
2029            .unwrap();
2030        assert_eq!(testnet_xpub.xkey_network(), Some(NetworkKind::Test));
2031
2032        // Test single public key (no extended key)
2033        let single_key = "021d4ea7132d4e1a362ee5efd8d0b59dd4d1fe8906eefa7dd812b05a46b73d829b"
2034            .parse::<DescriptorPublicKey>()
2035            .unwrap();
2036        assert_eq!(single_key.xkey_network(), None);
2037    }
2038}