Skip to content

Commit 687fd4e

Browse files
author
Scott Robinson
committed
Extract specialised DescriptorKey functionality into DescriptorMultiExtendedPublicKey
1 parent c430f70 commit 687fd4e

File tree

1 file changed

+81
-32
lines changed

1 file changed

+81
-32
lines changed

src/descriptor/key.rs

+81-32
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::{hash256, MiniscriptKey, ToPublicKey};
2020

2121
type DescriptorSinglePublicKey = SinglePub;
2222
type DescriptorExtendedPublicKey = DescriptorXKey<bip32::ExtendedPubKey>;
23+
type DescriptorMultiExtendedPublicKey = DescriptorMultiXKey<bip32::ExtendedPubKey>;
2324

2425
/// The descriptor pubkey, either a single pubkey or an xpub.
2526
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
@@ -29,7 +30,7 @@ pub enum DescriptorPublicKey {
2930
/// Extended public key (xpub).
3031
XPub(DescriptorExtendedPublicKey),
3132
/// Multiple extended public keys.
32-
MultiXPub(DescriptorMultiXKey<bip32::ExtendedPubKey>),
33+
MultiXPub(DescriptorMultiExtendedPublicKey),
3334
}
3435

3536
/// The descriptor secret key, either a single private key or an xprv.
@@ -310,22 +311,26 @@ impl fmt::Display for DescriptorExtendedPublicKey {
310311
}
311312
}
312313

314+
impl fmt::Display for DescriptorMultiExtendedPublicKey {
315+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316+
maybe_fmt_master_id(f, &self.origin)?;
317+
self.xkey.fmt(f)?;
318+
fmt_derivation_paths(f, self.derivation_paths.paths())?;
319+
match self.wildcard {
320+
Wildcard::None => {}
321+
Wildcard::Unhardened => write!(f, "/*")?,
322+
Wildcard::Hardened => write!(f, "/*h")?,
323+
}
324+
Ok(())
325+
}
326+
}
327+
313328
impl fmt::Display for DescriptorPublicKey {
314329
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
315330
match *self {
316331
DescriptorPublicKey::Single(ref pk) => pk.fmt(f),
317332
DescriptorPublicKey::XPub(ref xpub) => xpub.fmt(f),
318-
DescriptorPublicKey::MultiXPub(ref xpub) => {
319-
maybe_fmt_master_id(f, &xpub.origin)?;
320-
xpub.xkey.fmt(f)?;
321-
fmt_derivation_paths(f, xpub.derivation_paths.paths())?;
322-
match xpub.wildcard {
323-
Wildcard::None => {}
324-
Wildcard::Unhardened => write!(f, "/*")?,
325-
Wildcard::Hardened => write!(f, "/*h")?,
326-
}
327-
Ok(())
328-
}
333+
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.fmt(f),
329334
}
330335
}
331336
}
@@ -501,6 +506,30 @@ impl FromStr for DescriptorExtendedPublicKey {
501506
}
502507
}
503508

