Skip to content

Commit c9e6b53

Browse files
committed
Merge #475: Fix unreachable code from calling derive_public_key
c14d1ce Fix unreachable code from calling derive_public_key (sanket1729) Pull request description: DescriptorPublicKey::derive_public_key API hit an unreachable line when executing. public_key.derive_public_key(&secp).unwrap_err(); This commit removes the API altogether and only exposes the method via `DefiniteDescriptorKey`. Unfortunately, non-wildcard users would need to pass a dummy value to .at_derivation_index to get this struct, but I think this is okay. ACKs for top commit: apoelstra: ACK c14d1ce Tree-SHA512: e1372bf40aebe2a60ec85041776a12dd75d32443873c85ef2f46e12bb55e39538c3795062fb6fe04a1793d5aebfe504be5cf82284d43bd49abf29b30d586da0a
2 parents 72dab64 + c14d1ce commit c9e6b53

File tree

1 file changed

+27
-40
lines changed

1 file changed

+27
-40
lines changed

src/descriptor/key.rs

+27-40
Original file line numberDiff line numberDiff line change
@@ -485,39 +485,6 @@ impl DescriptorPublicKey {
485485
DefiniteDescriptorKey::new(definite)
486486
.expect("The key should not contain any wildcards at this point")
487487
}
488-
489-
/// Computes the public key corresponding to this descriptor key.
490-
/// When deriving from an XOnlyPublicKey, it adds the default 0x02 y-coordinate
491-
/// and returns the obtained full [`bitcoin::PublicKey`]. All BIP32 derivations
492-
/// always return a compressed key
493-
///
494-
/// Will return an error if the descriptor key has any hardened derivation steps in its path. To
495-
/// avoid this error you should replace any such public keys first with [`translate_pk`].
496-
///
497-
/// [`translate_pk`]: crate::TranslatePk::translate_pk
498-
pub fn derive_public_key<C: Verification>(
499-
&self,
500-
secp: &Secp256k1<C>,
501-
) -> Result<bitcoin::PublicKey, ConversionError> {
502-
match *self {
503-
DescriptorPublicKey::Single(ref pk) => match pk.key {
504-
SinglePubKey::FullKey(pk) => Ok(pk),
505-
SinglePubKey::XOnly(xpk) => Ok(xpk.to_public_key()),
506-
},
507-
DescriptorPublicKey::XPub(ref xpk) => match xpk.wildcard {
508-
Wildcard::Unhardened | Wildcard::Hardened => {
509-
unreachable!("we've excluded this error case")
510-
}
511-
Wildcard::None => match xpk.xkey.derive_pub(secp, &xpk.derivation_path.as_ref()) {
512-
Ok(xpub) => Ok(bitcoin::PublicKey::new(xpub.public_key)),
513-
Err(bip32::Error::CannotDeriveFromHardenedKey) => {
514-
Err(ConversionError::HardenedChild)
515-
}
516-
Err(e) => unreachable!("cryptographically unreachable: {}", e),
517-
},
518-
},
519-
}
520-
}
521488
}
522489

523490
impl FromStr for DescriptorSecretKey {
@@ -757,17 +724,37 @@ impl MiniscriptKey for DescriptorPublicKey {
757724
}
758725

759726
impl DefiniteDescriptorKey {
760-
/// Computes the raw [`bitcoin::PublicKey`] for this descriptor key.
727+
/// Computes the public key corresponding to this descriptor key.
728+
/// When deriving from an XOnlyPublicKey, it adds the default 0x02 y-coordinate
729+
/// and returns the obtained full [`bitcoin::PublicKey`]. All BIP32 derivations
730+
/// always return a compressed key
761731
///
762-
/// Will return an error if the key has any hardened derivation steps
763-
/// in its path, but unlike [`DescriptorPublicKey::derive_public_key`]
764-
/// this won't error in case of wildcards, because derived keys are
765-
/// guaranteed to never contain one.
732+
/// Will return an error if the descriptor key has any hardened derivation steps in its path. To
733+
/// avoid this error you should replace any such public keys first with [`translate_pk`].
734+
///
735+
/// [`translate_pk`]: crate::TranslatePk::translate_pk
766736
pub fn derive_public_key<C: Verification>(
767737
&self,
768738
secp: &Secp256k1<C>,
769739
) -> Result<bitcoin::PublicKey, ConversionError> {
770-
self.0.derive_public_key(secp)
740+
match self.0 {
741+
DescriptorPublicKey::Single(ref pk) => match pk.key {
742+
SinglePubKey::FullKey(pk) => Ok(pk),
743+
SinglePubKey::XOnly(xpk) => Ok(xpk.to_public_key()),
744+
},
745+
DescriptorPublicKey::XPub(ref xpk) => match xpk.wildcard {
746+
Wildcard::Unhardened | Wildcard::Hardened => {
747+
unreachable!("we've excluded this error case")
748+
}
749+
Wildcard::None => match xpk.xkey.derive_pub(secp, &xpk.derivation_path.as_ref()) {
750+
Ok(xpub) => Ok(bitcoin::PublicKey::new(xpub.public_key)),
751+
Err(bip32::Error::CannotDeriveFromHardenedKey) => {
752+
Err(ConversionError::HardenedChild)
753+
}
754+
Err(e) => unreachable!("cryptographically unreachable: {}", e),
755+
},
756+
},
757+
}
771758
}
772759

773760
/// Construct an instance from a descriptor key and a derivation index
@@ -829,7 +816,7 @@ impl MiniscriptKey for DefiniteDescriptorKey {
829816
impl ToPublicKey for DefiniteDescriptorKey {
830817
fn to_public_key(&self) -> bitcoin::PublicKey {
831818
let secp = Secp256k1::verification_only();
832-
self.0.derive_public_key(&secp).unwrap()
819+
self.derive_public_key(&secp).unwrap()
833820
}
834821

835822
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {

0 commit comments

Comments
 (0)