Skip to content

Commit c430f70

Browse files
author
Scott Robinson
committed
Extract specialised DescriptorKey functionality into DescriptorSinglePublicKey
1 parent bfa946e commit c430f70

File tree

1 file changed

+108
-69
lines changed

1 file changed

+108
-69
lines changed

src/descriptor/key.rs

+108-69
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::prelude::*;
1818
use crate::serde::{Deserialize, Deserializer, Serialize, Serializer};
1919
use crate::{hash256, MiniscriptKey, ToPublicKey};
2020

21+
type DescriptorSinglePublicKey = SinglePub;
2122
type DescriptorExtendedPublicKey = DescriptorXKey<bip32::ExtendedPubKey>;
2223

2324
/// The descriptor pubkey, either a single pubkey or an xpub.
@@ -285,6 +286,16 @@ impl error::Error for DescriptorKeyParseError {
285286
}
286287
}
287288

289+
impl fmt::Display for DescriptorSinglePublicKey {
290+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291+
maybe_fmt_master_id(f, &self.origin)?;
292+
match self.key {
293+
SinglePubKey::FullKey(full_key) => full_key.fmt(f),
294+
SinglePubKey::XOnly(x_only_key) => x_only_key.fmt(f),
295+
}
296+
}
297+
}
298+
288299
impl fmt::Display for DescriptorExtendedPublicKey {
289300
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290301
maybe_fmt_master_id(f, &self.origin)?;
@@ -302,14 +313,7 @@ impl fmt::Display for DescriptorExtendedPublicKey {
302313
impl fmt::Display for DescriptorPublicKey {
303314
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
304315
match *self {
305-
DescriptorPublicKey::Single(ref pk) => {
306-
maybe_fmt_master_id(f, &pk.origin)?;
307-
match pk.key {
308-
SinglePubKey::FullKey(full_key) => full_key.fmt(f),
309-
SinglePubKey::XOnly(x_only_key) => x_only_key.fmt(f),
310-
}?;
311-
Ok(())
312-
}
316+
DescriptorPublicKey::Single(ref pk) => pk.fmt(f),
313317
DescriptorPublicKey::XPub(ref xpub) => xpub.fmt(f),
314318
DescriptorPublicKey::MultiXPub(ref xpub) => {
315319
maybe_fmt_master_id(f, &xpub.origin)?;
@@ -438,6 +442,41 @@ fn fmt_derivation_paths(f: &mut fmt::Formatter, paths: &[bip32::DerivationPath])
438442
Ok(())
439443
}
440444

445+
impl FromStr for DescriptorSinglePublicKey {
446+
type Err = DescriptorKeyParseError;
447+
448+
fn from_str(s: &str) -> Result<Self, Self::Err> {
449+
let (key_part, origin) = parse_key_origin(s)?;
450+
451+
let key = match key_part.len() {
452+
64 => {
453+
let x_only_key = XOnlyPublicKey::from_str(key_part)
454+
.map_err(|_| DescriptorKeyParseError("Error while parsing simple xonly key"))?;
455+
SinglePubKey::XOnly(x_only_key)
456+
}
457+
66 | 130 => {
458+
if !(&key_part[0..2] == "02" || &key_part[0..2] == "03" || &key_part[0..2] == "04")
459+
{
460+
return Err(DescriptorKeyParseError(
461+
"Only publickeys with prefixes 02/03/04 are allowed",
462+
));
463+
}
464+
let key = bitcoin::PublicKey::from_str(key_part).map_err(|_| {
465+
DescriptorKeyParseError("Error while parsing simple public key")
466+
})?;
467+
SinglePubKey::FullKey(key)
468+
}
469+
_ => {
470+
return Err(DescriptorKeyParseError(
471+
"Public keys must be 64/66/130 characters in size",
472+
))
473+
}
474+
};
475+
476+
Ok(Self { key, origin })
477+
}
478+
}
479+
441480
impl FromStr for DescriptorExtendedPublicKey {
442481
type Err = DescriptorKeyParseError;
443482

@@ -489,34 +528,7 @@ impl FromStr for DescriptorPublicKey {
489528
DescriptorExtendedPublicKey::from_str(s).map(Self::XPub)
490529
}
491530
} else {
492-
let key = match key_part.len() {
493-
64 => {
494-
let x_only_key = XOnlyPublicKey::from_str(key_part).map_err(|_| {
495-
DescriptorKeyParseError("Error while parsing simple xonly key")
496-
})?;
497-
SinglePubKey::XOnly(x_only_key)
498-
}
499-
66 | 130 => {
500-
if !(&key_part[0..2] == "02"
501-
|| &key_part[0..2] == "03"
502-
|| &key_part[0..2] == "04")
503-
{
504-
return Err(DescriptorKeyParseError(
505-
"Only publickeys with prefixes 02/03/04 are allowed",
506-
));
507-
}
508-
let key = bitcoin::PublicKey::from_str(key_part).map_err(|_| {
509-
DescriptorKeyParseError("Error while parsing simple public key")
510-
})?;
511-
SinglePubKey::FullKey(key)
512-
}
513-
_ => {
514-
return Err(DescriptorKeyParseError(
515-
"Public keys must be 64/66/130 characters in size",
516-
))
517-
}
518-
};
519-
Ok(DescriptorPublicKey::Single(SinglePub { key, origin }))
531+
DescriptorSinglePublicKey::from_str(s).map(Self::Single)
520532
}
521533
}
522534
}
@@ -601,6 +613,60 @@ pub trait DescriptorKey : Clone + fmt::Debug + fmt::Display + Eq + FromStr + std
601613
) -> Result<bitcoin::PublicKey, ConversionError>;
602614
}
603615

