bip32: Add additional methods and traits to DerivationPath
- From<&[ChildNumber]> (cloning) - AsRef<[ChildNumber]> - std::iter::FromIterator<ChildNumber> - std::iter::IntoIterator<ChildNumber> - std::ops::Index (returning &[ChildNumber]) Also add two methods: - child(&self, ChildNumber) -> DerivationPath - into_child(self, ChildNumber) -> DerivationPath
This commit is contained in:
parent
1373969805
commit
dce81b623e
|
@ -204,7 +204,8 @@ impl serde::Serialize for ChildNumber {
|
||||||
|
|
||||||
/// A BIP-32 derivation path.
|
/// A BIP-32 derivation path.
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub struct DerivationPath(pub Vec<ChildNumber>);
|
pub struct DerivationPath(Vec<ChildNumber>);
|
||||||
|
impl_index_newtype!(DerivationPath, ChildNumber);
|
||||||
|
|
||||||
impl From<Vec<ChildNumber>> for DerivationPath {
|
impl From<Vec<ChildNumber>> for DerivationPath {
|
||||||
fn from(numbers: Vec<ChildNumber>) -> Self {
|
fn from(numbers: Vec<ChildNumber>) -> Self {
|
||||||
|
@ -218,6 +219,32 @@ impl Into<Vec<ChildNumber>> for DerivationPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a [ChildNumber]> for DerivationPath {
|
||||||
|
fn from(numbers: &'a [ChildNumber]) -> Self {
|
||||||
|
DerivationPath(numbers.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::iter::FromIterator<ChildNumber> for DerivationPath {
|
||||||
|
fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = ChildNumber> {
|
||||||
|
DerivationPath(Vec::from_iter(iter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ::std::iter::IntoIterator for &'a DerivationPath {
|
||||||
|
type Item = &'a ChildNumber;
|
||||||
|
type IntoIter = ::std::slice::Iter<'a, ChildNumber>;
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<[ChildNumber]> for DerivationPath {
|
||||||
|
fn as_ref(&self) -> &[ChildNumber] {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for DerivationPath {
|
impl FromStr for DerivationPath {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
|
@ -233,6 +260,22 @@ impl FromStr for DerivationPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DerivationPath {
|
||||||
|
/// Create a new DerivationPath that is a child of this one.
|
||||||
|
pub fn child(&self, cn: ChildNumber) -> DerivationPath {
|
||||||
|
let mut path = self.0.clone();
|
||||||
|
path.push(cn);
|
||||||
|
DerivationPath(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert into a DerivationPath that is a child of this one.
|
||||||
|
pub fn into_child(self, cn: ChildNumber) -> DerivationPath {
|
||||||
|
let mut path = self.0;
|
||||||
|
path.push(cn);
|
||||||
|
DerivationPath(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for DerivationPath {
|
impl fmt::Display for DerivationPath {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
f.write_str("m")?;
|
f.write_str("m")?;
|
||||||
|
@ -361,13 +404,15 @@ impl ExtendedPrivKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to derive an extended private key from a path.
|
/// Attempts to derive an extended private key from a path.
|
||||||
pub fn derive_priv<C: secp256k1::Signing>(
|
///
|
||||||
|
/// The `path` argument can be both of type `DerivationPath` or `Vec<ChildNumber>`.
|
||||||
|
pub fn derive_priv<C: secp256k1::Signing, P: AsRef<[ChildNumber]>>(
|
||||||
&self,
|
&self,
|
||||||
secp: &Secp256k1<C>,
|
secp: &Secp256k1<C>,
|
||||||
path: &DerivationPath,
|
path: &P,
|
||||||
) -> Result<ExtendedPrivKey, Error> {
|
) -> Result<ExtendedPrivKey, Error> {
|
||||||
let mut sk: ExtendedPrivKey = *self;
|
let mut sk: ExtendedPrivKey = *self;
|
||||||
for cnum in &path.0 {
|
for cnum in path.as_ref() {
|
||||||
sk = sk.ckd_priv(secp, *cnum)?;
|
sk = sk.ckd_priv(secp, *cnum)?;
|
||||||
}
|
}
|
||||||
Ok(sk)
|
Ok(sk)
|
||||||
|
@ -430,13 +475,15 @@ impl ExtendedPubKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to derive an extended public key from a path.
|
/// Attempts to derive an extended public key from a path.
|
||||||
pub fn derive_pub<C: secp256k1::Verification>(
|
///
|
||||||
|
/// The `path` argument can be both of type `DerivationPath` or `Vec<ChildNumber>`.
|
||||||
|
pub fn derive_pub<C: secp256k1::Verification, P: AsRef<[ChildNumber]>>(
|
||||||
&self,
|
&self,
|
||||||
secp: &Secp256k1<C>,
|
secp: &Secp256k1<C>,
|
||||||
path: &DerivationPath,
|
path: &P,
|
||||||
) -> Result<ExtendedPubKey, Error> {
|
) -> Result<ExtendedPubKey, Error> {
|
||||||
let mut pk: ExtendedPubKey = *self;
|
let mut pk: ExtendedPubKey = *self;
|
||||||
for cnum in &path.0 {
|
for cnum in path.as_ref() {
|
||||||
pk = pk.ckd_pub(secp, *cnum)?
|
pk = pk.ckd_pub(secp, *cnum)?
|
||||||
}
|
}
|
||||||
Ok(pk)
|
Ok(pk)
|
||||||
|
@ -657,6 +704,18 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_derivation_path_convertion_index() {
|
||||||
|
let path = DerivationPath::from_str("m/0h/1/2'").unwrap();
|
||||||
|
let numbers: Vec<ChildNumber> = path.clone().into();
|
||||||
|
let path2: DerivationPath = numbers.into();
|
||||||
|
assert_eq!(path, path2);
|
||||||
|
assert_eq!(&path[..2], &[ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap()]);
|
||||||
|
let indexed: DerivationPath = path[..2].into();
|
||||||
|
assert_eq!(indexed, DerivationPath::from_str("m/0h/1").unwrap());
|
||||||
|
assert_eq!(indexed.child(ChildNumber::from_hardened_idx(2).unwrap()), path);
|
||||||
|
}
|
||||||
|
|
||||||
fn test_path<C: secp256k1::Signing + secp256k1::Verification>(secp: &Secp256k1<C>,
|
fn test_path<C: secp256k1::Signing + secp256k1::Verification>(secp: &Secp256k1<C>,
|
||||||
network: Network,
|
network: Network,
|
||||||
seed: &[u8],
|
seed: &[u8],
|
||||||
|
|
Loading…
Reference in New Issue