Skip to content

Commit

Permalink
Extract specialised DescriptorPublicKey functionality into Descriptor…
Browse files Browse the repository at this point in the history
…SinglePublicKey
  • Loading branch information
Scott Robinson committed Jul 23, 2023
1 parent 8dd1ae1 commit eaba815
Showing 1 changed file with 60 additions and 38 deletions.
98 changes: 60 additions & 38 deletions src/descriptor/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::prelude::*;
use crate::serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{hash256, MiniscriptKey, ToPublicKey};

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

/// The descriptor pubkey, either a single pubkey or an xpub.
Expand Down Expand Up @@ -285,6 +286,17 @@ impl error::Error for DescriptorKeyParseError {
}
}

impl fmt::Display for DescriptorSinglePublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
maybe_fmt_master_id(f, &self.origin)?;
match self.key {
SinglePubKey::FullKey(full_key) => full_key.fmt(f),
SinglePubKey::XOnly(x_only_key) => x_only_key.fmt(f),
}?;
Ok(())
}
}

impl fmt::Display for DescriptorExtendedPublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
maybe_fmt_master_id(f, &self.origin)?;
Expand All @@ -302,14 +314,7 @@ impl fmt::Display for DescriptorExtendedPublicKey {
impl fmt::Display for DescriptorPublicKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DescriptorPublicKey::Single(ref pk) => {
maybe_fmt_master_id(f, &pk.origin)?;
match pk.key {
SinglePubKey::FullKey(full_key) => full_key.fmt(f),
SinglePubKey::XOnly(x_only_key) => x_only_key.fmt(f),
}?;
Ok(())
}
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)?;
Expand Down Expand Up @@ -565,6 +570,48 @@ pub trait DescriptorInnerKey {
fn is_multipath(&self) -> bool;
}

impl DescriptorInnerKey for DescriptorSinglePublicKey {
fn master_fingerprint(&self) -> bip32::Fingerprint {
if let Some((fingerprint, _)) = self.origin {
fingerprint
} else {
let mut engine = XpubIdentifier::engine();
match self.key {
SinglePubKey::FullKey(pk) => {
pk.write_into(&mut engine).expect("engines don't error")
}
SinglePubKey::XOnly(x_only_pk) => engine.input(&x_only_pk.serialize()),
};
bip32::Fingerprint::from(
&XpubIdentifier::from_engine(engine)[..4]
.try_into()
.expect("4 byte slice"),
)
}
}

fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
Some(if let Some((_, ref path)) = self.origin {
path.clone()
} else {
bip32::DerivationPath::from(vec![])
})
}

fn has_wildcard(&self) -> bool {
false
}

fn at_derivation_index(self, _index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
Ok(DefiniteDescriptorKey::new(DescriptorPublicKey::Single(self))
.expect("The key should not contain any wildcards at this point"))
}

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

impl DescriptorInnerKey for DescriptorExtendedPublicKey {
fn master_fingerprint(&self) -> bip32::Fingerprint {
if let Some((fingerprint, _)) = self.origin {
Expand Down Expand Up @@ -629,24 +676,7 @@ impl DescriptorPublicKey {
xpub.xkey.fingerprint()
}
}
DescriptorPublicKey::Single(ref single) => {
if let Some((fingerprint, _)) = single.origin {
fingerprint
} else {
let mut engine = XpubIdentifier::engine();
match single.key {
SinglePubKey::FullKey(pk) => {
pk.write_into(&mut engine).expect("engines don't error")
}
SinglePubKey::XOnly(x_only_pk) => engine.input(&x_only_pk.serialize()),
};
bip32::Fingerprint::from(
&XpubIdentifier::from_engine(engine)[..4]
.try_into()
.expect("4 byte slice"),
)
}
}
DescriptorPublicKey::Single(ref single) => single.master_fingerprint(),
}
}

Expand All @@ -660,13 +690,7 @@ impl DescriptorPublicKey {
pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
match *self {
DescriptorPublicKey::XPub(ref xpub) => xpub.full_derivation_path(),
DescriptorPublicKey::Single(ref single) => {
Some(if let Some((_, ref path)) = single.origin {
path.clone()
} else {
bip32::DerivationPath::from(vec![])
})
}
DescriptorPublicKey::Single(ref single) => single.full_derivation_path(),
DescriptorPublicKey::MultiXPub(_) => None,
}
}
Expand All @@ -680,7 +704,7 @@ impl DescriptorPublicKey {
/// Whether or not the key has a wildcard
pub fn has_wildcard(&self) -> bool {
match *self {
DescriptorPublicKey::Single(..) => false,
DescriptorPublicKey::Single(ref single) => single.has_wildcard(),
DescriptorPublicKey::XPub(ref xpub) => xpub.has_wildcard(),
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.wildcard != Wildcard::None,
}
Expand All @@ -706,8 +730,7 @@ impl DescriptorPublicKey {
/// - If `index` is hardened.
pub fn at_derivation_index(self, index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
match self {
DescriptorPublicKey::Single(_) => Ok(DefiniteDescriptorKey::new(self)
.expect("The key should not contain any wildcards at this point")),
DescriptorPublicKey::Single(single) => single.at_derivation_index(index),
DescriptorPublicKey::XPub(xpub) => xpub.at_derivation_index(index),
DescriptorPublicKey::MultiXPub(_) => Err(ConversionError::MultiKey),
}
Expand All @@ -716,8 +739,7 @@ impl DescriptorPublicKey {
/// Whether or not this key has multiple derivation paths.
pub fn is_multipath(&self) -> bool {
match *self {
DescriptorPublicKey::Single(..) => false,
DescriptorPublicKey::XPub(..) => self.is_multipath(),
DescriptorPublicKey::Single(..) | DescriptorPublicKey::XPub(..) => self.is_multipath(),
DescriptorPublicKey::MultiXPub(_) => true,
}
}
Expand Down

0 comments on commit eaba815

Please sign in to comment.