616+
impl DescriptorKey for DescriptorSinglePublicKey {
617+
fn master_fingerprint(&self) -> bip32::Fingerprint {
618+
if let Some((fingerprint, _)) = self.origin {
619+
fingerprint
620+
} else {
621+
let mut engine = XpubIdentifier::engine();
622+
match self.key {
623+
SinglePubKey::FullKey(pk) => {
624+
pk.write_into(&mut engine).expect("engines don't error")
625+
}
626+
SinglePubKey::XOnly(x_only_pk) => engine.input(&x_only_pk.serialize()),
627+
};
628+
bip32::Fingerprint::from(
629+
&XpubIdentifier::from_engine(engine)[..4]
630+
.try_into()
631+
.expect("4 byte slice"),
632+
)
633+
}
634+
}
635+
636+
fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
637+
Some(if let Some((_, ref path)) = self.origin {
638+
path.clone()
639+
} else {
640+
bip32::DerivationPath::from(vec![])
641+
})
642+
}
643+
644+
fn has_wildcard(&self) -> bool {
645+
false
646+
}
647+
648+
fn at_derivation_index(self, _index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
649+
Ok(
650+
DefiniteDescriptorKey::new(DescriptorPublicKey::Single(self))
651+
.expect("The key should not contain any wildcards at this point"),
652+
)
653+
}
654+
655+
fn is_multipath(&self) -> bool {
656+
false
657+
}
658+
659+
fn derive_public_key<C: Verification>(
660+
&self,
661+
_secp: &Secp256k1<C>,
662+
) -> Result<bitcoin::PublicKey, ConversionError> {
663+
match self.key {
664+
SinglePubKey::FullKey(pk) => Ok(pk),
665+
SinglePubKey::XOnly(xpk) => Ok(xpk.to_public_key()),
666+
}
667+
}
668+
}
669+
604670
impl DescriptorKey for DescriptorExtendedPublicKey {
605671
/// The fingerprint of the master key associated with this key, `0x00000000` if none.
606672
fn master_fingerprint(&self) -> bip32::Fingerprint {
@@ -703,24 +769,7 @@ impl DescriptorPublicKey {
703769
xpub.xkey.fingerprint()
704770
}
705771
}
706-
DescriptorPublicKey::Single(ref single) => {
707-
if let Some((fingerprint, _)) = single.origin {
708-
fingerprint
709-
} else {
710-
let mut engine = XpubIdentifier::engine();
711-
match single.key {
712-
SinglePubKey::FullKey(pk) => {
713-
pk.write_into(&mut engine).expect("engines don't error")
714-
}
715-
SinglePubKey::XOnly(x_only_pk) => engine.input(&x_only_pk.serialize()),
716-
};
717-
bip32::Fingerprint::from(
718-
&XpubIdentifier::from_engine(engine)[..4]
719-
.try_into()
720-
.expect("4 byte slice"),
721-
)
722-
}
723-
}
772+
DescriptorPublicKey::Single(ref single) => single.master_fingerprint(),
724773
}
725774
}
726775

