Skip to content

Commit

Permalink
BIP32 extended key to_ecdsa() and to_schnorr() methods
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Aug 1, 2021
1 parent 908b4c6 commit 7c565ec
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 8 deletions.
2 changes: 1 addition & 1 deletion examples/bip32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn main() {
let path = DerivationPath::from_str("m/84h/0h/0h").unwrap();
let child = root.derive_priv(&secp, &path).unwrap();
println!("Child at {}: {}", path, child);
let xpub = ExtendedPubKey::from_private(&secp, &child);
let xpub = ExtendedPubKey::from_priv(&secp, &child);
println!("Public key at {}: {}", path, xpub);

// generate first receiving address at m/0/0
Expand Down
41 changes: 35 additions & 6 deletions src/util/bip32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use secp256k1::{self, Secp256k1};

use network::constants::Network;
use util::{base58, endian};
use util::key;
use util::{key, ecdsa, schnorr};
use io::Write;

/// A chain code
Expand Down Expand Up @@ -507,6 +507,21 @@ impl ExtendedPrivKey {
})
}

/// Constructs ECDSA compressed private key matching internal secret key representation.
pub fn to_ecdsa_priv(&self) -> ecdsa::PrivateKey {
ecdsa::PrivateKey {
compressed: true,
network: self.network,
key: self.private_key
}
}

/// Constructs BIP340 keypair for Schnorr signatures and Taproot use matching the internal
/// secret key representation.
pub fn to_schnorr_keypair<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> schnorr::KeyPair {
schnorr::KeyPair::from_seckey_slice(secp, &self.private_key[..]).expect("BIP32 internal private key representation is broken")
}

/// Attempts to derive an extended private key from a path.
///
/// The `path` argument can be both of type `DerivationPath` or `Vec<ChildNumber>`.
Expand Down Expand Up @@ -596,7 +611,7 @@ impl ExtendedPrivKey {

/// Returns the HASH160 of the public key belonging to the xpriv
pub fn identifier<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> XpubIdentifier {
ExtendedPubKey::from_private(secp, self).identifier()
ExtendedPubKey::from_priv(secp, self).identifier()
}

/// Returns the first four bytes of the identifier
Expand All @@ -607,7 +622,7 @@ impl ExtendedPrivKey {

impl ExtendedPubKey {
/// Derives a public key from a private key
pub fn from_private<C: secp256k1::Signing>(secp: &Secp256k1<C>, sk: &ExtendedPrivKey) -> ExtendedPubKey {
pub fn from_priv<C: secp256k1::Signing>(secp: &Secp256k1<C>, sk: &ExtendedPrivKey) -> ExtendedPubKey {
ExtendedPubKey {
network: sk.network,
depth: sk.depth,
Expand All @@ -618,6 +633,20 @@ impl ExtendedPubKey {
}
}

/// Constructs ECDSA compressed public key matching internal public key representation.
pub fn to_ecdsa_pub(&self) -> ecdsa::PublicKey {
ecdsa::PublicKey {
compressed: true,
key: self.public_key
}
}

/// Constructs BIP340 x-only public key for BIP-340 signatures and Taproot use matching
/// the internal public key representation.
pub fn to_schnorr_pub(&self) -> schnorr::PublicKey {
schnorr::PublicKey::from(self.public_key)
}

/// Attempts to derive an extended public key from a path.
///
/// The `path` argument can be both of type `DerivationPath` or `Vec<ChildNumber>`.
Expand Down Expand Up @@ -849,7 +878,7 @@ mod tests {
expected_pk: &str) {

let mut sk = ExtendedPrivKey::new_master(network, seed).unwrap();
let mut pk = ExtendedPubKey::from_private(secp, &sk);
let mut pk = ExtendedPubKey::from_priv(secp, &sk);

// Check derivation convenience method for ExtendedPrivKey
assert_eq!(
Expand Down Expand Up @@ -877,15 +906,15 @@ mod tests {
match num {
Normal {..} => {
let pk2 = pk.ckd_pub(secp, num).unwrap();
pk = ExtendedPubKey::from_private(secp, &sk);
pk = ExtendedPubKey::from_priv(secp, &sk);
assert_eq!(pk, pk2);
}
Hardened {..} => {
assert_eq!(
pk.ckd_pub(secp, num),
Err(Error::CannotDeriveFromHardenedKey)
);
pk = ExtendedPubKey::from_private(secp, &sk);
pk = ExtendedPubKey::from_priv(secp, &sk);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/util/psbt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ mod tests {

sk = sk.derive_priv(secp, &dpath).unwrap();

let pk: ExtendedPubKey = ExtendedPubKey::from_private(&secp, &sk);
let pk: ExtendedPubKey = ExtendedPubKey::from_priv(&secp, &sk);

hd_keypaths.insert(pk.public_key, (fprint, dpath.into()));

Expand Down

0 comments on commit 7c565ec

Please sign in to comment.