509+
impl FromStr for DescriptorMultiExtendedPublicKey {
510+
type Err = DescriptorKeyParseError;
511+
512+
fn from_str(s: &str) -> Result<Self, Self::Err> {
513+
let (key_part, origin) = parse_key_origin(s)?;
514+
515+
let (xpub, derivation_paths, wildcard) =
516+
parse_xkey_deriv::<bip32::ExtendedPubKey>(key_part)?;
517+
518+
if derivation_paths.len() < 2 {
519+
return Err(DescriptorKeyParseError(
520+
"Multiple derivation paths are required for multi extended keys",
521+
));
522+
}
523+
524+
Ok(Self {
525+
origin,
526+
xkey: xpub,
527+
derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
528+
wildcard,
529+
})
530+
}
531+
}
532+
504533
impl FromStr for DescriptorPublicKey {
505534
type Err = DescriptorKeyParseError;
506535

@@ -518,12 +547,7 @@ impl FromStr for DescriptorPublicKey {
518547
let (xpub, derivation_paths, wildcard) =
519548
parse_xkey_deriv::<bip32::ExtendedPubKey>(key_part)?;
520549
if derivation_paths.len() > 1 {
521-
Ok(DescriptorPublicKey::MultiXPub(DescriptorMultiXKey {
522-
origin,
523-
xkey: xpub,
524-
derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
525-
wildcard,
526-
}))
550+
DescriptorMultiExtendedPublicKey::from_str(s).map(Self::MultiXPub)
527551
} else {
528552
DescriptorExtendedPublicKey::from_str(s).map(Self::XPub)
529553
}
@@ -757,18 +781,45 @@ impl DescriptorKey for DescriptorExtendedPublicKey {
757781
}
758782
}
759783

784+
impl DescriptorKey for DescriptorMultiExtendedPublicKey {
785+
fn master_fingerprint(&self) -> bip32::Fingerprint {
786+
if let Some((fingerprint, _)) = self.origin {
787+
fingerprint
788+
} else {
789+
self.xkey.fingerprint()
790+
}
791+
}
792+
793+
fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
794+
None
795+
}
796+
797+
fn has_wildcard(&self) -> bool {
798+
self.wildcard != Wildcard::None
799+
}
800+
801+
fn at_derivation_index(self, _index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
802+
Err(ConversionError::MultiKey)
803+
}
804+
805+
fn is_multipath(&self) -> bool {
806+
true
807+
}
808+
809+
fn derive_public_key<C: Verification>(
810+
&self,
811+
_secp: &Secp256k1<C>,
812+
) -> Result<bitcoin::PublicKey, ConversionError> {
813+
Err(ConversionError::MultiKey)
814+
}
815+
}
816+
760817
impl DescriptorPublicKey {
761818
/// The fingerprint of the master key associated with this key, `0x00000000` if none.
762819
pub fn master_fingerprint(&self) -> bip32::Fingerprint {
763820
match *self {
764821
DescriptorPublicKey::XPub(ref xpub) => xpub.master_fingerprint(),
765-
DescriptorPublicKey::MultiXPub(ref xpub) => {
766-
if let Some((fingerprint, _)) = xpub.origin {
767-
fingerprint
768-
} else {
769-
xpub.xkey.fingerprint()
770-
}
771-
}
822+
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.master_fingerprint(),
772823
DescriptorPublicKey::Single(ref single) => single.master_fingerprint(),
773824
}
774825
}
@@ -784,7 +835,7 @@ impl DescriptorPublicKey {
784835
match *self {
785836
DescriptorPublicKey::XPub(ref xpub) => xpub.full_derivation_path(),
786837
DescriptorPublicKey::Single(ref single) => single.full_derivation_path(),
787-
DescriptorPublicKey::MultiXPub(_) => None,
838+
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.full_derivation_path(),
788839
}
789840
}
790841

@@ -799,7 +850,7 @@ impl DescriptorPublicKey {
799850
match *self {
800851
DescriptorPublicKey::Single(ref single) => single.has_wildcard(),
801852
DescriptorPublicKey::XPub(ref xpub) => xpub.has_wildcard(),
802-
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.wildcard != Wildcard::None,
853+
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.has_wildcard(),
803854
}
804855
}
805856

@@ -825,7 +876,7 @@ impl DescriptorPublicKey {
825876
match self {
826877
DescriptorPublicKey::Single(single) => single.at_derivation_index(index),
827878
DescriptorPublicKey::XPub(xpub) => xpub.at_derivation_index(index),
828-
DescriptorPublicKey::MultiXPub(_) => Err(ConversionError::MultiKey),
879+
DescriptorPublicKey::MultiXPub(xpub) => xpub.at_derivation_index(index),
829880
}
830881
}
831882

@@ -834,7 +885,7 @@ impl DescriptorPublicKey {
834885
match self {
835886
DescriptorPublicKey::Single(single) => single.is_multipath(),
836887
DescriptorPublicKey::XPub(xpub) => xpub.is_multipath(),
837-
DescriptorPublicKey::MultiXPub(_) => true,
888+
DescriptorPublicKey::MultiXPub(xpub) => xpub.is_multipath(),
838889
}
839890
}
840891

@@ -1208,9 +1259,7 @@ impl DefiniteDescriptorKey {
12081259
match self.0 {
12091260
DescriptorPublicKey::Single(ref pk) => pk.derive_public_key(secp),
12101261
DescriptorPublicKey::XPub(ref xpk) => xpk.derive_public_key(secp),
1211-
DescriptorPublicKey::MultiXPub(_) => {
1212-
unreachable!("A definite key cannot contain a multipath key.")
1213-
}
1262+
DescriptorPublicKey::MultiXPub(ref xpk) => xpk.derive_public_key(secp),
12141263
}
12151264
}
12161265

0 commit comments

Comments
 (0)