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