From 100b7d6e4f4c08d7f35232ebc8fc145b49825c76 Mon Sep 17 00:00:00 2001 From: Scott Robinson Date: Sun, 23 Jul 2023 13:10:41 +1000 Subject: [PATCH] Extract specialised DescriptorPublicKey functionality into DescriptorMultiExtendedPublicKey --- src/descriptor/key.rs | 82 +++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/src/descriptor/key.rs b/src/descriptor/key.rs index 6c44bd27a..dcf9b42d6 100644 --- a/src/descriptor/key.rs +++ b/src/descriptor/key.rs @@ -20,6 +20,7 @@ use crate::{hash256, MiniscriptKey, ToPublicKey}; type DescriptorSinglePublicKey = SinglePub; type DescriptorExtendedPublicKey = DescriptorXKey; +type DescriptorMultiExtendedPublicKey = DescriptorMultiXKey; /// The descriptor pubkey, either a single pubkey or an xpub. #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)] @@ -29,7 +30,7 @@ pub enum DescriptorPublicKey { /// Extended public key (xpub). XPub(DescriptorExtendedPublicKey), /// Multiple extended public keys. - MultiXPub(DescriptorMultiXKey), + MultiXPub(DescriptorMultiExtendedPublicKey), } /// The descriptor secret key, either a single private key or an xprv. @@ -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), } } } @@ -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 { + None + } + + fn has_wildcard(&self) -> bool { + self.wildcard != Wildcard::None + } + + fn at_derivation_index(self, _index: u32) -> Result { + Err(ConversionError::MultiKey) + } + + fn is_multipath(&self) -> bool { + true + } + + fn derive_public_key( + &self, + _secp: &Secp256k1, + ) -> Result { + 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(), } } @@ -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(), } } @@ -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(), } } @@ -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), } } @@ -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(), } } @@ -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), } }