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