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 crate::prelude::*;
16#[cfg(feature = "serde")]
17use crate::serde::{Deserialize, Deserializer, Serialize, Serializer};
18use crate::{hash256, MiniscriptKey, ToPublicKey};
19
20/// The descriptor pubkey, either a single pubkey or an xpub.
21#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
22pub enum DescriptorPublicKey {
23    /// Single public key.
24    Single(SinglePub),
25    /// Extended public key (xpub).
26    XPub(DescriptorXKey<bip32::Xpub>),
27    /// Multiple extended public keys.
28    MultiXPub(DescriptorMultiXKey<bip32::Xpub>),
29}
30
31/// The descriptor secret key, either a single private key or an xprv.
32#[derive(Debug, Eq, PartialEq, Clone)]
33pub enum DescriptorSecretKey {
34    /// Single private key.
35    Single(SinglePriv),
36    /// Extended private key (xpriv).
37    XPrv(DescriptorXKey<bip32::Xpriv>),
38    /// Multiple extended private keys.
39    MultiXPrv(DescriptorMultiXKey<bip32::Xpriv>),
40}
41
42/// A descriptor [`SinglePubKey`] with optional origin information.
43#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
44pub struct SinglePub {
45    /// Origin information (fingerprint and derivation path).
46    pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
47    /// The public key.
48    pub key: SinglePubKey,
49}
50
51/// A descriptor [`bitcoin::PrivateKey`] with optional origin information.
52#[derive(Debug, Eq, PartialEq, Clone)]
53pub struct SinglePriv {
54    /// Origin information (fingerprint and derivation path).
55    pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
56    /// The private key.
57    pub key: bitcoin::PrivateKey,
58}
59
60/// An extended key with origin, derivation path, and wildcard.
61#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
62pub struct DescriptorXKey<K: InnerXKey> {
63    /// Origin information
64    pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
65    /// The extended key
66    pub xkey: K,
67    /// The derivation path
68    pub derivation_path: bip32::DerivationPath,
69    /// Whether the descriptor is wildcard
70    pub wildcard: Wildcard,
71}
72
73/// The derivation paths in a multipath key expression.
74#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
75pub struct DerivPaths(Vec<bip32::DerivationPath>);
76
77impl DerivPaths {
78    /// Create a non empty derivation paths list.
79    pub fn new(paths: Vec<bip32::DerivationPath>) -> Option<DerivPaths> {
80        if paths.is_empty() {
81            None
82        } else {
83            Some(DerivPaths(paths))
84        }
85    }
86
87    /// Get the list of derivation paths.
88    pub fn paths(&self) -> &Vec<bip32::DerivationPath> { &self.0 }
89
90    /// Get the list of derivation paths.
91    pub fn into_paths(self) -> Vec<bip32::DerivationPath> { self.0 }
92}
93
94/// Instance of one or more extended keys, as specified in BIP 389.
95#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
96pub struct DescriptorMultiXKey<K: InnerXKey> {
97    /// Origin information
98    pub origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
99    /// The extended key
100    pub xkey: K,
101    /// The derivation paths. Never empty.
102    pub derivation_paths: DerivPaths,
103    /// Whether the descriptor is wildcard
104    pub wildcard: Wildcard,
105}
106
107/// Single public key without any origin or range information.
108#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
109pub enum SinglePubKey {
110    /// A bitcoin public key (compressed or uncompressed).
111    FullKey(bitcoin::PublicKey),
112    /// An xonly public key.
113    XOnly(XOnlyPublicKey),
114}
115
116/// A [`DescriptorPublicKey`] without any wildcards.
117#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
118pub struct DefiniteDescriptorKey(DescriptorPublicKey);
119
120/// Network information extracted from extended keys in a descriptor.
121#[derive(Debug, Eq, PartialEq, Clone)]
122pub enum XKeyNetwork {
123    /// No extended keys are present in the descriptor.
124    NoXKeys,
125    /// Extended keys are present but have conflicting network prefixes.
126    Mixed,
127    /// Extended key(s) are present and all have the same network prefix.
128    Single(NetworkKind),
129}
130
131impl fmt::Display for DescriptorSecretKey {
132    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133        match self {
134            DescriptorSecretKey::Single(ref sk) => {
135                maybe_fmt_master_id(f, &sk.origin)?;
136                sk.key.fmt(f)?;
137                Ok(())
138            }
139            DescriptorSecretKey::XPrv(ref xprv) => {
140                maybe_fmt_master_id(f, &xprv.origin)?;
141                xprv.xkey.fmt(f)?;
142                fmt_derivation_path(f, &xprv.derivation_path)?;
143                match xprv.wildcard {
144                    Wildcard::None => {}
145                    Wildcard::Unhardened => write!(f, "/*")?,
146                    Wildcard::Hardened => write!(f, "/*h")?,
147                }
148                Ok(())
149            }
150            DescriptorSecretKey::MultiXPrv(ref xprv) => {
151                maybe_fmt_master_id(f, &xprv.origin)?;
152                xprv.xkey.fmt(f)?;
153                fmt_derivation_paths(f, xprv.derivation_paths.paths())?;
154                match xprv.wildcard {
155                    Wildcard::None => {}
156                    Wildcard::Unhardened => write!(f, "/*")?,
157                    Wildcard::Hardened => write!(f, "/*h")?,
158                }
159                Ok(())
160            }
161        }
162    }
163}
164
165/// Trait for "extended key" types like `xpub` and `xprv`. Used internally to generalize parsing and
166/// handling of `bip32::Xpub` and `bip32::Xpriv`.
167pub trait InnerXKey: fmt::Display + FromStr {
168    /// Returns the fingerprint of the key
169    fn xkey_fingerprint<C: Signing>(&self, secp: &Secp256k1<C>) -> bip32::Fingerprint;
170
171    /// Returns whether hardened steps can be derived on the key
172    ///
173    /// `true` for `bip32::Xpriv` and `false` for `bip32::Xpub`.
174    fn can_derive_hardened() -> bool;
175}
176
177impl InnerXKey for bip32::Xpub {
178    fn xkey_fingerprint<C: Signing>(&self, _secp: &Secp256k1<C>) -> bip32::Fingerprint {
179        self.fingerprint()
180    }
181
182    fn can_derive_hardened() -> bool { false }
183}
184
185impl InnerXKey for bip32::Xpriv {
186    fn xkey_fingerprint<C: Signing>(&self, secp: &Secp256k1<C>) -> bip32::Fingerprint {
187        self.fingerprint(secp)
188    }
189
190    fn can_derive_hardened() -> bool { true }
191}
192
193/// Whether a descriptor has a wildcard in it
194#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
195pub enum Wildcard {
196    /// No wildcard
197    None,
198    /// Unhardened wildcard, e.g. *
199    Unhardened,
200    /// Hardened wildcard, e.g. *h
201    Hardened,
202}
203
204impl SinglePriv {
205    /// Returns the public key of this key.
206    fn to_public<C: Signing>(&self, secp: &Secp256k1<C>) -> SinglePub {
207        let pub_key = self.key.public_key(secp);
208
209        SinglePub { origin: self.origin.clone(), key: SinglePubKey::FullKey(pub_key) }
210    }
211}
212
213impl DescriptorXKey<bip32::Xpriv> {
214    /// Returns the public version of this key, applying all the hardened derivation steps on the
215    /// private key before turning it into a public key.
216    ///
217    /// If the key already has an origin, the derivation steps applied will be appended to the path
218    /// already present, otherwise this key will be treated as a master key and an origin will be
219    /// added with this key's fingerprint and the derivation steps applied.
220    fn to_public<C: Signing>(
221        &self,
222        secp: &Secp256k1<C>,
223    ) -> Result<DescriptorXKey<bip32::Xpub>, DescriptorKeyParseError> {
224        let unhardened = self
225            .derivation_path
226            .into_iter()
227            .rev()
228            .take_while(|c| c.is_normal())
229            .count();
230        let last_hardened_idx = self.derivation_path.len() - unhardened;
231
232        let hardened_path = &self.derivation_path[..last_hardened_idx];
233        let unhardened_path = &self.derivation_path[last_hardened_idx..];
234
235        let xprv = self
236            .xkey
237            .derive_priv(secp, &hardened_path)
238            .map_err(DescriptorKeyParseError::DeriveHardenedKey)?;
239
240        let xpub = bip32::Xpub::from_priv(secp, &xprv);
241
242        let origin = match &self.origin {
243            Some((fingerprint, path)) => {
244                Some((*fingerprint, path.into_iter().chain(hardened_path).copied().collect()))
245            }
246            None if !hardened_path.is_empty() => {
247                Some((self.xkey.fingerprint(secp), hardened_path.into()))
248            }
249            None => None,
250        };
251
252        Ok(DescriptorXKey {
253            origin,
254            xkey: xpub,
255            derivation_path: unhardened_path.into(),
256            wildcard: self.wildcard,
257        })
258    }
259}
260
261impl DescriptorMultiXKey<bip32::Xpriv> {
262    /// Returns the public version of this multi-key, applying all the hardened derivation steps that
263    /// are shared among all derivation paths before turning it into a public key.
264    ///
265    /// Errors if there are hardened derivation steps that are not shared among all paths.
266    fn to_public<C: Signing>(
267        &self,
268        secp: &Secp256k1<C>,
269    ) -> Result<DescriptorMultiXKey<bip32::Xpub>, DescriptorKeyParseError> {
270        let deriv_paths = self.derivation_paths.paths();
271
272        let shared_prefix: Vec<_> = deriv_paths[0]
273            .into_iter()
274            .enumerate()
275            .take_while(|(index, child_num)| {
276                deriv_paths[1..].iter().all(|other_path| {
277                    other_path.len() > *index && other_path[*index] == **child_num
278                })
279            })
280            .map(|(_, child_num)| *child_num)
281            .collect();
282
283        let suffixes: Vec<Vec<_>> = deriv_paths
284            .iter()
285            .map(|path| {
286                path.into_iter()
287                    .skip(shared_prefix.len())
288                    .map(|child_num| {
289                        if child_num.is_normal() {
290                            Ok(*child_num)
291                        } else {
292                            Err(DescriptorKeyParseError::MalformedKeyData(
293                                MalformedKeyDataKind::InvalidMultiXKeyDerivation,
294                            ))
295                        }
296                    })
297                    .collect()
298            })
299            .collect::<Result<_, _>>()?;
300
301        let unhardened = shared_prefix
302            .iter()
303            .rev()
304            .take_while(|c| c.is_normal())
305            .count();
306        let last_hardened_idx = shared_prefix.len() - unhardened;
307        let hardened_path = &shared_prefix[..last_hardened_idx];
308        let unhardened_path = &shared_prefix[last_hardened_idx..];
309
310        let xprv = self
311            .xkey
312            .derive_priv(secp, &hardened_path)
313            .map_err(DescriptorKeyParseError::DeriveHardenedKey)?;
314        let xpub = bip32::Xpub::from_priv(secp, &xprv);
315
316        let origin = match &self.origin {
317            Some((fingerprint, path)) => {
318                Some((*fingerprint, path.into_iter().chain(hardened_path).copied().collect()))
319            }
320            None if !hardened_path.is_empty() => {
321                Some((self.xkey.fingerprint(secp), hardened_path.into()))
322            }
323            None => None,
324        };
325        let new_deriv_paths = suffixes
326            .into_iter()
327            .map(|suffix| {
328                let path = unhardened_path.iter().copied().chain(suffix);
329                path.collect::<Vec<_>>().into()
330            })
331            .collect();
332
333        Ok(DescriptorMultiXKey {
334            origin,
335            xkey: xpub,
336            derivation_paths: DerivPaths::new(new_deriv_paths).expect("not empty"),
337            wildcard: self.wildcard,
338        })
339    }
340}
341
342/// Kinds of malformed key data
343#[derive(Debug, PartialEq, Eq, Clone)]
344#[non_exhaustive]
345#[allow(missing_docs)]
346pub enum NonDefiniteKeyError {
347    Wildcard,
348    Multipath,
349    HardenedStep,
350}
351
352impl fmt::Display for NonDefiniteKeyError {
353    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354        match *self {
355            Self::Wildcard => f.write_str("key with a wildcard cannot be a DerivedDescriptorKey"),
356            Self::Multipath => f.write_str("multipath key cannot be a DerivedDescriptorKey"),
357            Self::HardenedStep => {
358                f.write_str("key with hardened derivation steps cannot be a DerivedDescriptorKey")
359            }
360        }
361    }
362}
363
364#[cfg(feature = "std")]
365impl error::Error for NonDefiniteKeyError {}
366
367/// Kinds of malformed key data
368#[derive(Debug, PartialEq, Eq, Clone)]
369#[non_exhaustive]
370#[allow(missing_docs)]
371pub enum MalformedKeyDataKind {
372    EmptyKey,
373    EncounteredUnprintableCharacter,
374    InvalidFullPublicKeyPrefix,
375    InvalidMasterFingerprintLength,
376    InvalidMultiIndexStep,
377    InvalidMultiXKeyDerivation,
378    InvalidPublicKeyLength,
379    InvalidWildcardInDerivationPath,
380    KeyTooShort,
381    MultipleFingerprintsInPublicKey,
382    MultipleDerivationPathIndexSteps,
383    NoKeyAfterOrigin,
384    NoMasterFingerprintFound,
385    UnclosedSquareBracket,
386}
387
388impl fmt::Display for MalformedKeyDataKind {
389    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
390        let err = match self {
391            Self::EmptyKey => "empty key",
392            Self::EncounteredUnprintableCharacter => "encountered an unprintable character",
393            Self::InvalidFullPublicKeyPrefix => "only full public keys with prefixes '02', '03' or '04' are allowed",
394            Self::InvalidMasterFingerprintLength => "master fingerprint should be 8 characters long",
395            Self::InvalidMultiIndexStep => "invalid multi index step in multipath descriptor",
396            Self::InvalidMultiXKeyDerivation => "can't make a multi-xpriv with hardened derivation steps that are not shared among all paths into a public key",
397            Self::InvalidPublicKeyLength => "public keys must be 64, 66 or 130 characters in size",
398            Self::InvalidWildcardInDerivationPath => "'*' may only appear as last element in a derivation path",
399            Self::KeyTooShort => "key too short",
400            Self::MultipleFingerprintsInPublicKey => "multiple ']' in Descriptor Public Key",
401            Self::MultipleDerivationPathIndexSteps => "'<' may only appear once in a derivation path",
402            Self::NoKeyAfterOrigin => "no key after origin",
403            Self::NoMasterFingerprintFound => "no master fingerprint found after '['",
404            Self::UnclosedSquareBracket => "unclosed '['",
405        };
406
407        f.write_str(err)
408    }
409}
410
411/// Descriptor Key parsing errors
412#[derive(Debug, PartialEq, Eq, Clone)]
413#[non_exhaustive]
414pub enum DescriptorKeyParseError {
415    /// Error while parsing a BIP32 extended private key
416    Bip32Xpriv(bip32::Error),
417    /// Error while parsing a BIP32 extended public key
418    Bip32Xpub(bip32::Error),
419    /// Error while parsing a derivation index
420    DerivationIndexError {
421        /// The invalid index
422        index: String,
423        /// The underlying parse error
424        err: bitcoin::bip32::Error,
425    },
426    /// Error deriving the hardened private key.
427    DeriveHardenedKey(bip32::Error),
428    /// Error indicating the key data was malformed
429    MalformedKeyData(MalformedKeyDataKind),
430    /// Error while parsing the master derivation path.
431    MasterDerivationPath(bip32::Error),
432    /// Error indicating a malformed master fingerprint (invalid hex).
433    MasterFingerprint {
434        /// The invalid fingerprint
435        fingerprint: String,
436        /// The underlying parse error
437        err: bitcoin::hex::HexToArrayError,
438    },
439    /// Attempt to construct a [`DefiniteDescriptorKey`] from an ambiguous key.
440    NonDefiniteKey(NonDefiniteKeyError),
441    /// Error while parsing a simple public key.
442    FullPublicKey(bitcoin::key::ParsePublicKeyError),
443    /// Error while parsing a WIF private key.
444    WifPrivateKey(bitcoin::key::FromWifError),
445    /// Error while parsing an X-only public key (Secp256k1 error).
446    XonlyPublicKey(bitcoin::secp256k1::Error),
447}
448
449impl fmt::Display for DescriptorKeyParseError {
450    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
451        match self {
452            Self::Bip32Xpriv(err) => err.fmt(f),
453            Self::Bip32Xpub(err) => err.fmt(f),
454            Self::DerivationIndexError { index, err } => {
455                write!(f, "at derivation index '{index}': {err}")
456            }
457            Self::DeriveHardenedKey(err) => err.fmt(f),
458            Self::MalformedKeyData(err) => err.fmt(f),
459            Self::MasterDerivationPath(err) => err.fmt(f),
460            Self::MasterFingerprint { fingerprint, err } => {
461                write!(f, "on master fingerprint '{fingerprint}': {err}")
462            }
463            Self::NonDefiniteKey(err) => err.fmt(f),
464            Self::FullPublicKey(err) => err.fmt(f),
465            Self::WifPrivateKey(err) => err.fmt(f),
466            Self::XonlyPublicKey(err) => err.fmt(f),
467        }
468    }
469}
470
471#[cfg(feature = "std")]
472impl error::Error for DescriptorKeyParseError {
473    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
474        match self {
475            Self::Bip32Xpriv(err)
476            | Self::Bip32Xpub(err)
477            | Self::DerivationIndexError { err, .. }
478            | Self::DeriveHardenedKey(err)
479            | Self::MasterDerivationPath(err) => Some(err),
480            Self::MasterFingerprint { err, .. } => Some(err),
481            Self::NonDefiniteKey(err) => Some(err),
482            Self::FullPublicKey(err) => Some(err),
483            Self::WifPrivateKey(err) => Some(err),
484            Self::XonlyPublicKey(err) => Some(err),
485            Self::MalformedKeyData(_) => None,
486        }
487    }
488}
489
490impl fmt::Display for DescriptorPublicKey {
491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
492        match *self {
493            Self::Single(ref pk) => {
494                maybe_fmt_master_id(f, &pk.origin)?;
495                match pk.key {
496                    SinglePubKey::FullKey(full_key) => full_key.fmt(f),
497                    SinglePubKey::XOnly(x_only_key) => x_only_key.fmt(f),
498                }?;
499                Ok(())
500            }
501            Self::XPub(ref xpub) => {
502                maybe_fmt_master_id(f, &xpub.origin)?;
503                xpub.xkey.fmt(f)?;
504                fmt_derivation_path(f, &xpub.derivation_path)?;
505                match xpub.wildcard {
506                    Wildcard::None => {}
507                    Wildcard::Unhardened => write!(f, "/*")?,
508                    Wildcard::Hardened => write!(f, "/*h")?,
509                }
510                Ok(())
511            }
512            Self::MultiXPub(ref xpub) => {
513                maybe_fmt_master_id(f, &xpub.origin)?;
514                xpub.xkey.fmt(f)?;
515                fmt_derivation_paths(f, xpub.derivation_paths.paths())?;
516                match xpub.wildcard {
517                    Wildcard::None => {}
518                    Wildcard::Unhardened => write!(f, "/*")?,
519                    Wildcard::Hardened => write!(f, "/*h")?,
520                }
521                Ok(())
522            }
523        }
524    }
525}
526
527impl DescriptorSecretKey {
528    /// Returns the public version of this key.
529    ///
530    /// If the key is an "XPrv", the hardened derivation steps will be applied
531    /// before converting it to a public key.
532    ///
533    /// It will return an error if the key is a "multi-xpriv" that includes
534    /// hardened derivation steps not shared for all paths.
535    pub fn to_public<C: Signing>(
536        &self,
537        secp: &Secp256k1<C>,
538    ) -> Result<DescriptorPublicKey, DescriptorKeyParseError> {
539        let pk = match self {
540            DescriptorSecretKey::Single(prv) => DescriptorPublicKey::Single(prv.to_public(secp)),
541            DescriptorSecretKey::XPrv(xprv) => DescriptorPublicKey::XPub(xprv.to_public(secp)?),
542            DescriptorSecretKey::MultiXPrv(xprv) => {
543                DescriptorPublicKey::MultiXPub(xprv.to_public(secp)?)
544            }
545        };
546
547        Ok(pk)
548    }
549
550    /// Whether or not this key has multiple derivation paths.
551    pub fn is_multipath(&self) -> bool {
552        match *self {
553            DescriptorSecretKey::Single(..) | DescriptorSecretKey::XPrv(..) => false,
554            DescriptorSecretKey::MultiXPrv(_) => true,
555        }
556    }
557
558    /// Get as many keys as derivation paths in this key.
559    ///
560    /// For raw keys and single-path extended keys it will return the key itself.
561    /// For multipath extended keys it will return a single-path extended key per derivation
562    /// path.
563    pub fn into_single_keys(self) -> Vec<DescriptorSecretKey> {
564        match self {
565            DescriptorSecretKey::Single(..) | DescriptorSecretKey::XPrv(..) => vec![self],
566            DescriptorSecretKey::MultiXPrv(xpub) => {
567                let DescriptorMultiXKey { origin, xkey, derivation_paths, wildcard } = xpub;
568                derivation_paths
569                    .into_paths()
570                    .into_iter()
571                    .map(|derivation_path| {
572                        DescriptorSecretKey::XPrv(DescriptorXKey {
573                            origin: origin.clone(),
574                            xkey,
575                            derivation_path,
576                            wildcard,
577                        })
578                    })
579                    .collect()
580            }
581        }
582    }
583}
584
585/// Writes the fingerprint of the origin, if there is one.
586fn maybe_fmt_master_id(
587    f: &mut fmt::Formatter,
588    origin: &Option<(bip32::Fingerprint, bip32::DerivationPath)>,
589) -> fmt::Result {
590    if let Some((ref master_id, ref master_deriv)) = *origin {
591        fmt::Formatter::write_str(f, "[")?;
592        for byte in master_id.as_bytes().iter() {
593            write!(f, "{:02x}", byte)?;
594        }
595        fmt_derivation_path(f, master_deriv)?;
596        fmt::Formatter::write_str(f, "]")?;
597    }
598
599    Ok(())
600}
601
602/// Writes a derivation path to the formatter, no leading 'm'
603fn fmt_derivation_path(f: &mut fmt::Formatter, path: &bip32::DerivationPath) -> fmt::Result {
604    for child in path {
605        write!(f, "/{}", child)?;
606    }
607    Ok(())
608}
609
610/// Writes multiple derivation paths to the formatter, no leading 'm'.
611/// NOTE: we assume paths only differ at a single index, as prescribed by BIP389.
612/// Will panic if the list of paths is empty.
613fn fmt_derivation_paths(f: &mut fmt::Formatter, paths: &[bip32::DerivationPath]) -> fmt::Result {
614    for (i, child) in paths[0].into_iter().enumerate() {
615        if paths.len() > 1 && child != &paths[1][i] {
616            write!(f, "/<")?;
617            for (j, p) in paths.iter().enumerate() {
618                write!(f, "{}", p[i])?;
619                if j != paths.len() - 1 {
620                    write!(f, ";")?;
621                }
622            }
623            write!(f, ">")?;
624        } else {
625            write!(f, "/{}", child)?;
626        }
627    }
628    Ok(())
629}
630
631impl FromStr for DescriptorPublicKey {
632    type Err = DescriptorKeyParseError;
633
634    fn from_str(s: &str) -> Result<Self, Self::Err> {
635        // A "raw" public key without any origin is the least we accept.
636        if s.len() < 64 {
637            return Err(DescriptorKeyParseError::MalformedKeyData(
638                MalformedKeyDataKind::KeyTooShort,
639            ));
640        }
641
642        let (key_part, origin) = parse_key_origin(s)?;
643
644        if key_part.contains("pub") {
645            let (xpub, derivation_paths, wildcard) = parse_xkey_deriv(parse_bip32_xpub, key_part)?;
646            if derivation_paths.len() > 1 {
647                Ok(DescriptorPublicKey::MultiXPub(DescriptorMultiXKey {
648                    origin,
649                    xkey: xpub,
650                    derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
651                    wildcard,
652                }))
653            } else {
654                Ok(DescriptorPublicKey::XPub(DescriptorXKey {
655                    origin,
656                    xkey: xpub,
657                    derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
658                    wildcard,
659                }))
660            }
661        } else {
662            let key = match key_part.len() {
663                64 => {
664                    let x_only_key = XOnlyPublicKey::from_str(key_part)
665                        .map_err(DescriptorKeyParseError::XonlyPublicKey)?;
666                    SinglePubKey::XOnly(x_only_key)
667                }
668                66 | 130 => {
669                    if !(&key_part[0..2] == "02"
670                        || &key_part[0..2] == "03"
671                        || &key_part[0..2] == "04")
672                    {
673                        return Err(DescriptorKeyParseError::MalformedKeyData(
674                            MalformedKeyDataKind::InvalidFullPublicKeyPrefix,
675                        ));
676                    }
677                    let key = bitcoin::PublicKey::from_str(key_part)
678                        .map_err(DescriptorKeyParseError::FullPublicKey)?;
679                    SinglePubKey::FullKey(key)
680                }
681                _ => {
682                    return Err(DescriptorKeyParseError::MalformedKeyData(
683                        MalformedKeyDataKind::InvalidPublicKeyLength,
684                    ))
685                }
686            };
687            Ok(DescriptorPublicKey::Single(SinglePub { key, origin }))
688        }
689    }
690}
691
692impl From<XOnlyPublicKey> for DescriptorPublicKey {
693    fn from(key: XOnlyPublicKey) -> Self {
694        DescriptorPublicKey::Single(SinglePub { origin: None, key: SinglePubKey::XOnly(key) })
695    }
696}
697
698impl From<PublicKey> for DescriptorPublicKey {
699    fn from(key: PublicKey) -> Self {
700        DescriptorPublicKey::Single(SinglePub { origin: None, key: SinglePubKey::FullKey(key) })
701    }
702}
703
704impl DescriptorPublicKey {
705    /// The fingerprint of the master key associated with this key, `0x00000000` if none.
706    pub fn master_fingerprint(&self) -> bip32::Fingerprint {
707        match *self {
708            DescriptorPublicKey::XPub(ref xpub) => {
709                if let Some((fingerprint, _)) = xpub.origin {
710                    fingerprint
711                } else {
712                    xpub.xkey.fingerprint()
713                }
714            }
715            DescriptorPublicKey::MultiXPub(ref xpub) => {
716                if let Some((fingerprint, _)) = xpub.origin {
717                    fingerprint
718                } else {
719                    xpub.xkey.fingerprint()
720                }
721            }
722            DescriptorPublicKey::Single(ref single) => {
723                if let Some((fingerprint, _)) = single.origin {
724                    fingerprint
725                } else {
726                    let mut engine = XKeyIdentifier::engine();
727                    match single.key {
728                        SinglePubKey::FullKey(pk) => {
729                            pk.write_into(&mut engine).expect("engines don't error")
730                        }
731                        SinglePubKey::XOnly(x_only_pk) => engine.input(&x_only_pk.serialize()),
732                    };
733                    bip32::Fingerprint::from(
734                        &XKeyIdentifier::from_engine(engine)[..4]
735                            .try_into()
736                            .expect("4 byte slice"),
737                    )
738                }
739            }
740        }
741    }
742
743    /// Full path, from the master key
744    ///
745    /// For wildcard keys this will return the path up to the wildcard, so you
746    /// can get full paths by appending one additional derivation step, according
747    /// to the wildcard type (hardened or normal).
748    ///
749    /// For multipath extended keys, this returns `None`.
750    pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
751        match *self {
752            DescriptorPublicKey::XPub(ref xpub) => {
753                let origin_path = if let Some((_, ref path)) = xpub.origin {
754                    path.clone()
755                } else {
756                    bip32::DerivationPath::from(vec![])
757                };
758                Some(origin_path.extend(&xpub.derivation_path))
759            }
760            DescriptorPublicKey::Single(ref single) => {
761                Some(if let Some((_, ref path)) = single.origin {
762                    path.clone()
763                } else {
764                    bip32::DerivationPath::from(vec![])
765                })
766            }
767            DescriptorPublicKey::MultiXPub(_) => None,
768        }
769    }
770
771    /// Returns a vector containing the full derivation paths from the master key.
772    /// The vector will contain just one element for single keys, and multiple elements
773    /// for multipath extended keys.
774    ///
775    /// For wildcard keys this will return the path up to the wildcard, so you
776    /// can get full paths by appending one additional derivation step, according
777    /// to the wildcard type (hardened or normal).
778    pub fn full_derivation_paths(&self) -> Vec<bip32::DerivationPath> {
779        match self {
780            DescriptorPublicKey::MultiXPub(xpub) => {
781                let origin_path = if let Some((_, ref path)) = xpub.origin {
782                    path.clone()
783                } else {
784                    bip32::DerivationPath::from(vec![])
785                };
786                xpub.derivation_paths
787                    .paths()
788                    .iter()
789                    .map(|p| origin_path.extend(p))
790                    .collect()
791            }
792            _ => vec![self
793                .full_derivation_path()
794                .expect("Must be Some for non-multipath keys")],
795        }
796    }
797
798    /// Whether or not the key has a wildcard
799    pub fn has_wildcard(&self) -> bool {
800        match *self {
801            DescriptorPublicKey::Single(..) => false,
802            DescriptorPublicKey::XPub(ref xpub) => xpub.wildcard != Wildcard::None,
803            DescriptorPublicKey::MultiXPub(ref xpub) => xpub.wildcard != Wildcard::None,
804        }
805    }
806
807    /// Whether or not the key has a wildcard
808    pub fn has_hardened_step(&self) -> bool {
809        let paths = match self {
810            DescriptorPublicKey::Single(..) => &[],
811            DescriptorPublicKey::XPub(xpub) => core::slice::from_ref(&xpub.derivation_path),
812            DescriptorPublicKey::MultiXPub(xpub) => &xpub.derivation_paths.paths()[..],
813        };
814        for p in paths {
815            for step in p.into_iter() {
816                if step.is_hardened() {
817                    return true;
818                }
819            }
820        }
821        false
822    }
823
824    /// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
825    /// *definite* key (i.e. one where all the derivation paths are set).
826    ///
827    /// # Returns
828    ///
829    /// - If this key is not an xpub, returns `self`.
830    /// - If this key is an xpub but does not have a wildcard, returns `self`.
831    /// - Otherwise, returns the xpub at derivation `index` (removing the wildcard).
832    ///
833    /// # Errors
834    ///
835    /// - If `index` is hardened.
836    /// - If the key contains multi-path derivations
837    pub fn at_derivation_index(
838        self,
839        index: u32,
840    ) -> Result<DefiniteDescriptorKey, NonDefiniteKeyError> {
841        let definite = match self {
842            DescriptorPublicKey::Single(_) => self,
843            DescriptorPublicKey::XPub(xpub) => {
844                let derivation_path = match xpub.wildcard {
845                    Wildcard::None => xpub.derivation_path,
846                    Wildcard::Unhardened => xpub.derivation_path.into_child(
847                        bip32::ChildNumber::from_normal_idx(index)
848                            .ok()
849                            .ok_or(NonDefiniteKeyError::HardenedStep)?,
850                    ),
851                    Wildcard::Hardened => xpub.derivation_path.into_child(
852                        bip32::ChildNumber::from_hardened_idx(index)
853                            .ok()
854                            .ok_or(NonDefiniteKeyError::HardenedStep)?,
855                    ),
856                };
857                DescriptorPublicKey::XPub(DescriptorXKey {
858                    origin: xpub.origin,
859                    xkey: xpub.xkey,
860                    derivation_path,
861                    wildcard: Wildcard::None,
862                })
863            }
864            DescriptorPublicKey::MultiXPub(_) => return Err(NonDefiniteKeyError::Multipath),
865        };
866
867        Ok(DefiniteDescriptorKey::new(definite)
868            .expect("The key should not contain any wildcards at this point"))
869    }
870
871    /// Whether or not this key has multiple derivation paths.
872    pub fn is_multipath(&self) -> bool {
873        match *self {
874            DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => false,
875            DescriptorPublicKey::MultiXPub(_) => true,
876        }
877    }
878
879    /// Get as many keys as derivation paths in this key.
880    ///
881    /// For raw public key and single-path extended keys it will return the key itself.
882    /// For multipath extended keys it will return a single-path extended key per derivation
883    /// path.
884    pub fn into_single_keys(self) -> Vec<DescriptorPublicKey> {
885        match self {
886            DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => vec![self],
887            DescriptorPublicKey::MultiXPub(xpub) => {
888                let DescriptorMultiXKey { origin, xkey, derivation_paths, wildcard } = xpub;
889                derivation_paths
890                    .into_paths()
891                    .into_iter()
892                    .map(|derivation_path| {
893                        DescriptorPublicKey::XPub(DescriptorXKey {
894                            origin: origin.clone(),
895                            xkey,
896                            derivation_path,
897                            wildcard,
898                        })
899                    })
900                    .collect()
901            }
902        }
903    }
904
905    /// Get the network of this key, if it's an extended key.
906    ///
907    /// Returns `None` for single keys (non-extended keys), `Some(NetworkKind)` for extended keys.
908    pub fn xkey_network(&self) -> Option<NetworkKind> {
909        match self {
910            DescriptorPublicKey::Single(_) => None,
911            DescriptorPublicKey::XPub(xpub) => Some(xpub.xkey.network),
912            DescriptorPublicKey::MultiXPub(multi_xpub) => Some(multi_xpub.xkey.network),
913        }
914    }
915}
916
917impl FromStr for DescriptorSecretKey {
918    type Err = DescriptorKeyParseError;
919
920    fn from_str(s: &str) -> Result<Self, Self::Err> {
921        let (key_part, origin) = parse_key_origin(s)?;
922
923        if key_part.len() <= 52 {
924            let sk = bitcoin::PrivateKey::from_str(key_part)
925                .map_err(DescriptorKeyParseError::WifPrivateKey)?;
926            Ok(DescriptorSecretKey::Single(SinglePriv { key: sk, origin }))
927        } else {
928            let (xpriv, derivation_paths, wildcard) =
929                parse_xkey_deriv(parse_bip32_xpriv, key_part)?;
930            if derivation_paths.len() > 1 {
931                Ok(DescriptorSecretKey::MultiXPrv(DescriptorMultiXKey {
932                    origin,
933                    xkey: xpriv,
934                    derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
935                    wildcard,
936                }))
937            } else {
938                Ok(DescriptorSecretKey::XPrv(DescriptorXKey {
939                    origin,
940                    xkey: xpriv,
941                    derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
942                    wildcard,
943                }))
944            }
945        }
946    }
947}
948
949// Parse the origin information part of a descriptor key.
950fn parse_key_origin(s: &str) -> Result<(&str, Option<bip32::KeySource>), DescriptorKeyParseError> {
951    for ch in s.as_bytes() {
952        if *ch < 20 || *ch > 127 {
953            return Err(DescriptorKeyParseError::MalformedKeyData(
954                MalformedKeyDataKind::EncounteredUnprintableCharacter,
955            ));
956        }
957    }
958
959    if s.is_empty() {
960        return Err(DescriptorKeyParseError::MalformedKeyData(MalformedKeyDataKind::EmptyKey));
961    }
962    let mut parts = s[1..].split(']');
963
964    if let Some('[') = s.chars().next() {
965        let mut raw_origin = parts
966            .next()
967            .ok_or(DescriptorKeyParseError::MalformedKeyData(
968                MalformedKeyDataKind::UnclosedSquareBracket,
969            ))?
970            .split('/');
971
972        let origin_id_hex = raw_origin
973            .next()
974            .ok_or(DescriptorKeyParseError::MalformedKeyData(
975                MalformedKeyDataKind::NoMasterFingerprintFound,
976            ))?;
977
978        if origin_id_hex.len() != 8 {
979            return Err(DescriptorKeyParseError::MalformedKeyData(
980                MalformedKeyDataKind::InvalidMasterFingerprintLength,
981            ));
982        }
983        let parent_fingerprint = bip32::Fingerprint::from_hex(origin_id_hex).map_err(|err| {
984            DescriptorKeyParseError::MasterFingerprint {
985                fingerprint: origin_id_hex.to_owned(),
986                err,
987            }
988        })?;
989        let origin_path = raw_origin
990            .map(bip32::ChildNumber::from_str)
991            .collect::<Result<bip32::DerivationPath, bip32::Error>>()
992            .map_err(DescriptorKeyParseError::MasterDerivationPath)?;
993
994        let key = parts
995            .next()
996            .ok_or(DescriptorKeyParseError::MalformedKeyData(
997                MalformedKeyDataKind::NoKeyAfterOrigin,
998            ))?;
999
1000        if parts.next().is_some() {
1001            Err(DescriptorKeyParseError::MalformedKeyData(
1002                MalformedKeyDataKind::MultipleFingerprintsInPublicKey,
1003            ))
1004        } else {
1005            Ok((key, Some((parent_fingerprint, origin_path))))
1006        }
1007    } else {
1008        Ok((s, None))
1009    }
1010}
1011
1012fn parse_bip32_xpub(xkey_str: &str) -> Result<bip32::Xpub, DescriptorKeyParseError> {
1013    bip32::Xpub::from_str(xkey_str).map_err(DescriptorKeyParseError::Bip32Xpub)
1014}
1015
1016fn parse_bip32_xpriv(xkey_str: &str) -> Result<bip32::Xpriv, DescriptorKeyParseError> {
1017    bip32::Xpriv::from_str(xkey_str).map_err(DescriptorKeyParseError::Bip32Xpriv)
1018}
1019
1020fn parse_xkey_deriv<Key>(
1021    parse_xkey_fn: impl Fn(&str) -> Result<Key, DescriptorKeyParseError>,
1022    key_deriv: &str,
1023) -> Result<(Key, Vec<bip32::DerivationPath>, Wildcard), DescriptorKeyParseError> {
1024    let mut key_deriv = key_deriv.split('/');
1025    let xkey_str = key_deriv
1026        .next()
1027        .ok_or(DescriptorKeyParseError::MalformedKeyData(
1028            MalformedKeyDataKind::NoKeyAfterOrigin,
1029        ))?;
1030
1031    let xkey = parse_xkey_fn(xkey_str)?;
1032
1033    let mut wildcard = Wildcard::None;
1034    let mut multipath = false;
1035    let derivation_paths = key_deriv
1036        .filter_map(|p| {
1037            if wildcard == Wildcard::None && p == "*" {
1038                wildcard = Wildcard::Unhardened;
1039                None
1040            } else if wildcard == Wildcard::None && (p == "*'" || p == "*h") {
1041                wildcard = Wildcard::Hardened;
1042                None
1043            } else if wildcard != Wildcard::None {
1044                Some(Err(DescriptorKeyParseError::MalformedKeyData(
1045                    MalformedKeyDataKind::InvalidWildcardInDerivationPath,
1046                )))
1047            } else {
1048                // BIP389 defines a new step in the derivation path. This step contains two or more
1049                // derivation indexes in the form '<1;2;3';4h;5H;6>'.
1050                if p.starts_with('<') && p.ends_with('>') {
1051                    // There may only be one occurrence of this step.
1052                    if multipath {
1053                        return Some(Err(DescriptorKeyParseError::MalformedKeyData(
1054                            MalformedKeyDataKind::MultipleDerivationPathIndexSteps,
1055                        )));
1056                    }
1057                    multipath = true;
1058
1059                    // The step must contain at least two derivation indexes.
1060                    // So it's at least '<' + a number + ';' + a number + '>'.
1061                    if p.len() < 5 || !p.contains(';') {
1062                        return Some(Err(DescriptorKeyParseError::MalformedKeyData(
1063                            MalformedKeyDataKind::InvalidMultiIndexStep,
1064                        )));
1065                    }
1066
1067                    // Collect all derivation indexes at this step.
1068                    let indexes = p[1..p.len() - 1].split(';');
1069                    Some(
1070                        indexes
1071                            .into_iter()
1072                            .map(|s| {
1073                                bip32::ChildNumber::from_str(s).map_err(|err| {
1074                                    DescriptorKeyParseError::DerivationIndexError {
1075                                        index: s.to_owned(),
1076                                        err,
1077                                    }
1078                                })
1079                            })
1080                            .collect::<Result<Vec<bip32::ChildNumber>, _>>(),
1081                    )
1082                } else {
1083                    // Not a BIP389 step, just a regular derivation index.
1084                    Some(
1085                        bip32::ChildNumber::from_str(p)
1086                            .map(|i| vec![i])
1087                            .map_err(|err| DescriptorKeyParseError::DerivationIndexError {
1088                                index: p.to_owned(),
1089                                err,
1090                            }),
1091                    )
1092                }
1093            }
1094        })
1095        // Now we've got all derivation indexes in a list of vectors of indexes. If the derivation
1096        // path was empty then this list is empty. If the derivation path didn't contain any BIP389
1097        // step all the vectors of indexes contain a single element. If it did though, one of the
1098        // vectors contains more than one element.
1099        // Now transform this list of vectors of steps into distinct derivation paths.
1100        .try_fold(Vec::new(), |mut paths, index_list| {
1101            let mut index_list = index_list?.into_iter();
1102            let first_index = index_list
1103                .next()
1104                .expect("There is always at least one element");
1105
1106            if paths.is_empty() {
1107                paths.push(vec![first_index]);
1108            } else {
1109                for path in paths.iter_mut() {
1110                    path.push(first_index);
1111                }
1112            }
1113
1114            // If the step is a BIP389 one, create as many paths as there is indexes.
1115            for (i, index) in index_list.enumerate() {
1116                paths.push(paths[0].clone());
1117                *paths[i + 1].last_mut().expect("Never empty") = index;
1118            }
1119
1120            Ok(paths)
1121        })?
1122        .into_iter()
1123        .map(|index_list| index_list.into_iter().collect::<bip32::DerivationPath>())
1124        .collect::<Vec<bip32::DerivationPath>>();
1125
1126    Ok((xkey, derivation_paths, wildcard))
1127}
1128
1129impl<K: InnerXKey> DescriptorXKey<K> {
1130    /// Compares this key with a `keysource` and returns the matching derivation path, if any.
1131    ///
1132    /// For keys that have an origin, the `keysource`'s fingerprint will be compared
1133    /// with the origin's fingerprint, and the `keysource`'s path will be compared with the concatenation of the
1134    /// origin's and key's paths.
1135    ///
1136    /// If the key `wildcard`, the last item of the `keysource`'s path will be ignored,
1137    ///
1138    /// ## Examples
1139    ///
1140    /// ```
1141    /// # use std::str::FromStr;
1142    /// # fn body() -> Result<(), ()> {
1143    /// use miniscript::bitcoin::bip32;
1144    /// use miniscript::descriptor::DescriptorPublicKey;
1145    ///
1146    /// let ctx = miniscript::bitcoin::secp256k1::Secp256k1::signing_only();
1147    ///
1148    /// let key = DescriptorPublicKey::from_str("[d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*").or(Err(()))?;
1149    /// let xpub = match key {
1150    ///     DescriptorPublicKey::XPub(xpub) => xpub,
1151    ///     _ => panic!("Parsing Error"),
1152    /// };
1153    ///
1154    /// assert_eq!(
1155    ///     xpub.matches(&(
1156    ///         bip32::Fingerprint::from_str("d34db33f").or(Err(()))?,
1157    ///         bip32::DerivationPath::from_str("m/44'/0'/0'/1/42").or(Err(()))?
1158    ///     ), &ctx),
1159    ///     Some(bip32::DerivationPath::from_str("m/44'/0'/0'/1").or(Err(()))?)
1160    /// );
1161    /// assert_eq!(
1162    ///     xpub.matches(&(
1163    ///         bip32::Fingerprint::from_str("ffffffff").or(Err(()))?,
1164    ///         bip32::DerivationPath::from_str("m/44'/0'/0'/1/42").or(Err(()))?
1165    ///     ), &ctx),
1166    ///     None
1167    /// );
1168    /// assert_eq!(
1169    ///     xpub.matches(&(
1170    ///         bip32::Fingerprint::from_str("d34db33f").or(Err(()))?,
1171    ///         bip32::DerivationPath::from_str("m/44'/0'/0'/100/0").or(Err(()))?
1172    ///     ), &ctx),
1173    ///     None
1174    /// );
1175    /// # Ok(())
1176    /// # }
1177    /// # body().unwrap()
1178    /// ```
1179    pub fn matches<C: Signing>(
1180        &self,
1181        keysource: &bip32::KeySource,
1182        secp: &Secp256k1<C>,
1183    ) -> Option<bip32::DerivationPath> {
1184        let (fingerprint, path) = keysource;
1185
1186        let (compare_fingerprint, compare_path) = match self.origin {
1187            Some((fingerprint, ref path)) => {
1188                (fingerprint, path.into_iter().chain(&self.derivation_path).collect())
1189            }
1190            None => (
1191                self.xkey.xkey_fingerprint(secp),
1192                self.derivation_path.into_iter().collect::<Vec<_>>(),
1193            ),
1194        };
1195
1196        let path_excluding_wildcard = if self.wildcard != Wildcard::None && !path.is_empty() {
1197            path.into_iter()
1198                .take(path.as_ref().len() - 1)
1199                .cloned()
1200                .collect()
1201        } else {
1202            path.clone()
1203        };
1204
1205        if &compare_fingerprint == fingerprint
1206            && compare_path.into_iter().eq(&path_excluding_wildcard)
1207        {
1208            Some(path_excluding_wildcard)
1209        } else {
1210            None
1211        }
1212    }
1213}
1214
1215impl MiniscriptKey for DescriptorPublicKey {
1216    type Sha256 = sha256::Hash;
1217    type Hash256 = hash256::Hash;
1218    type Ripemd160 = ripemd160::Hash;
1219    type Hash160 = hash160::Hash;
1220
1221    fn is_uncompressed(&self) -> bool {
1222        match self {
1223            DescriptorPublicKey::Single(SinglePub {
1224                key: SinglePubKey::FullKey(ref key), ..
1225            }) => key.is_uncompressed(),
1226            _ => false,
1227        }
1228    }
1229
1230    fn is_x_only_key(&self) -> bool {
1231        matches!(
1232            self,
1233            DescriptorPublicKey::Single(SinglePub { key: SinglePubKey::XOnly(ref _key), .. })
1234        )
1235    }
1236
1237    fn num_der_paths(&self) -> usize {
1238        match self {
1239            DescriptorPublicKey::Single(_) => 0,
1240            DescriptorPublicKey::XPub(_) => 1,
1241            DescriptorPublicKey::MultiXPub(xpub) => xpub.derivation_paths.paths().len(),
1242        }
1243    }
1244}
1245
1246impl DefiniteDescriptorKey {
1247    /// Computes the public key corresponding to this descriptor key.
1248    /// When deriving from an XOnlyPublicKey, it adds the default 0x02 y-coordinate
1249    /// and returns the obtained full [`bitcoin::PublicKey`]. All BIP32 derivations
1250    /// always return a compressed key
1251    ///
1252    /// Will return an error if the descriptor key has any hardened derivation steps in its path. To
1253    /// avoid this error you should replace any such public keys first with [`crate::Descriptor::translate_pk`].
1254    pub fn derive_public_key<C: Verification>(&self, secp: &Secp256k1<C>) -> bitcoin::PublicKey {
1255        match self.0 {
1256            DescriptorPublicKey::Single(ref pk) => match pk.key {
1257                SinglePubKey::FullKey(pk) => pk,
1258                SinglePubKey::XOnly(xpk) => xpk.to_public_key(),
1259            },
1260            DescriptorPublicKey::XPub(ref xpk) => match xpk.wildcard {
1261                Wildcard::Unhardened | Wildcard::Hardened => {
1262                    unreachable!("impossible by construction of DefiniteDescriptorKey")
1263                }
1264                Wildcard::None => match xpk.xkey.derive_pub(secp, &xpk.derivation_path.as_ref()) {
1265                    Ok(xpub) => bitcoin::PublicKey::new(xpub.public_key),
1266                    Err(bip32::Error::CannotDeriveFromHardenedKey) => {
1267                        unreachable!("impossible by construction of DefiniteDescriptorKey")
1268                    }
1269                    Err(e) => unreachable!("cryptographically unreachable: {}", e),
1270                },
1271            },
1272            DescriptorPublicKey::MultiXPub(_) => {
1273                unreachable!("impossible by construction of DefiniteDescriptorKey")
1274            }
1275        }
1276    }
1277
1278    /// Construct an instance from a descriptor key and a derivation index
1279    ///
1280    /// Returns `None` if the key contains a wildcard
1281    pub fn new(key: DescriptorPublicKey) -> Result<Self, NonDefiniteKeyError> {
1282        if key.has_wildcard() {
1283            Err(NonDefiniteKeyError::Wildcard)
1284        } else if key.has_hardened_step() {
1285            Err(NonDefiniteKeyError::HardenedStep)
1286        } else if key.is_multipath() {
1287            Err(NonDefiniteKeyError::Multipath)
1288        } else {
1289            Ok(Self(key))
1290        }
1291    }
1292
1293    /// The fingerprint of the master key associated with this key, `0x00000000` if none.
1294    pub fn master_fingerprint(&self) -> bip32::Fingerprint { self.0.master_fingerprint() }
1295
1296    /// Full path from the master key if not a multipath extended key.
1297    pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
1298        self.0.full_derivation_path()
1299    }
1300
1301    /// Full paths from the master key. The vector will contain just one path for single
1302    /// keys, and multiple ones for multipath extended keys
1303    pub fn full_derivation_paths(&self) -> Vec<bip32::DerivationPath> {
1304        self.0.full_derivation_paths()
1305    }
1306
1307    /// Reference to the underlying `DescriptorPublicKey`
1308    pub fn as_descriptor_public_key(&self) -> &DescriptorPublicKey { &self.0 }
1309
1310    /// Converts the definite key into a generic one
1311    pub fn into_descriptor_public_key(self) -> DescriptorPublicKey { self.0 }
1312}
1313
1314impl FromStr for DefiniteDescriptorKey {
1315    type Err = DescriptorKeyParseError;
1316
1317    fn from_str(s: &str) -> Result<Self, Self::Err> {
1318        let d = DescriptorPublicKey::from_str(s)?;
1319        DefiniteDescriptorKey::new(d).map_err(DescriptorKeyParseError::NonDefiniteKey)
1320    }
1321}
1322
1323impl fmt::Display for DefiniteDescriptorKey {
1324    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) }
1325}
1326
1327impl MiniscriptKey for DefiniteDescriptorKey {
1328    type Sha256 = sha256::Hash;
1329    type Hash256 = hash256::Hash;
1330    type Ripemd160 = ripemd160::Hash;
1331    type Hash160 = hash160::Hash;
1332
1333    fn is_uncompressed(&self) -> bool { self.0.is_uncompressed() }
1334
1335    fn is_x_only_key(&self) -> bool { self.0.is_x_only_key() }
1336
1337    fn num_der_paths(&self) -> usize { self.0.num_der_paths() }
1338}
1339
1340impl ToPublicKey for DefiniteDescriptorKey {
1341    fn to_public_key(&self) -> bitcoin::PublicKey {
1342        let secp = Secp256k1::verification_only();
1343        self.derive_public_key(&secp)
1344    }
1345
1346    fn to_sha256(hash: &sha256::Hash) -> sha256::Hash { *hash }
1347
1348    fn to_hash256(hash: &hash256::Hash) -> hash256::Hash { *hash }
1349
1350    fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash { *hash }
1351
1352    fn to_hash160(hash: &hash160::Hash) -> hash160::Hash { *hash }
1353}
1354
1355impl From<DefiniteDescriptorKey> for DescriptorPublicKey {
1356    fn from(d: DefiniteDescriptorKey) -> Self { d.0 }
1357}
1358
1359impl Borrow<DescriptorPublicKey> for DefiniteDescriptorKey {
1360    fn borrow(&self) -> &DescriptorPublicKey { &self.0 }
1361}
1362
1363#[cfg(feature = "serde")]
1364impl<'de> Deserialize<'de> for DescriptorPublicKey {
1365    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1366    where
1367        D: Deserializer<'de>,
1368    {
1369        let s = String::deserialize(deserializer)?;
1370        DescriptorPublicKey::from_str(&s).map_err(crate::serde::de::Error::custom)
1371    }
1372}
1373
1374#[cfg(feature = "serde")]
1375impl Serialize for DescriptorPublicKey {
1376    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1377    where
1378        S: Serializer,
1379    {
1380        serializer.serialize_str(&self.to_string())
1381    }
1382}
1383
1384#[cfg(test)]
1385mod test {
1386    use core::str::FromStr;
1387
1388    use bitcoin::bip32;
1389    #[cfg(feature = "serde")]
1390    use serde_test::{assert_tokens, Token};
1391
1392    use super::{
1393        DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey, MiniscriptKey, Wildcard,
1394    };
1395    use crate::descriptor::key::NonDefiniteKeyError;
1396    use crate::prelude::*;
1397    use crate::DefiniteDescriptorKey;
1398
1399    #[test]
1400    fn parse_descriptor_key_errors() {
1401        // And ones with misplaced wildcard
1402        let desc = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*/44";
1403        assert_eq!(
1404            DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1405            "\'*\' may only appear as last element in a derivation path"
1406        );
1407
1408        // And ones with invalid fingerprints
1409        let desc = "[NonHexor]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*";
1410        assert_eq!(
1411            DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1412            "on master fingerprint 'NonHexor': failed to parse hex digit"
1413        );
1414
1415        // And ones with invalid xpubs..
1416        let desc = "[78412e3a]xpub1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaLcgJvLJuZZvRcEL/1/*";
1417        assert_eq!(
1418            DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1419            "base58 encoding error"
1420        );
1421
1422        // ..or invalid raw keys
1423        let desc = "[78412e3a]0208a117f3897c3a13c9384b8695eed98dc31bc2500feb19a1af424cd47a5d83/1/*";
1424        assert_eq!(
1425            DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1426            "public keys must be 64, 66 or 130 characters in size",
1427        );
1428
1429        // ..or invalid separators
1430        let desc = "[78412e3a]]03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8";
1431        assert_eq!(
1432            DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1433            "multiple \']\' in Descriptor Public Key"
1434        );
1435
1436        // fuzzer errors
1437        let desc = "[11111f11]033333333333333333333333333333323333333333333333333333333433333333]]333]]3]]101333333333333433333]]]10]333333mmmm";
1438        assert_eq!(
1439            DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1440            "multiple \']\' in Descriptor Public Key"
1441        );
1442
1443        // fuzz failure, hybrid keys
1444        let desc = "0777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777";
1445        assert_eq!(
1446            DescriptorPublicKey::from_str(desc).unwrap_err().to_string(),
1447            "only full public keys with prefixes '02', '03' or '04' are allowed"
1448        );
1449    }
1450
1451    #[test]
1452    fn parse_descriptor_secret_key_error() {
1453        // Xpubs are invalid
1454        let secret_key = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
1455        assert_eq!(
1456            DescriptorSecretKey::from_str(secret_key)
1457                .unwrap_err()
1458                .to_string(),
1459            "unknown version magic bytes: [4, 136, 178, 30]"
1460        );
1461
1462        // And ones with invalid fingerprints
1463        let desc = "[NonHexor]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/*";
1464        assert_eq!(
1465            DescriptorSecretKey::from_str(desc).unwrap_err().to_string(),
1466            "on master fingerprint 'NonHexor': failed to parse hex digit"
1467        );
1468
1469        // ..or invalid raw keys
1470        let desc = "[78412e3a]L32jTfVLei6BYTPUpwpJSkrHx8iL9GZzeErVS8y4Y/1/*";
1471        assert_eq!(DescriptorSecretKey::from_str(desc).unwrap_err().to_string(), "invalid base58");
1472    }
1473
1474    #[test]
1475    fn test_wildcard() {
1476        let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2").unwrap();
1477        assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1478        assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'/2");
1479        assert!(!public_key.has_wildcard());
1480
1481        let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*").unwrap();
1482        assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1483        assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'");
1484        assert!(public_key.has_wildcard());
1485
1486        let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*h").unwrap();
1487        assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
1488        assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'");
1489        assert!(public_key.has_wildcard());
1490    }
1491
1492    #[test]
1493    fn test_deriv_on_xprv() {
1494        let secp = secp256k1::Secp256k1::signing_only();
1495
1496        let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2").unwrap();
1497        let public_key = secret_key.to_public(&secp).unwrap();
1498        assert_eq!(public_key.to_string(), "[2cbe2a6d/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2");
1499        assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1500        assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'/2");
1501        assert!(!public_key.has_wildcard());
1502
1503        let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2'").unwrap();
1504        let public_key = secret_key.to_public(&secp).unwrap();
1505        assert_eq!(public_key.to_string(), "[2cbe2a6d/0'/1'/2']tpubDDPuH46rv4dbFtmF6FrEtJEy1CvLZonyBoVxF6xsesHdYDdTBrq2mHhm8AbsPh39sUwL2nZyxd6vo4uWNTU9v4t893CwxjqPnwMoUACLvMV");
1506        assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1507        assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0'/1'/2'");
1508
1509        let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0/1/2").unwrap();
1510        let public_key = secret_key.to_public(&secp).unwrap();
1511        assert_eq!(public_key.to_string(), "tpubD6NzVbkrYhZ4WQdzxL7NmJN7b85ePo4p6RSj9QQHF7te2RR9iUeVSGgnGkoUsB9LBRosgvNbjRv9bcsJgzgBd7QKuxDm23ZewkTRzNSLEDr/0/1/2");
1512        assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
1513        assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0/1/2");
1514
1515        let secret_key = DescriptorSecretKey::from_str("[aabbccdd]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0/1/2").unwrap();
1516        let public_key = secret_key.to_public(&secp).unwrap();
1517        assert_eq!(public_key.to_string(), "[aabbccdd]tpubD6NzVbkrYhZ4WQdzxL7NmJN7b85ePo4p6RSj9QQHF7te2RR9iUeVSGgnGkoUsB9LBRosgvNbjRv9bcsJgzgBd7QKuxDm23ZewkTRzNSLEDr/0/1/2");
1518        assert_eq!(public_key.master_fingerprint().to_string(), "aabbccdd");
1519        assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "0/1/2");
1520
1521        let secret_key = DescriptorSecretKey::from_str("[aabbccdd/90']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2").unwrap();
1522        let public_key = secret_key.to_public(&secp).unwrap();
1523        assert_eq!(public_key.to_string(), "[aabbccdd/90'/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2");
1524        assert_eq!(public_key.master_fingerprint().to_string(), "aabbccdd");
1525        assert_eq!(public_key.full_derivation_path().unwrap().to_string(), "90'/0'/1'/2");
1526    }
1527
1528    #[test]
1529    fn test_master_fingerprint() {
1530        assert_eq!(
1531            DescriptorPublicKey::from_str(
1532                "02a489e0ea42b56148d212d325b7c67c6460483ff931c303ea311edfef667c8f35",
1533            )
1534            .unwrap()
1535            .master_fingerprint()
1536            .as_bytes(),
1537            b"\xb0\x59\x11\x6a"
1538        );
1539    }
1540
1541    fn get_multipath_xpub(key_str: &str, num_paths: usize) -> DescriptorMultiXKey<bip32::Xpub> {
1542        let desc_key = DescriptorPublicKey::from_str(key_str).unwrap();
1543        assert_eq!(desc_key.num_der_paths(), num_paths);
1544        match desc_key {
1545            DescriptorPublicKey::MultiXPub(xpub) => xpub,
1546            _ => unreachable!(),
1547        }
1548    }
1549
1550    fn get_multipath_xprv(key_str: &str) -> DescriptorMultiXKey<bip32::Xpriv> {
1551        let desc_key = DescriptorSecretKey::from_str(key_str).unwrap();
1552        match desc_key {
1553            DescriptorSecretKey::MultiXPrv(xprv) => xprv,
1554            _ => unreachable!(),
1555        }
1556    }
1557
1558    #[test]
1559    fn multipath_extended_keys() {
1560        let secp = secp256k1::Secp256k1::signing_only();
1561
1562        // We can have a key in a descriptor that has multiple paths
1563        let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;42;9854>", 4);
1564        assert_eq!(
1565            xpub.derivation_paths.paths(),
1566            &vec![
1567                bip32::DerivationPath::from_str("m/2/0").unwrap(),
1568                bip32::DerivationPath::from_str("m/2/1").unwrap(),
1569                bip32::DerivationPath::from_str("m/2/42").unwrap(),
1570                bip32::DerivationPath::from_str("m/2/9854").unwrap()
1571            ],
1572        );
1573        assert_eq!(
1574            xpub,
1575            get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 4)
1576        );
1577        // Even if it's in the middle of the derivation path.
1578        let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;9854>/0/5/10", 3);
1579        assert_eq!(
1580            xpub.derivation_paths.paths(),
1581            &vec![
1582                bip32::DerivationPath::from_str("m/2/0/0/5/10").unwrap(),
1583                bip32::DerivationPath::from_str("m/2/1/0/5/10").unwrap(),
1584                bip32::DerivationPath::from_str("m/2/9854/0/5/10").unwrap()
1585            ],
1586        );
1587        assert_eq!(
1588            xpub,
1589            get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 3)
1590        );
1591        // Even if it is a wildcard extended key.
1592        let xpub = get_multipath_xpub("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;9854>/3456/9876/*", 3);
1593        assert_eq!(xpub.wildcard, Wildcard::Unhardened);
1594        assert_eq!(
1595            xpub.derivation_paths.paths(),
1596            &vec![
1597                bip32::DerivationPath::from_str("m/2/0/3456/9876").unwrap(),
1598                bip32::DerivationPath::from_str("m/2/1/3456/9876").unwrap(),
1599                bip32::DerivationPath::from_str("m/2/9854/3456/9876").unwrap()
1600            ],
1601        );
1602        assert_eq!(
1603            xpub,
1604            get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 3)
1605        );
1606        // Also even if it has an origin.
1607        let xpub = get_multipath_xpub("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/<0;1>/*", 2);
1608        assert_eq!(xpub.wildcard, Wildcard::Unhardened);
1609        assert_eq!(
1610            xpub.derivation_paths.paths(),
1611            &vec![
1612                bip32::DerivationPath::from_str("m/0").unwrap(),
1613                bip32::DerivationPath::from_str("m/1").unwrap(),
1614            ],
1615        );
1616        assert_eq!(
1617            xpub,
1618            get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 2)
1619        );
1620        // Also if it has hardened steps in the derivation path. In fact, it can also have hardened
1621        // indexes even at the step with multiple indexes!
1622        let xpub = get_multipath_xpub("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1h>/8h/*'", 2);
1623        assert_eq!(xpub.wildcard, Wildcard::Hardened);
1624        assert_eq!(
1625            xpub.derivation_paths.paths(),
1626            &vec![
1627                bip32::DerivationPath::from_str("m/9478'/0'/8'").unwrap(),
1628                bip32::DerivationPath::from_str("m/9478h/1h/8h").unwrap(),
1629            ],
1630        );
1631        assert_eq!(
1632            xpub,
1633            get_multipath_xpub(&DescriptorPublicKey::MultiXPub(xpub.clone()).to_string(), 2)
1634        );
1635        // You can't get the "full derivation path" for a multipath extended public key.
1636        let desc_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1>/8h/*'").unwrap();
1637        assert!(desc_key.full_derivation_path().is_none());
1638        assert!(desc_key.is_multipath());
1639        // But you can get all the derivation paths
1640        assert_eq!(
1641            desc_key.full_derivation_paths(),
1642            vec![
1643                bip32::DerivationPath::from_str("m/0'/1'/9478'/0'/8'").unwrap(),
1644                bip32::DerivationPath::from_str("m/0'/1'/9478'/1/8'").unwrap(),
1645            ],
1646        );
1647        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()]);
1648
1649        // All the same but with extended private keys instead of xpubs.
1650        let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;42;9854>");
1651        assert_eq!(
1652            xprv.derivation_paths.paths(),
1653            &vec![
1654                bip32::DerivationPath::from_str("m/2/0").unwrap(),
1655                bip32::DerivationPath::from_str("m/2/1").unwrap(),
1656                bip32::DerivationPath::from_str("m/2/42").unwrap(),
1657                bip32::DerivationPath::from_str("m/2/9854").unwrap()
1658            ],
1659        );
1660        assert_eq!(
1661            xprv,
1662            get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1663        );
1664        let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;9854>/0/5/10");
1665        assert_eq!(
1666            xprv.derivation_paths.paths(),
1667            &vec![
1668                bip32::DerivationPath::from_str("m/2/0/0/5/10").unwrap(),
1669                bip32::DerivationPath::from_str("m/2/1/0/5/10").unwrap(),
1670                bip32::DerivationPath::from_str("m/2/9854/0/5/10").unwrap()
1671            ],
1672        );
1673        assert_eq!(
1674            xprv,
1675            get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1676        );
1677        let xprv = get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;9854>/3456/9876/*");
1678        assert_eq!(xprv.wildcard, Wildcard::Unhardened);
1679        assert_eq!(
1680            xprv.derivation_paths.paths(),
1681            &vec![
1682                bip32::DerivationPath::from_str("m/2/0/3456/9876").unwrap(),
1683                bip32::DerivationPath::from_str("m/2/1/3456/9876").unwrap(),
1684                bip32::DerivationPath::from_str("m/2/9854/3456/9876").unwrap()
1685            ],
1686        );
1687        assert_eq!(
1688            xprv,
1689            get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1690        );
1691        let xprv = get_multipath_xprv("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/<0;1>/*");
1692        assert_eq!(xprv.wildcard, Wildcard::Unhardened);
1693        assert_eq!(
1694            xprv.derivation_paths.paths(),
1695            &vec![
1696                bip32::DerivationPath::from_str("m/0").unwrap(),
1697                bip32::DerivationPath::from_str("m/1").unwrap(),
1698            ],
1699        );
1700        assert_eq!(
1701            xprv,
1702            get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1703        );
1704        let xprv = get_multipath_xprv("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1h>/8h/*'");
1705        assert_eq!(xprv.wildcard, Wildcard::Hardened);
1706        assert_eq!(
1707            xprv.derivation_paths.paths(),
1708            &vec![
1709                bip32::DerivationPath::from_str("m/9478'/0'/8'").unwrap(),
1710                bip32::DerivationPath::from_str("m/9478h/1h/8h").unwrap(),
1711            ],
1712        );
1713        assert_eq!(
1714            xprv,
1715            get_multipath_xprv(&DescriptorSecretKey::MultiXPrv(xprv.clone()).to_string())
1716        );
1717        let desc_key = DescriptorSecretKey::from_str("[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1>/8h/*'").unwrap();
1718        assert!(desc_key.to_public(&secp).is_err());
1719        assert!(desc_key.is_multipath());
1720        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()]);
1721
1722        // It's invalid to:
1723        // - Not have opening or closing brackets
1724        // - Have multiple steps with different indexes
1725        // - Only have one index within the brackets
1726        DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/<0;1;42;9854").unwrap_err();
1727        DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/0;1;42;9854>").unwrap_err();
1728        DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;1>/96/<0;1>").unwrap_err();
1729        DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0>").unwrap_err();
1730        DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;>").unwrap_err();
1731        DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<;1>").unwrap_err();
1732        DescriptorPublicKey::from_str("tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2/4/<0;1;>").unwrap_err();
1733    }
1734
1735    #[test]
1736    fn test_multixprv_to_public() {
1737        let secp = secp256k1::Secp256k1::signing_only();
1738
1739        // Works if all hardended derivation steps are part of the shared path
1740        let xprv = get_multipath_xprv("[01020304/5]tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1'/2'/3/<4;5>/6");
1741        let xpub = DescriptorPublicKey::MultiXPub(xprv.to_public(&secp).unwrap()); // wrap in a DescriptorPublicKey to have Display
1742        assert_eq!(xpub.to_string(), "[01020304/5/1'/2']tpubDBTRkEMEFkUbk3WTz6CFSULyswkTPpPr38AWibf5TVkB5GxuBxbSbmdFGr3jmswwemknyYxAGoX7BJnKfyPy4WXaHmcrxZhfzFwoUFvFtm5/3/<4;5>/6");
1743
1744        // Fails if they're part of the multi-path specifier or following it
1745        get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/2/<3';4'>/5").to_public(&secp).unwrap_err();
1746        get_multipath_xprv("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/2/<3;4>/5/6'").to_public(&secp).unwrap_err();
1747    }
1748
1749    #[test]
1750    fn test_parse_wif() {
1751        let secret_key = "[0dd03d09/0'/1/2']5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ"
1752            .parse()
1753            .unwrap();
1754        if let DescriptorSecretKey::Single(single) = secret_key {
1755            assert_eq!(
1756                single.key.inner,
1757                "0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D"
1758                    .parse()
1759                    .unwrap()
1760            );
1761            assert_eq!(
1762                single.origin,
1763                Some(("0dd03d09".parse().unwrap(), "m/0'/1/2'".parse().unwrap()))
1764            );
1765        } else {
1766            panic!("expected a DescriptorSecretKey::Single");
1767        }
1768    }
1769
1770    #[test]
1771    #[cfg(feature = "serde")]
1772    fn test_descriptor_public_key_serde() {
1773        let desc = "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2";
1774        let public_key = DescriptorPublicKey::from_str(desc).unwrap();
1775        assert_tokens(&public_key, &[Token::String(desc)]);
1776    }
1777
1778    #[test]
1779    fn definite_keys() {
1780        // basic xpub
1781        let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
1782            .parse::<DescriptorPublicKey>()
1783            .unwrap();
1784        assert!(matches!(DefiniteDescriptorKey::new(desc), Ok(..)));
1785        // xpub with wildcard
1786        let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/*"
1787            .parse::<DescriptorPublicKey>()
1788            .unwrap();
1789        assert!(matches!(DefiniteDescriptorKey::new(desc), Err(NonDefiniteKeyError::Wildcard)));
1790        // multipath xpub
1791        let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/<0;1>"
1792            .parse::<DescriptorPublicKey>()
1793            .unwrap();
1794        assert!(matches!(DefiniteDescriptorKey::new(desc), Err(NonDefiniteKeyError::Multipath)));
1795        // xpub with hardened path
1796        let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/1'/2"
1797            .parse::<DescriptorPublicKey>()
1798            .unwrap();
1799        assert!(matches!(
1800            DefiniteDescriptorKey::new(desc),
1801            Err(NonDefiniteKeyError::HardenedStep)
1802        ));
1803    }
1804
1805    #[test]
1806    fn test_xkey_network() {
1807        use bitcoin::NetworkKind;
1808
1809        // Test mainnet xpub
1810        let mainnet_xpub = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
1811            .parse::<DescriptorPublicKey>()
1812            .unwrap();
1813        assert_eq!(mainnet_xpub.xkey_network(), Some(NetworkKind::Main));
1814
1815        // Test testnet xpub
1816        let testnet_xpub = "tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi"
1817            .parse::<DescriptorPublicKey>()
1818            .unwrap();
1819        assert_eq!(testnet_xpub.xkey_network(), Some(NetworkKind::Test));
1820
1821        // Test single public key (no extended key)
1822        let single_key = "021d4ea7132d4e1a362ee5efd8d0b59dd4d1fe8906eefa7dd812b05a46b73d829b"
1823            .parse::<DescriptorPublicKey>()
1824            .unwrap();
1825        assert_eq!(single_key.xkey_network(), None);
1826    }
1827}