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: ACK8bed2ddffe
Kixunil: ACK8bed2ddffe
Tree-SHA512: dadea31be0459fd10e71927bd21dc44b59428f695a6df7093052ca7257b6590d5dd5b1343a89869ac9f4d7805dbca7558b475048ea9387c36265f14246cc6852
This commit is contained in:
commit
b1869803bf
|
@ -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(
|
||||||
Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4],
|
&match self.network {
|
||||||
Network::Testnet | Network::Signet | Network::Regtest => [0x04, 0x35, 0x83, 0x94],
|
Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4],
|
||||||
}[..]);
|
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(
|
||||||
Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E],
|
&match self.network {
|
||||||
Network::Testnet | Network::Signet | Network::Regtest => [0x04u8, 0x35, 0x87, 0xCF],
|
Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E],
|
||||||
}[..]);
|
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() {
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue