Skip to content

Fix unreachable code from calling derive_public_key #475

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 19, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 27 additions & 40 deletions src/descriptor/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,39 +485,6 @@ impl DescriptorPublicKey {
DefiniteDescriptorKey::new(definite)
.expect("The key should not contain any wildcards at this point")
}

/// Computes the public key corresponding to this descriptor key.
/// When deriving from an XOnlyPublicKey, it adds the default 0x02 y-coordinate
/// and returns the obtained full [`bitcoin::PublicKey`]. All BIP32 derivations
/// always return a compressed key
///
/// Will return an error if the descriptor key has any hardened derivation steps in its path. To
/// avoid this error you should replace any such public keys first with [`translate_pk`].
///
/// [`translate_pk`]: crate::TranslatePk::translate_pk
pub fn derive_public_key<C: Verification>(
&self,
secp: &Secp256k1<C>,
) -> Result<bitcoin::PublicKey, ConversionError> {
match *self {
DescriptorPublicKey::Single(ref pk) => match pk.key {
SinglePubKey::FullKey(pk) => Ok(pk),
SinglePubKey::XOnly(xpk) => Ok(xpk.to_public_key()),
},
DescriptorPublicKey::XPub(ref xpk) => match xpk.wildcard {
Wildcard::Unhardened | Wildcard::Hardened => {
unreachable!("we've excluded this error case")
}
Wildcard::None => match xpk.xkey.derive_pub(secp, &xpk.derivation_path.as_ref()) {
Ok(xpub) => Ok(bitcoin::PublicKey::new(xpub.public_key)),
Err(bip32::Error::CannotDeriveFromHardenedKey) => {
Err(ConversionError::HardenedChild)
}
Err(e) => unreachable!("cryptographically unreachable: {}", e),
},
},
}
}
}

impl FromStr for DescriptorSecretKey {
Expand Down Expand Up @@ -757,17 +724,37 @@ impl MiniscriptKey for DescriptorPublicKey {
}

impl DefiniteDescriptorKey {
/// Computes the raw [`bitcoin::PublicKey`] for this descriptor key.
/// Computes the public key corresponding to this descriptor key.
/// When deriving from an XOnlyPublicKey, it adds the default 0x02 y-coordinate
/// and returns the obtained full [`bitcoin::PublicKey`]. All BIP32 derivations
/// always return a compressed key
///
/// Will return an error if the key has any hardened derivation steps
/// in its path, but unlike [`DescriptorPublicKey::derive_public_key`]
/// this won't error in case of wildcards, because derived keys are
/// guaranteed to never contain one.
/// Will return an error if the descriptor key has any hardened derivation steps in its path. To
/// avoid this error you should replace any such public keys first with [`translate_pk`].
///
/// [`translate_pk`]: crate::TranslatePk::translate_pk
pub fn derive_public_key<C: Verification>(
&self,
secp: &Secp256k1<C>,
) -> Result<bitcoin::PublicKey, ConversionError> {
self.0.derive_public_key(secp)
match self.0 {
DescriptorPublicKey::Single(ref pk) => match pk.key {
SinglePubKey::FullKey(pk) => Ok(pk),
SinglePubKey::XOnly(xpk) => Ok(xpk.to_public_key()),
},
DescriptorPublicKey::XPub(ref xpk) => match xpk.wildcard {
Wildcard::Unhardened | Wildcard::Hardened => {
unreachable!("we've excluded this error case")
}
Wildcard::None => match xpk.xkey.derive_pub(secp, &xpk.derivation_path.as_ref()) {
Ok(xpub) => Ok(bitcoin::PublicKey::new(xpub.public_key)),
Err(bip32::Error::CannotDeriveFromHardenedKey) => {
Err(ConversionError::HardenedChild)
}
Err(e) => unreachable!("cryptographically unreachable: {}", e),
},
},
}
}

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

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