@@ -734,13 +783,7 @@ impl DescriptorPublicKey {
734783
pub fn full_derivation_path(&self) -> Option<bip32::DerivationPath> {
735784
match *self {
736785
DescriptorPublicKey::XPub(ref xpub) => xpub.full_derivation_path(),
737-
DescriptorPublicKey::Single(ref single) => {
738-
Some(if let Some((_, ref path)) = single.origin {
739-
path.clone()
740-
} else {
741-
bip32::DerivationPath::from(vec![])
742-
})
743-
}
786+
DescriptorPublicKey::Single(ref single) => single.full_derivation_path(),
744787
DescriptorPublicKey::MultiXPub(_) => None,
745788
}
746789
}
@@ -754,7 +797,7 @@ impl DescriptorPublicKey {
754797
/// Whether or not the key has a wildcard
755798
pub fn has_wildcard(&self) -> bool {
756799
match *self {
757-
DescriptorPublicKey::Single(..) => false,
800+
DescriptorPublicKey::Single(ref single) => single.has_wildcard(),
758801
DescriptorPublicKey::XPub(ref xpub) => xpub.has_wildcard(),
759802
DescriptorPublicKey::MultiXPub(ref xpub) => xpub.wildcard != Wildcard::None,
760803
}
@@ -780,8 +823,7 @@ impl DescriptorPublicKey {
780823
/// - If `index` is hardened.
781824
pub fn at_derivation_index(self, index: u32) -> Result<DefiniteDescriptorKey, ConversionError> {
782825
match self {
783-
DescriptorPublicKey::Single(_) => Ok(DefiniteDescriptorKey::new(self)
784-
.expect("The key should not contain any wildcards at this point")),
826+
DescriptorPublicKey::Single(single) => single.at_derivation_index(index),
785827
DescriptorPublicKey::XPub(xpub) => xpub.at_derivation_index(index),
786828
DescriptorPublicKey::MultiXPub(_) => Err(ConversionError::MultiKey),
787829
}
@@ -790,7 +832,7 @@ impl DescriptorPublicKey {
790832
/// Whether or not this key has multiple derivation paths.
791833
pub fn is_multipath(&self) -> bool {
792834
match self {
793-
DescriptorPublicKey::Single(..) => false,
835+
DescriptorPublicKey::Single(single) => single.is_multipath(),
794836
DescriptorPublicKey::XPub(xpub) => xpub.is_multipath(),
795837
DescriptorPublicKey::MultiXPub(_) => true,
796838
}
@@ -1164,10 +1206,7 @@ impl DefiniteDescriptorKey {
11641206
secp: &Secp256k1<C>,
11651207
) -> Result<bitcoin::PublicKey, ConversionError> {
11661208
match self.0 {
1167-
DescriptorPublicKey::Single(ref pk) => match pk.key {
1168-
SinglePubKey::FullKey(pk) => Ok(pk),
1169-
SinglePubKey::XOnly(xpk) => Ok(xpk.to_public_key()),
1170-
},
1209+
DescriptorPublicKey::Single(ref pk) => pk.derive_public_key(secp),
11711210
DescriptorPublicKey::XPub(ref xpk) => xpk.derive_public_key(secp),
11721211
DescriptorPublicKey::MultiXPub(_) => {
11731212
unreachable!("A definite key cannot contain a multipath key.")

0 commit comments

Comments
 (0)