Skip to content

Commit

Permalink
Extract specialised DescriptorPublicKey functionality into Descriptor…
Browse files Browse the repository at this point in the history
…MultiExtendedPublicKey
  • Loading branch information
quad committed Jul 23, 2023
1 parent fa4dabb commit 100b7d6
Showing 1 changed file with 56 additions and 26 deletions.
82 changes: 56 additions & 26 deletions src/descriptor/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::{hash256, MiniscriptKey, ToPublicKey};

type DescriptorSinglePublicKey = SinglePub;
type DescriptorExtendedPublicKey = DescriptorXKey<bip32::ExtendedPubKey>;
type DescriptorMultiExtendedPublicKey = DescriptorMultiXKey<bip32::ExtendedPubKey>;

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

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

impl fmt::Display for DescriptorMultiExtendedPublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
maybe_fmt_master_id(f, &self.origin)?;
self.xkey.fmt(f)?;
fmt_derivation_paths(f, self.derivation_paths.paths())?;
match self.wildcard {
Wildcard::None => {}
Wildcard::Unhardened => write!(f, "/*")?,
Wildcard::Hardened => write!(f, "/*h")?,
}
Ok(())
}
}

impl fmt::Display for DescriptorPublicKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DescriptorPublicKey::Single(ref pk) => pk.fmt(f),
DescriptorPublicKey::XPub(ref xpub) => xpub.fmt(f),
DescriptorPublicKey::MultiXPub(ref xpub) => {
maybe_fmt_master_id(f, &xpub.origin)?;
xpub.xkey.fmt(f)?;
fmt_derivation_paths(f, xpub.derivation_paths.paths())?;
match xpub.wildcard {
Wildcard::None => {}
Wildcard::Unhardened => write!(f, "/*")?,
Wildcard::Hardened => write!(f, "/*h")?,
}
Ok(())
}
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.fmt(f),
}
}
}
Expand Down Expand Up @@ -730,18 +735,45 @@ impl DescriptorInnerKey for DescriptorExtendedPublicKey {
}
}

impl DescriptorInnerKey for DescriptorMultiExtendedPublicKey {
fn master_fingerprint(&self) -> bip32::Fingerprint {
if let Some((fingerprint, _)) = self.origin {
fingerprint
} else {
self.xkey.fingerprint()
}
}

fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
None
}

fn has_wildcard(&self) -> bool {
self.wildcard != Wildcard::None
}

fn at_derivation_index(self, _index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
Err(ConversionError::MultiKey)
}

fn is_multipath(&self) -> bool {
true
}

fn derive_public_key<C: Verification>(
&self,
_secp: &Secp256k1<C>,
) -> Result<bitcoin::PublicKey, ConversionError> {
Err(ConversionError::MultiKey)
}
}

impl DescriptorPublicKey {
/// The fingerprint of the master key associated with this key, `0x00000000` if none.
pub fn master_fingerprint(&self) -> bip32::Fingerprint {
match *self {
DescriptorPublicKey::XPub(ref xpub) => xpub.master_fingerprint(),
DescriptorPublicKey::MultiXPub(ref xpub) => {
if let Some((fingerprint, _)) = xpub.origin {
fingerprint
} else {
xpub.xkey.fingerprint()
}
}
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.master_fingerprint(),
DescriptorPublicKey::Single(ref single) => single.master_fingerprint(),
}
}
Expand All @@ -757,7 +789,7 @@ impl DescriptorPublicKey {
match *self {
DescriptorPublicKey::XPub(ref xpub) => xpub.full_derivation_path(),
DescriptorPublicKey::Single(ref single) => single.full_derivation_path(),
DescriptorPublicKey::MultiXPub(_) => None,
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.full_derivation_path(),
}
}

Expand All @@ -772,7 +804,7 @@ impl DescriptorPublicKey {
match *self {
DescriptorPublicKey::Single(ref single) => single.has_wildcard(),
DescriptorPublicKey::XPub(ref xpub) => xpub.has_wildcard(),
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.wildcard != Wildcard::None,
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.has_wildcard(),
}
}

Expand All @@ -798,7 +830,7 @@ impl DescriptorPublicKey {
match self {
DescriptorPublicKey::Single(single) => single.at_derivation_index(index),
DescriptorPublicKey::XPub(xpub) => xpub.at_derivation_index(index),
DescriptorPublicKey::MultiXPub(_) => Err(ConversionError::MultiKey),
DescriptorPublicKey::MultiXPub(xpub) => xpub.at_derivation_index(index),
}
}

Expand All @@ -807,7 +839,7 @@ impl DescriptorPublicKey {
match self {
DescriptorPublicKey::Single(single) => single.is_multipath(),
DescriptorPublicKey::XPub(xpub) => xpub.is_multipath(),
DescriptorPublicKey::MultiXPub(_) => true,
DescriptorPublicKey::MultiXPub(xpub) => xpub.is_multipath(),
}
}

Expand Down Expand Up @@ -1181,9 +1213,7 @@ impl DefiniteDescriptorKey {
match self.0 {
DescriptorPublicKey::Single(ref pk) => pk.derive_public_key(secp),
DescriptorPublicKey::XPub(ref xpk) => xpk.derive_public_key(secp),
DescriptorPublicKey::MultiXPub(_) => {
unreachable!("A definite key cannot contain a multipath key.")
}
DescriptorPublicKey::MultiXPub(ref xpk) => xpk.derive_public_key(secp),
}
}

Expand Down

0 comments on commit 100b7d6

Please sign in to comment.