Skip to content

Commit 14799e2

Browse files
author
Scott Robinson
committed
Extract FromStr functionality for DescriptorInnerKeys
1 parent 100b7d6 commit 14799e2

File tree

1 file changed

+83
-48
lines changed

1 file changed

+83
-48
lines changed

src/descriptor/key.rs

+83-48
Original file line numberDiff line numberDiff line change
@@ -447,66 +447,101 @@ fn fmt_derivation_paths(f: &mut fmt::Formatter, paths: &[bip32::DerivationPath])
447447
Ok(())
448448
}
449449

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

453488
fn from_str(s: &str) -> Result<Self, Self::Err> {
454-
// A "raw" public key without any origin is the least we accept.
455-
if s.len() < 64 {
489+
let (key_part, origin) = parse_key_origin(s)?;
490+
491+
let (xpub, derivation_paths, wildcard) =
492+
parse_xkey_deriv::<bip32::ExtendedPubKey>(key_part)?;
493+
494+
if derivation_paths.len() > 1 {
456495
return Err(DescriptorKeyParseError(
457-
"Key too short (<66 char), doesn't match any format",
496+
"Multiple derivation paths are not allowed for single extended keys",
458497
));
459498
}
460499

500+
Ok(Self {
501+
origin,
502+
xkey: xpub,
503+
derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
504+
wildcard,
505+
})
506+
}
507+
}
508+
509+
impl FromStr for DescriptorMultiExtendedPublicKey {
510+
type Err = DescriptorKeyParseError;
511+
512+
fn from_str(s: &str) -> Result<Self, Self::Err> {
461513
let (key_part, origin) = parse_key_origin(s)?;
462514

463-
if key_part.contains("pub") {
464-
let (xpub, derivation_paths, wildcard) =
465-
parse_xkey_deriv::<bip32::ExtendedPubKey>(key_part)?;
466-
if derivation_paths.len() > 1 {
467-
Ok(DescriptorPublicKey::MultiXPub(DescriptorMultiXKey {
468-
origin,
469-
xkey: xpub,
470-
derivation_paths: DerivPaths::new(derivation_paths).expect("Not empty"),
471-
wildcard,
472-
}))
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+
533+
impl FromStr for DescriptorPublicKey {
534+
type Err = DescriptorKeyParseError;
535+
536+
fn from_str(s: &str) -> Result<Self, Self::Err> {
537+
if s.contains("pub") {
538+
if s.contains("<") {
539+
DescriptorMultiExtendedPublicKey::from_str(s).map(Self::MultiXPub)
473540
} else {
474-
Ok(DescriptorPublicKey::XPub(DescriptorXKey {
475-
origin,
476-
xkey: xpub,
477-
derivation_path: derivation_paths.into_iter().next().unwrap_or_default(),
478-
wildcard,
479-
}))
541+
DescriptorExtendedPublicKey::from_str(s).map(Self::XPub)
480542
}
481543
} else {
482-
let key = match key_part.len() {
483-
64 => {
484-
let x_only_key = XOnlyPublicKey::from_str(key_part).map_err(|_| {
485-
DescriptorKeyParseError("Error while parsing simple xonly key")
486-
})?;
487-
SinglePubKey::XOnly(x_only_key)
488-
}
489-
66 | 130 => {
490-
if !(&key_part[0..2] == "02"
491-
|| &key_part[0..2] == "03"
492-
|| &key_part[0..2] == "04")
493-
{
494-
return Err(DescriptorKeyParseError(
495-
"Only publickeys with prefixes 02/03/04 are allowed",
496-
));
497-
}
498-
let key = bitcoin::PublicKey::from_str(key_part).map_err(|_| {
499-
DescriptorKeyParseError("Error while parsing simple public key")
500-
})?;
501-
SinglePubKey::FullKey(key)
502-
}
503-
_ => {
504-
return Err(DescriptorKeyParseError(
505-
"Public keys must be 64/66/130 characters in size",
506-
))
507-
}
508-
};
509-
Ok(DescriptorPublicKey::Single(SinglePub { key, origin }))
544+
DescriptorSinglePublicKey::from_str(s).map(Self::Single)
510545
}
511546
}
512547
}

0 commit comments

Comments
 (0)