Merge rust-bitcoin/rust-bitcoin#1208: Move bip32 module to crate root

8bed2ddffe Run formmater on bip32 (Tobin C. Harding)
34113c9558 Move bip32 module to crate root (Tobin C. Harding)

Pull request description:

  We are attempting to flatten the `util` module.

  Move the `bip32` module to the crate root out of `util`.

  Currently `src/util/` is ignored by the formatter so this move requires `bip32` module to be formatted. Formatting is done as a separate patch so reviewers can run `cargo +nightly fmt` and compare the diffs if so desired.

ACKs for top commit:
  apoelstra:
    ACK 8bed2ddffe
  Kixunil:
    ACK 8bed2ddffe

Tree-SHA512: dadea31be0459fd10e71927bd21dc44b59428f695a6df7093052ca7257b6590d5dd5b1343a89869ac9f4d7805dbca7558b475048ea9387c36265f14246cc6852
This commit is contained in:
Andrew Poelstra 2022-09-21 16:45:42 +00:00
commit b1869803bf
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
3 changed files with 147 additions and 158 deletions

View File

@ -7,22 +7,24 @@
//! at <https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki>. //! at <https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki>.
//! //!
use crate::prelude::*; use core::default::Default;
use core::fmt;
use crate::io::Write;
use core::{fmt, str::FromStr, default::Default};
use core::ops::Index; use core::ops::Index;
#[cfg(feature = "serde")] use serde; use core::str::FromStr;
use bitcoin_internals::write_err; use bitcoin_internals::write_err;
use crate::hash_types::XpubIdentifier;
use crate::hashes::{sha512, Hash, HashEngine, Hmac, HmacEngine, hex};
use secp256k1::{self, Secp256k1, XOnlyPublicKey}; use secp256k1::{self, Secp256k1, XOnlyPublicKey};
#[cfg(feature = "serde")]
use serde;
use crate::network::constants::Network; use crate::hash_types::XpubIdentifier;
use crate::util::{base58, endian, key}; use crate::hashes::{hex, sha512, Hash, HashEngine, Hmac, HmacEngine};
use crate::util::key::{PublicKey, PrivateKey, KeyPair};
use crate::internal_macros::{impl_array_newtype, impl_bytes_newtype, serde_string_impl}; use crate::internal_macros::{impl_array_newtype, impl_bytes_newtype, serde_string_impl};
use crate::io::Write;
use crate::network::constants::Network;
use crate::prelude::*;
use crate::util::key::{KeyPair, PrivateKey, PublicKey};
use crate::util::{base58, endian, key};
/// A chain code /// A chain code
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -51,7 +53,7 @@ pub struct ExtendedPrivKey {
/// Private key /// Private key
pub private_key: secp256k1::SecretKey, pub private_key: secp256k1::SecretKey,
/// Chain code /// Chain code
pub chain_code: ChainCode pub chain_code: ChainCode,
} }
serde_string_impl!(ExtendedPrivKey, "a BIP-32 extended private key"); serde_string_impl!(ExtendedPrivKey, "a BIP-32 extended private key");
@ -84,7 +86,7 @@ pub struct ExtendedPubKey {
/// Public key /// Public key
pub public_key: secp256k1::PublicKey, pub public_key: secp256k1::PublicKey,
/// Chain code /// Chain code
pub chain_code: ChainCode pub chain_code: ChainCode,
} }
serde_string_impl!(ExtendedPubKey, "a BIP-32 extended public key"); serde_string_impl!(ExtendedPubKey, "a BIP-32 extended public key");
@ -94,12 +96,12 @@ pub enum ChildNumber {
/// Non-hardened key /// Non-hardened key
Normal { Normal {
/// Key index, within [0, 2^31 - 1] /// Key index, within [0, 2^31 - 1]
index: u32 index: u32,
}, },
/// Hardened key /// Hardened key
Hardened { Hardened {
/// Key index, within [0, 2^31 - 1] /// Key index, within [0, 2^31 - 1]
index: u32 index: u32,
}, },
} }
@ -131,25 +133,23 @@ impl ChildNumber {
/// Returns `true` if the child number is a [`Normal`] value. /// Returns `true` if the child number is a [`Normal`] value.
/// ///
/// [`Normal`]: #variant.Normal /// [`Normal`]: #variant.Normal
pub fn is_normal(&self) -> bool { pub fn is_normal(&self) -> bool { !self.is_hardened() }
!self.is_hardened()
}
/// Returns `true` if the child number is a [`Hardened`] value. /// Returns `true` if the child number is a [`Hardened`] value.
/// ///
/// [`Hardened`]: #variant.Hardened /// [`Hardened`]: #variant.Hardened
pub fn is_hardened(&self) -> bool { pub fn is_hardened(&self) -> bool {
match self { match self {
ChildNumber::Hardened {..} => true, ChildNumber::Hardened { .. } => true,
ChildNumber::Normal {..} => false, ChildNumber::Normal { .. } => false,
} }
} }
/// Returns the child number that is a single increment from this one. /// Returns the child number that is a single increment from this one.
pub fn increment(self) -> Result<ChildNumber, Error> { pub fn increment(self) -> Result<ChildNumber, Error> {
match self { match self {
ChildNumber::Normal{ index: idx } => ChildNumber::from_normal_idx(idx+1), ChildNumber::Normal { index: idx } => ChildNumber::from_normal_idx(idx + 1),
ChildNumber::Hardened{ index: idx } => ChildNumber::from_hardened_idx(idx+1), ChildNumber::Hardened { index: idx } => ChildNumber::from_hardened_idx(idx + 1),
} }
} }
} }
@ -180,7 +180,7 @@ impl fmt::Display for ChildNumber {
fmt::Display::fmt(&index, f)?; fmt::Display::fmt(&index, f)?;
let alt = f.alternate(); let alt = f.alternate();
f.write_str(if alt { "h" } else { "'" }) f.write_str(if alt { "h" } else { "'" })
}, }
ChildNumber::Normal { index } => fmt::Display::fmt(&index, f), ChildNumber::Normal { index } => fmt::Display::fmt(&index, f),
} }
} }
@ -192,7 +192,9 @@ impl FromStr for ChildNumber {
fn from_str(inp: &str) -> Result<ChildNumber, Error> { fn from_str(inp: &str) -> Result<ChildNumber, Error> {
let is_hardened = inp.chars().last().map_or(false, |l| l == '\'' || l == 'h'); let is_hardened = inp.chars().last().map_or(false, |l| l == '\'' || l == 'h');
Ok(if is_hardened { Ok(if is_hardened {
ChildNumber::from_hardened_idx(inp[0..inp.len() - 1].parse().map_err(|_| Error::InvalidChildNumberFormat)?)? ChildNumber::from_hardened_idx(
inp[0..inp.len() - 1].parse().map_err(|_| Error::InvalidChildNumberFormat)?,
)?
} else { } else {
ChildNumber::from_normal_idx(inp.parse().map_err(|_| Error::InvalidChildNumberFormat)?)? ChildNumber::from_normal_idx(inp.parse().map_err(|_| Error::InvalidChildNumberFormat)?)?
}) })
@ -240,55 +242,45 @@ where
type Output = <Vec<ChildNumber> as Index<I>>::Output; type Output = <Vec<ChildNumber> as Index<I>>::Output;
#[inline] #[inline]
fn index(&self, index: I) -> &Self::Output { fn index(&self, index: I) -> &Self::Output { &self.0[index] }
&self.0[index]
}
} }
impl Default for DerivationPath { impl Default for DerivationPath {
fn default() -> DerivationPath { fn default() -> DerivationPath { DerivationPath::master() }
DerivationPath::master()
}
} }
impl<T> IntoDerivationPath for T where T: Into<DerivationPath> { impl<T> IntoDerivationPath for T
fn into_derivation_path(self) -> Result<DerivationPath, Error> { where
Ok(self.into()) T: Into<DerivationPath>,
} {
fn into_derivation_path(self) -> Result<DerivationPath, Error> { Ok(self.into()) }
} }
impl IntoDerivationPath for String { impl IntoDerivationPath for String {
fn into_derivation_path(self) -> Result<DerivationPath, Error> { fn into_derivation_path(self) -> Result<DerivationPath, Error> { self.parse() }
self.parse()
}
} }
impl<'a> IntoDerivationPath for &'a str { impl<'a> IntoDerivationPath for &'a str {
fn into_derivation_path(self) -> Result<DerivationPath, Error> { fn into_derivation_path(self) -> Result<DerivationPath, Error> { self.parse() }
self.parse()
}
} }
impl From<Vec<ChildNumber>> for DerivationPath { impl From<Vec<ChildNumber>> for DerivationPath {
fn from(numbers: Vec<ChildNumber>) -> Self { fn from(numbers: Vec<ChildNumber>) -> Self { DerivationPath(numbers) }
DerivationPath(numbers)
}
} }
impl From<DerivationPath> for Vec<ChildNumber> { impl From<DerivationPath> for Vec<ChildNumber> {
fn from(path: DerivationPath) -> Self { fn from(path: DerivationPath) -> Self { path.0 }
path.0
}
} }
impl<'a> From<&'a [ChildNumber]> for DerivationPath { impl<'a> From<&'a [ChildNumber]> for DerivationPath {
fn from(numbers: &'a [ChildNumber]) -> Self { fn from(numbers: &'a [ChildNumber]) -> Self { DerivationPath(numbers.to_vec()) }
DerivationPath(numbers.to_vec())
}
} }
impl core::iter::FromIterator<ChildNumber> for DerivationPath { impl core::iter::FromIterator<ChildNumber> for DerivationPath {
fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item=ChildNumber> { fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = ChildNumber>,
{
DerivationPath(Vec::from_iter(iter)) DerivationPath(Vec::from_iter(iter))
} }
} }
@ -296,15 +288,11 @@ impl core::iter::FromIterator<ChildNumber> for DerivationPath {
impl<'a> core::iter::IntoIterator for &'a DerivationPath { impl<'a> core::iter::IntoIterator for &'a DerivationPath {
type Item = &'a ChildNumber; type Item = &'a ChildNumber;
type IntoIter = slice::Iter<'a, ChildNumber>; type IntoIter = slice::Iter<'a, ChildNumber>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter { self.0.iter() }
self.0.iter()
}
} }
impl AsRef<[ChildNumber]> for DerivationPath { impl AsRef<[ChildNumber]> for DerivationPath {
fn as_ref(&self) -> &[ChildNumber] { fn as_ref(&self) -> &[ChildNumber] { &self.0 }
&self.0
}
} }
impl FromStr for DerivationPath { impl FromStr for DerivationPath {
@ -334,10 +322,7 @@ pub struct DerivationPathIterator<'a> {
impl<'a> DerivationPathIterator<'a> { impl<'a> DerivationPathIterator<'a> {
/// Start a new [DerivationPathIterator] at the given child. /// Start a new [DerivationPathIterator] at the given child.
pub fn start_from(path: &'a DerivationPath, start: ChildNumber) -> DerivationPathIterator<'a> { pub fn start_from(path: &'a DerivationPath, start: ChildNumber) -> DerivationPathIterator<'a> {
DerivationPathIterator { DerivationPathIterator { base: path, next_child: Some(start) }
base: path,
next_child: Some(start),
}
} }
} }
@ -353,25 +338,17 @@ impl<'a> Iterator for DerivationPathIterator<'a> {
impl DerivationPath { impl DerivationPath {
/// Returns length of the derivation path /// Returns length of the derivation path
pub fn len(&self) -> usize { pub fn len(&self) -> usize { self.0.len() }
self.0.len()
}
/// Returns `true` if the derivation path is empty /// Returns `true` if the derivation path is empty
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool { self.0.is_empty() }
self.0.is_empty()
}
/// Returns derivation path for a master key (i.e. empty derivation path) /// Returns derivation path for a master key (i.e. empty derivation path)
pub fn master() -> DerivationPath { pub fn master() -> DerivationPath { DerivationPath(vec![]) }
DerivationPath(vec![])
}
/// Returns whether derivation path represents master key (i.e. it's length /// Returns whether derivation path represents master key (i.e. it's length
/// is empty). True for `m` path. /// is empty). True for `m` path.
pub fn is_master(&self) -> bool { pub fn is_master(&self) -> bool { self.0.is_empty() }
self.0.is_empty()
}
/// Create a new [DerivationPath] that is a child of this one. /// Create a new [DerivationPath] that is a child of this one.
pub fn child(&self, cn: ChildNumber) -> DerivationPath { pub fn child(&self, cn: ChildNumber) -> DerivationPath {
@ -395,12 +372,12 @@ impl DerivationPath {
/// Get an [Iterator] over the unhardened children of this [DerivationPath]. /// Get an [Iterator] over the unhardened children of this [DerivationPath].
pub fn normal_children(&self) -> DerivationPathIterator { pub fn normal_children(&self) -> DerivationPathIterator {
DerivationPathIterator::start_from(self, ChildNumber::Normal{ index: 0 }) DerivationPathIterator::start_from(self, ChildNumber::Normal { index: 0 })
} }
/// Get an [Iterator] over the hardened children of this [DerivationPath]. /// Get an [Iterator] over the hardened children of this [DerivationPath].
pub fn hardened_children(&self) -> DerivationPathIterator { pub fn hardened_children(&self) -> DerivationPathIterator {
DerivationPathIterator::start_from(self, ChildNumber::Hardened{ index: 0 }) DerivationPathIterator::start_from(self, ChildNumber::Hardened { index: 0 })
} }
/// Concatenate `self` with `path` and return the resulting new path. /// Concatenate `self` with `path` and return the resulting new path.
@ -438,9 +415,7 @@ impl fmt::Display for DerivationPath {
} }
impl fmt::Debug for DerivationPath { impl fmt::Debug for DerivationPath {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self, f) }
fmt::Display::fmt(&self, f)
}
} }
/// Full information on the used extended public key: fingerprint of the /// Full information on the used extended public key: fingerprint of the
@ -468,19 +443,23 @@ pub enum Error {
/// Base58 encoding error /// Base58 encoding error
Base58(base58::Error), Base58(base58::Error),
/// Hexadecimal decoding error /// Hexadecimal decoding error
Hex(hex::Error) Hex(hex::Error),
} }
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
Error::CannotDeriveFromHardenedKey => f.write_str("cannot derive hardened key from public key"), Error::CannotDeriveFromHardenedKey =>
f.write_str("cannot derive hardened key from public key"),
Error::Secp256k1(ref e) => write_err!(f, "secp256k1 error"; e), Error::Secp256k1(ref e) => write_err!(f, "secp256k1 error"; e),
Error::InvalidChildNumber(ref n) => write!(f, "child number {} is invalid (not within [0, 2^31 - 1])", n), Error::InvalidChildNumber(ref n) =>
write!(f, "child number {} is invalid (not within [0, 2^31 - 1])", n),
Error::InvalidChildNumberFormat => f.write_str("invalid child number format"), Error::InvalidChildNumberFormat => f.write_str("invalid child number format"),
Error::InvalidDerivationPathFormat => f.write_str("invalid derivation path format"), Error::InvalidDerivationPathFormat => f.write_str("invalid derivation path format"),
Error::UnknownVersion(ref bytes) => write!(f, "unknown version magic bytes: {:?}", bytes), Error::UnknownVersion(ref bytes) =>
Error::WrongExtendedKeyLength(ref len) => write!(f, "encoded extended key data has wrong length {}", len), write!(f, "unknown version magic bytes: {:?}", bytes),
Error::WrongExtendedKeyLength(ref len) =>
write!(f, "encoded extended key data has wrong length {}", len),
Error::Base58(ref e) => write_err!(f, "base58 encoding error"; e), Error::Base58(ref e) => write_err!(f, "base58 encoding error"; e),
Error::Hex(ref e) => write_err!(f, "Hexadecimal decoding error"; e), Error::Hex(ref e) => write_err!(f, "Hexadecimal decoding error"; e),
} }
@ -513,7 +492,7 @@ impl From<key::Error> for Error {
key::Error::Base58(e) => Error::Base58(e), key::Error::Base58(e) => Error::Base58(e),
key::Error::Secp256k1(e) => Error::Secp256k1(e), key::Error::Secp256k1(e) => Error::Secp256k1(e),
key::Error::InvalidKeyPrefix(_) => Error::Secp256k1(secp256k1::Error::InvalidPublicKey), key::Error::InvalidKeyPrefix(_) => Error::Secp256k1(secp256k1::Error::InvalidPublicKey),
key::Error::Hex(e) => Error::Hex(e) key::Error::Hex(e) => Error::Hex(e),
} }
} }
} }
@ -523,9 +502,7 @@ impl From<secp256k1::Error> for Error {
} }
impl From<base58::Error> for Error { impl From<base58::Error> for Error {
fn from(err: base58::Error) -> Self { fn from(err: base58::Error) -> Self { Error::Base58(err) }
Error::Base58(err)
}
} }
impl ExtendedPrivKey { impl ExtendedPrivKey {
@ -547,17 +524,14 @@ impl ExtendedPrivKey {
/// Constructs ECDSA compressed private key matching internal secret key representation. /// Constructs ECDSA compressed private key matching internal secret key representation.
pub fn to_priv(self) -> PrivateKey { pub fn to_priv(self) -> PrivateKey {
PrivateKey { PrivateKey { compressed: true, network: self.network, inner: self.private_key }
compressed: true,
network: self.network,
inner: self.private_key
}
} }
/// Constructs BIP340 keypair for Schnorr signatures and Taproot use matching the internal /// Constructs BIP340 keypair for Schnorr signatures and Taproot use matching the internal
/// secret key representation. /// secret key representation.
pub fn to_keypair<C: secp256k1::Signing>(self, secp: &Secp256k1<C>) -> KeyPair { pub fn to_keypair<C: secp256k1::Signing>(self, secp: &Secp256k1<C>) -> KeyPair {
KeyPair::from_seckey_slice(secp, &self.private_key[..]).expect("BIP32 internal private key representation is broken") 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. /// Attempts to derive an extended private key from a path.
@ -576,12 +550,18 @@ impl ExtendedPrivKey {
} }
/// Private->Private child key derivation /// Private->Private child key derivation
pub fn ckd_priv<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>, i: ChildNumber) -> Result<ExtendedPrivKey, Error> { pub fn ckd_priv<C: secp256k1::Signing>(
&self,
secp: &Secp256k1<C>,
i: ChildNumber,
) -> Result<ExtendedPrivKey, Error> {
let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]); let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]);
match i { match i {
ChildNumber::Normal { .. } => { ChildNumber::Normal { .. } => {
// Non-hardened key: compute public data and use that // Non-hardened key: compute public data and use that
hmac_engine.input(&secp256k1::PublicKey::from_secret_key(secp, &self.private_key).serialize()[..]); hmac_engine.input(
&secp256k1::PublicKey::from_secret_key(secp, &self.private_key).serialize()[..],
);
} }
ChildNumber::Hardened { .. } => { ChildNumber::Hardened { .. } => {
// Hardened key: use only secret data to prevent public derivation // Hardened key: use only secret data to prevent public derivation
@ -592,8 +572,10 @@ impl ExtendedPrivKey {
hmac_engine.input(&endian::u32_to_array_be(u32::from(i))); hmac_engine.input(&endian::u32_to_array_be(u32::from(i)));
let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine); let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
let sk = secp256k1::SecretKey::from_slice(&hmac_result[..32]).expect("statistically impossible to hit"); let sk = secp256k1::SecretKey::from_slice(&hmac_result[..32])
let tweaked = sk.add_tweak(&self.private_key.into()).expect("statistically impossible to hit"); .expect("statistically impossible to hit");
let tweaked =
sk.add_tweak(&self.private_key.into()).expect("statistically impossible to hit");
Ok(ExtendedPrivKey { Ok(ExtendedPrivKey {
network: self.network, network: self.network,
@ -601,14 +583,14 @@ impl ExtendedPrivKey {
parent_fingerprint: self.fingerprint(secp), parent_fingerprint: self.fingerprint(secp),
child_number: i, child_number: i,
private_key: tweaked, private_key: tweaked,
chain_code: ChainCode::from(&hmac_result[32..]) chain_code: ChainCode::from(&hmac_result[32..]),
}) })
} }
/// Decoding extended private key from binary data according to BIP 32 /// Decoding extended private key from binary data according to BIP 32
pub fn decode(data: &[u8]) -> Result<ExtendedPrivKey, Error> { pub fn decode(data: &[u8]) -> Result<ExtendedPrivKey, Error> {
if data.len() != 78 { if data.len() != 78 {
return Err(Error::WrongExtendedKeyLength(data.len())) return Err(Error::WrongExtendedKeyLength(data.len()));
} }
let network = if data[0..4] == [0x04u8, 0x88, 0xAD, 0xE4] { let network = if data[0..4] == [0x04u8, 0x88, 0xAD, 0xE4] {
@ -634,10 +616,12 @@ impl ExtendedPrivKey {
/// Extended private key binary encoding according to BIP 32 /// Extended private key binary encoding according to BIP 32
pub fn encode(&self) -> [u8; 78] { pub fn encode(&self) -> [u8; 78] {
let mut ret = [0; 78]; let mut ret = [0; 78];
ret[0..4].copy_from_slice(&match self.network { ret[0..4].copy_from_slice(
&match self.network {
Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4], Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4],
Network::Testnet | Network::Signet | Network::Regtest => [0x04, 0x35, 0x83, 0x94], Network::Testnet | Network::Signet | Network::Regtest => [0x04, 0x35, 0x83, 0x94],
}[..]); }[..],
);
ret[4] = self.depth as u8; ret[4] = self.depth as u8;
ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); ret[5..9].copy_from_slice(&self.parent_fingerprint[..]);
ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number))); ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number)));
@ -660,30 +644,26 @@ impl ExtendedPrivKey {
impl ExtendedPubKey { impl ExtendedPubKey {
/// Derives a public key from a private key /// Derives a public key from a private key
pub fn from_priv<C: secp256k1::Signing>(secp: &Secp256k1<C>, sk: &ExtendedPrivKey) -> ExtendedPubKey { pub fn from_priv<C: secp256k1::Signing>(
secp: &Secp256k1<C>,
sk: &ExtendedPrivKey,
) -> ExtendedPubKey {
ExtendedPubKey { ExtendedPubKey {
network: sk.network, network: sk.network,
depth: sk.depth, depth: sk.depth,
parent_fingerprint: sk.parent_fingerprint, parent_fingerprint: sk.parent_fingerprint,
child_number: sk.child_number, child_number: sk.child_number,
public_key: secp256k1::PublicKey::from_secret_key(secp, &sk.private_key), public_key: secp256k1::PublicKey::from_secret_key(secp, &sk.private_key),
chain_code: sk.chain_code chain_code: sk.chain_code,
} }
} }
/// Constructs ECDSA compressed public key matching internal public key representation. /// Constructs ECDSA compressed public key matching internal public key representation.
pub fn to_pub(self) -> PublicKey { pub fn to_pub(self) -> PublicKey { PublicKey { compressed: true, inner: self.public_key } }
PublicKey {
compressed: true,
inner: self.public_key
}
}
/// Constructs BIP340 x-only public key for BIP-340 signatures and Taproot use matching /// Constructs BIP340 x-only public key for BIP-340 signatures and Taproot use matching
/// the internal public key representation. /// the internal public key representation.
pub fn to_x_only_pub(self) -> XOnlyPublicKey { pub fn to_x_only_pub(self) -> XOnlyPublicKey { XOnlyPublicKey::from(self.public_key) }
XOnlyPublicKey::from(self.public_key)
}
/// Attempts to derive an extended public key from a path. /// Attempts to derive an extended public key from a path.
/// ///
@ -701,13 +681,15 @@ impl ExtendedPubKey {
} }
/// Compute the scalar tweak added to this key to get a child key /// Compute the scalar tweak added to this key to get a child key
pub fn ckd_pub_tweak(&self, i: ChildNumber) -> Result<(secp256k1::SecretKey, ChainCode), Error> { pub fn ckd_pub_tweak(
&self,
i: ChildNumber,
) -> Result<(secp256k1::SecretKey, ChainCode), Error> {
match i { match i {
ChildNumber::Hardened { .. } => { ChildNumber::Hardened { .. } => Err(Error::CannotDeriveFromHardenedKey),
Err(Error::CannotDeriveFromHardenedKey)
}
ChildNumber::Normal { index: n } => { ChildNumber::Normal { index: n } => {
let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]); let mut hmac_engine: HmacEngine<sha512::Hash> =
HmacEngine::new(&self.chain_code[..]);
hmac_engine.input(&self.public_key.serialize()[..]); hmac_engine.input(&self.public_key.serialize()[..]);
hmac_engine.input(&endian::u32_to_array_be(n)); hmac_engine.input(&endian::u32_to_array_be(n));
@ -742,7 +724,7 @@ impl ExtendedPubKey {
/// Decoding extended public key from binary data according to BIP 32 /// Decoding extended public key from binary data according to BIP 32
pub fn decode(data: &[u8]) -> Result<ExtendedPubKey, Error> { pub fn decode(data: &[u8]) -> Result<ExtendedPubKey, Error> {
if data.len() != 78 { if data.len() != 78 {
return Err(Error::WrongExtendedKeyLength(data.len())) return Err(Error::WrongExtendedKeyLength(data.len()));
} }
Ok(ExtendedPubKey { Ok(ExtendedPubKey {
@ -766,10 +748,12 @@ impl ExtendedPubKey {
/// Extended public key binary encoding according to BIP 32 /// Extended public key binary encoding according to BIP 32
pub fn encode(&self) -> [u8; 78] { pub fn encode(&self) -> [u8; 78] {
let mut ret = [0; 78]; let mut ret = [0; 78];
ret[0..4].copy_from_slice(&match self.network { ret[0..4].copy_from_slice(
&match self.network {
Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E], Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E],
Network::Testnet | Network::Signet | Network::Regtest => [0x04u8, 0x35, 0x87, 0xCF], Network::Testnet | Network::Signet | Network::Regtest => [0x04u8, 0x35, 0x87, 0xCF],
}[..]); }[..],
);
ret[4] = self.depth as u8; ret[4] = self.depth as u8;
ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); ret[5..9].copy_from_slice(&self.parent_fingerprint[..]);
ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number))); ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number)));
@ -786,9 +770,7 @@ impl ExtendedPubKey {
} }
/// Returns the first four bytes of the identifier /// Returns the first four bytes of the identifier
pub fn fingerprint(&self) -> Fingerprint { pub fn fingerprint(&self) -> Fingerprint { Fingerprint::from(&self.identifier()[0..4]) }
Fingerprint::from(&self.identifier()[0..4])
}
} }
impl fmt::Display for ExtendedPrivKey { impl fmt::Display for ExtendedPrivKey {
@ -832,27 +814,22 @@ impl FromStr for ExtendedPubKey {
} }
impl From<ExtendedPubKey> for XpubIdentifier { impl From<ExtendedPubKey> for XpubIdentifier {
fn from(key: ExtendedPubKey) -> XpubIdentifier { fn from(key: ExtendedPubKey) -> XpubIdentifier { key.identifier() }
key.identifier()
}
} }
impl From<&ExtendedPubKey> for XpubIdentifier { impl From<&ExtendedPubKey> for XpubIdentifier {
fn from(key: &ExtendedPubKey) -> XpubIdentifier { fn from(key: &ExtendedPubKey) -> XpubIdentifier { key.identifier() }
key.identifier()
}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use super::ChildNumber::{Hardened, Normal};
use core::str::FromStr; use core::str::FromStr;
use secp256k1::{self, Secp256k1}; use secp256k1::{self, Secp256k1};
use crate::hashes::hex::FromHex;
use super::ChildNumber::{Hardened, Normal};
use super::*;
use crate::hashes::hex::FromHex;
use crate::network::constants::Network::{self, Bitcoin}; use crate::network::constants::Network::{self, Bitcoin};
#[test] #[test]
@ -862,7 +839,10 @@ mod tests {
assert_eq!(DerivationPath::from_str("4/m/5"), Err(Error::InvalidDerivationPathFormat)); assert_eq!(DerivationPath::from_str("4/m/5"), Err(Error::InvalidDerivationPathFormat));
assert_eq!(DerivationPath::from_str("m//3/0'"), Err(Error::InvalidChildNumberFormat)); assert_eq!(DerivationPath::from_str("m//3/0'"), Err(Error::InvalidChildNumberFormat));
assert_eq!(DerivationPath::from_str("m/0h/0x"), Err(Error::InvalidChildNumberFormat)); assert_eq!(DerivationPath::from_str("m/0h/0x"), Err(Error::InvalidChildNumberFormat));
assert_eq!(DerivationPath::from_str("m/2147483648"), Err(Error::InvalidChildNumber(2147483648))); assert_eq!(
DerivationPath::from_str("m/2147483648"),
Err(Error::InvalidChildNumber(2147483648))
);
assert_eq!(DerivationPath::master(), DerivationPath::from_str("m").unwrap()); assert_eq!(DerivationPath::master(), DerivationPath::from_str("m").unwrap());
assert_eq!(DerivationPath::master(), DerivationPath::default()); assert_eq!(DerivationPath::master(), DerivationPath::default());
@ -873,7 +853,11 @@ mod tests {
); );
assert_eq!( assert_eq!(
DerivationPath::from_str("m/0'/1"), DerivationPath::from_str("m/0'/1"),
Ok(vec![ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap()].into()) Ok(vec![
ChildNumber::from_hardened_idx(0).unwrap(),
ChildNumber::from_normal_idx(1).unwrap()
]
.into())
); );
assert_eq!( assert_eq!(
DerivationPath::from_str("m/0h/1/2'"), DerivationPath::from_str("m/0h/1/2'"),
@ -881,7 +865,8 @@ mod tests {
ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_hardened_idx(0).unwrap(),
ChildNumber::from_normal_idx(1).unwrap(), ChildNumber::from_normal_idx(1).unwrap(),
ChildNumber::from_hardened_idx(2).unwrap(), ChildNumber::from_hardened_idx(2).unwrap(),
].into()) ]
.into())
); );
assert_eq!( assert_eq!(
DerivationPath::from_str("m/0'/1/2h/2"), DerivationPath::from_str("m/0'/1/2h/2"),
@ -890,7 +875,8 @@ mod tests {
ChildNumber::from_normal_idx(1).unwrap(), ChildNumber::from_normal_idx(1).unwrap(),
ChildNumber::from_hardened_idx(2).unwrap(), ChildNumber::from_hardened_idx(2).unwrap(),
ChildNumber::from_normal_idx(2).unwrap(), ChildNumber::from_normal_idx(2).unwrap(),
].into()) ]
.into())
); );
assert_eq!( assert_eq!(
DerivationPath::from_str("m/0'/1/2'/2/1000000000"), DerivationPath::from_str("m/0'/1/2'/2/1000000000"),
@ -900,7 +886,8 @@ mod tests {
ChildNumber::from_hardened_idx(2).unwrap(), ChildNumber::from_hardened_idx(2).unwrap(),
ChildNumber::from_normal_idx(2).unwrap(), ChildNumber::from_normal_idx(2).unwrap(),
ChildNumber::from_normal_idx(1000000000).unwrap(), ChildNumber::from_normal_idx(1000000000).unwrap(),
].into()) ]
.into())
); );
let s = "m/0'/50/3'/5/545456"; let s = "m/0'/50/3'/5/545456";
assert_eq!(DerivationPath::from_str(s), s.into_derivation_path()); assert_eq!(DerivationPath::from_str(s), s.into_derivation_path());
@ -913,7 +900,10 @@ mod tests {
let numbers: Vec<ChildNumber> = path.clone().into(); let numbers: Vec<ChildNumber> = path.clone().into();
let path2: DerivationPath = numbers.into(); let path2: DerivationPath = numbers.into();
assert_eq!(path, path2); assert_eq!(path, path2);
assert_eq!(&path[..2], &[ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap()]); assert_eq!(
&path[..2],
&[ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap()]
);
let indexed: DerivationPath = path[..2].into(); let indexed: DerivationPath = path[..2].into();
assert_eq!(indexed, DerivationPath::from_str("m/0h/1").unwrap()); assert_eq!(indexed, DerivationPath::from_str("m/0h/1").unwrap());
assert_eq!(indexed.child(ChildNumber::from_hardened_idx(2).unwrap()), path); assert_eq!(indexed.child(ChildNumber::from_hardened_idx(2).unwrap()), path);
@ -925,8 +915,8 @@ mod tests {
seed: &[u8], seed: &[u8],
path: DerivationPath, path: DerivationPath,
expected_sk: &str, expected_sk: &str,
expected_pk: &str) expected_pk: &str,
{ ) {
let mut sk = ExtendedPrivKey::new_master(network, seed).unwrap(); let mut sk = ExtendedPrivKey::new_master(network, seed).unwrap();
let mut pk = ExtendedPubKey::from_priv(secp, &sk); let mut pk = ExtendedPubKey::from_priv(secp, &sk);
@ -945,16 +935,13 @@ mod tests {
for &num in path.0.iter() { for &num in path.0.iter() {
sk = sk.ckd_priv(secp, num).unwrap(); sk = sk.ckd_priv(secp, num).unwrap();
match num { match num {
Normal {..} => { Normal { .. } => {
let pk2 = pk.ckd_pub(secp, num).unwrap(); let pk2 = pk.ckd_pub(secp, num).unwrap();
pk = ExtendedPubKey::from_priv(secp, &sk); pk = ExtendedPubKey::from_priv(secp, &sk);
assert_eq!(pk, pk2); assert_eq!(pk, pk2);
} }
Hardened {..} => { Hardened { .. } => {
assert_eq!( assert_eq!(pk.ckd_pub(secp, num), Err(Error::CannotDeriveFromHardenedKey));
pk.ckd_pub(secp, num),
Err(Error::CannotDeriveFromHardenedKey)
);
pk = ExtendedPubKey::from_priv(secp, &sk); pk = ExtendedPubKey::from_priv(secp, &sk);
} }
} }
@ -974,15 +961,15 @@ mod tests {
fn test_increment() { fn test_increment() {
let idx = 9345497; // randomly generated, I promise let idx = 9345497; // randomly generated, I promise
let cn = ChildNumber::from_normal_idx(idx).unwrap(); let cn = ChildNumber::from_normal_idx(idx).unwrap();
assert_eq!(cn.increment().ok(), Some(ChildNumber::from_normal_idx(idx+1).unwrap())); assert_eq!(cn.increment().ok(), Some(ChildNumber::from_normal_idx(idx + 1).unwrap()));
let cn = ChildNumber::from_hardened_idx(idx).unwrap(); let cn = ChildNumber::from_hardened_idx(idx).unwrap();
assert_eq!(cn.increment().ok(), Some(ChildNumber::from_hardened_idx(idx+1).unwrap())); assert_eq!(cn.increment().ok(), Some(ChildNumber::from_hardened_idx(idx + 1).unwrap()));
let max = (1<<31)-1; let max = (1 << 31) - 1;
let cn = ChildNumber::from_normal_idx(max).unwrap(); let cn = ChildNumber::from_normal_idx(max).unwrap();
assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1<<31))); assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1 << 31)));
let cn = ChildNumber::from_hardened_idx(max).unwrap(); let cn = ChildNumber::from_hardened_idx(max).unwrap();
assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1<<31))); assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1 << 31)));
let cn = ChildNumber::from_normal_idx(350).unwrap(); let cn = ChildNumber::from_normal_idx(350).unwrap();
let path = DerivationPath::from_str("m/42'").unwrap(); let path = DerivationPath::from_str("m/42'").unwrap();
@ -1099,7 +1086,6 @@ mod tests {
test_path(&secp, Bitcoin, &seed, "m/0h".parse().unwrap(), test_path(&secp, Bitcoin, &seed, "m/0h".parse().unwrap(),
"xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L", "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
"xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y"); "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y");
} }
#[test] #[test]
@ -1117,7 +1103,8 @@ mod tests {
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
pub fn encode_fingerprint_chaincode() { pub fn encode_fingerprint_chaincode() {
use serde_json; use serde_json;
let fp = Fingerprint::from(&[1u8,2,3,42][..]); let fp = Fingerprint::from(&[1u8, 2, 3, 42][..]);
#[rustfmt::skip]
let cc = ChainCode::from( let cc = ChainCode::from(
&[1u8,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2][..] &[1u8,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2][..]
); );
@ -1175,7 +1162,6 @@ mod tests {
ExtendedPrivKey::from_str(xpriv_str).unwrap(); ExtendedPrivKey::from_str(xpriv_str).unwrap();
} }
#[test] #[test]
#[should_panic(expected = "Secp256k1(InvalidSecretKey)")] #[should_panic(expected = "Secp256k1(InvalidSecretKey)")]
fn schnorr_broken_privkey_ffs() { fn schnorr_broken_privkey_ffs() {

View File

@ -81,6 +81,7 @@ mod serde_utils;
pub mod network; pub mod network;
pub mod address; pub mod address;
pub mod bip158; pub mod bip158;
pub mod bip32;
pub mod blockdata; pub mod blockdata;
pub mod consensus; pub mod consensus;
pub mod error; pub mod error;

View File

@ -11,7 +11,6 @@ pub mod ecdsa;
pub mod schnorr; pub mod schnorr;
pub mod amount; pub mod amount;
pub mod base58; pub mod base58;
pub mod bip32;
pub mod bip152; pub mod bip152;
pub mod hash; pub mod hash;
pub mod merkleblock; pub mod merkleblock;
@ -117,5 +116,8 @@ pub mod address {
pub use crate::address::*; pub use crate::address::*;
} }
#[deprecated(since = "0.30.0", note = "Please use crate::bip32")]
pub use crate::bip32;
#[deprecated(since = "0.30.0", note = "Please use crate::bip158")] #[deprecated(since = "0.30.0", note = "Please use crate::bip158")]
pub use crate::bip158; pub use crate::bip158;