Skip to main content

elements_miniscript/descriptor/
key.rs

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