diff --git a/bip32/src/lib.rs b/bip32/src/lib.rs
index ed97e21..16b8a12 100644
--- a/bip32/src/lib.rs
+++ b/bip32/src/lib.rs
@@ -22,17 +22,17 @@ pub struct Fingerprint(pub [u8; 4]);
///
/// This contains the key derivation information about a public key.
#[derive(Debug, Clone)]
-pub struct ExtendedPublicKey<'a> {
+pub struct ExtendedPublicKey {
/// The version of the extended public key.
pub version: [u8; 4],
/// The depth of the extended public key.
pub depth: u8,
/// The fingerprint of the extended public key parent.
- pub parent_fingerprint: &'a [u8],
+ pub parent_fingerprint: [u8; 4],
/// The child number of the extended public key.
pub child_number: u32,
/// The chain code of the extended public key.
- pub chain_code: &'a [u8],
+ pub chain_code: [u8; 32],
/// The public key.
pub public_key: PublicKey,
}
@@ -46,12 +46,12 @@ pub struct ExtendedPublicKey<'a> {
///
/// The buffer contained in the type should be always valid.
#[derive(Debug, Clone)]
-pub struct DerivationPathLe<'a> {
- buf: &'a [u8],
+pub struct DerivationPathLe {
+ buf: Input,
len: usize,
}
-impl<'a> DerivationPathLe<'a> {
+impl DerivationPathLe {
/// Returns the number of elements in the derivation path.
#[inline]
pub fn len(&self) -> usize {
@@ -59,25 +59,41 @@ impl<'a> DerivationPathLe<'a> {
}
/// Returns an iterator over the elements of the derivation path.
- pub fn iter(&self) -> DerivationPathLeIter {
- DerivationPathLeIter { buf: self.buf }
+ pub fn iter(&self) -> DerivationPathLeIter
+ where
+ Input: Clone,
+ {
+ DerivationPathLeIter {
+ count: 0,
+ len: self.len,
+ buf: self.buf.clone(),
+ }
}
}
/// Iterator over the derivation path elements.
-pub struct DerivationPathLeIter<'a> {
- buf: &'a [u8],
+pub struct DerivationPathLeIter {
+ count: usize,
+ len: usize,
+ buf: Input,
}
-impl<'a> Iterator for DerivationPathLeIter<'a> {
+impl Iterator for DerivationPathLeIter
+where
+ Input: Clone
+ + core::fmt::Debug
+ + nom::InputLength
+ + nom::InputIter-
+ + nom::Slice>,
+{
type Item = u32;
fn next(&mut self) -> Option {
- if self.buf.is_empty() {
+ if self.count >= self.len {
return None;
}
- let (buf, item) = le_u32::<_, nom::error::Error<_>>(self.buf)
+ let (buf, item) = le_u32::<_, nom::error::Error<_>>(self.buf.clone())
.expect("element should be valid at this point");
self.buf = buf;
@@ -87,11 +103,11 @@ impl<'a> Iterator for DerivationPathLeIter<'a> {
/// Information about an extended public key was derived.
#[derive(Debug)]
-pub struct KeySource<'a> {
+pub struct KeySource {
/// Fingerprint of the master key.
pub fingerprint: Fingerprint,
/// Derivation path of the key.
- pub path: DerivationPathLe<'a>,
+ pub path: DerivationPathLe,
}
#[cfg(test)]
diff --git a/bip32/src/parser.rs b/bip32/src/parser.rs
index b4329d7..a864bbe 100644
--- a/bip32/src/parser.rs
+++ b/bip32/src/parser.rs
@@ -3,24 +3,40 @@
//! Parser combinators for BIP-32 serialization formats.
-use nom::multi::fill;
+use core::ops::RangeFrom;
+
use nom::{
branch::alt,
bytes::complete::{tag, take},
combinator::{map, map_res, verify},
error::{FromExternalError, ParseError},
- multi::many0_count,
+ multi::{fill, many0_count},
number::complete::{be_u32, le_u32, u8},
sequence::tuple,
- IResult,
+ Compare, IResult, InputIter, InputLength, InputTake, Slice,
};
use secp256k1::PublicKey;
use crate::{DerivationPathLe, ExtendedPublicKey, Fingerprint, KeySource};
-fn bitcoin_mainnet_xpub<'a, Error: ParseError<&'a [u8]>>(
- input: &'a [u8],
-) -> IResult<&[u8], &[u8], Error> {
+fn to_fixed_bytes(i: Input) -> [u8; N]
+where
+ Input: InputIter
- ,
+{
+ let mut slice = [0; N];
+ for (i, byte) in i.iter_indices() {
+ slice[i] = byte;
+ }
+ slice
+}
+
+fn bitcoin_mainnet_xpub(i: Input) -> IResult
+where
+ Input: for<'a> Compare<&'a [u8]> + InputTake + Clone,
+ Error: ParseError,
+{
+ let tag = tag::<_, Input, Error>;
+
let xpub = tag(&[0x04, 0x88, 0xb2, 0x1e]);
let ypub = tag(&[0x04, 0x9d, 0x7c, 0xb2]);
let zpub = tag(&[0x04, 0xb2, 0x47, 0x46]);
@@ -28,12 +44,16 @@ fn bitcoin_mainnet_xpub<'a, Error: ParseError<&'a [u8]>>(
let multisig_zpub = tag(&[0x02, 0xaa, 0x7e, 0xd3]); // Zpub
let mut parser = alt((xpub, ypub, zpub, multisig_ypub, multisig_zpub));
- parser(input)
+ parser(i)
}
-fn bitcoin_testnet_xpub<'a, Error: ParseError<&'a [u8]>>(
- input: &'a [u8],
-) -> IResult<&[u8], &[u8], Error> {
+fn bitcoin_testnet_xpub(i: Input) -> IResult
+where
+ Input: for<'a> Compare<&'a [u8]> + InputTake + Clone,
+ Error: ParseError,
+{
+ let tag = tag::<_, Input, Error>;
+
let tpub = tag(&[0x04, 0x35, 0x87, 0xcf]);
let upub = tag(&[0x04, 0x4a, 0x52, 0x62]);
let vpub = tag(&[0x04, 0x5f, 0x1c, 0xf6]);
@@ -41,32 +61,43 @@ fn bitcoin_testnet_xpub<'a, Error: ParseError<&'a [u8]>>(
let multisig_vpub = tag(&[0x02, 0x57, 0x54, 0x83]); // Vpub
let mut parser = alt((tpub, upub, vpub, multisig_upub, multisig_vpub));
- parser(input)
+ parser(i)
}
-fn xpub_version<'a, Error: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], [u8; 4], Error> {
- let bitcoin_xpub = alt((bitcoin_mainnet_xpub, bitcoin_testnet_xpub));
-
- let mut version = map(bitcoin_xpub, |version| {
- let mut tmp = [0; 4];
- tmp.copy_from_slice(&version);
- tmp
- });
+fn xpub_version(i: Input) -> IResult
+where
+ Input: for<'a> Compare<&'a [u8]> + InputTake + Clone + InputIter
- ,
+ Error: ParseError,
+{
+ let bitcoin_xpub = alt((
+ bitcoin_mainnet_xpub::,
+ bitcoin_testnet_xpub::,
+ ));
+ let mut version = map(bitcoin_xpub, to_fixed_bytes::);
version(i)
}
/// Parse an extended public key.
-pub fn extended_public_key<'a, Error>(i: &'a [u8]) -> IResult<&[u8], ExtendedPublicKey, Error>
+pub fn extended_public_key(i: Input) -> IResult
where
- Error: ParseError<&'a [u8]>,
- Error: FromExternalError<&'a [u8], secp256k1::Error>,
+ Input: for<'a> Compare<&'a [u8]>
+ + InputTake
+ + Clone
+ + InputIter
-
+ + InputLength
+ + Slice>,
+ Error: ParseError,
+ Error: FromExternalError,
{
- let depth = u8;
- let parent_fingerprint = take(4usize);
- let child_number = be_u32;
- let chain_code = take(32usize);
- let public_key = map_res(take(33usize), PublicKey::from_slice);
+ let depth = u8::;
+ let parent_fingerprint = map(take::<_, Input, Error>(4usize), to_fixed_bytes::<_, 4>);
+ let child_number = be_u32::;
+ let chain_code = map(take::<_, Input, Error>(32usize), to_fixed_bytes::<_, 32>);
+ let public_key = map_res(
+ map(take::<_, Input, Error>(33usize), to_fixed_bytes::<_, 33>),
+ |pk| PublicKey::from_slice(&pk),
+ );
let parser = tuple((
xpub_version,
@@ -94,7 +125,7 @@ where
let mut parser = verify(parser, |key| {
// When the depth is 0 (master key) the parent fingerprint should be 0 and
// child number should be 0 as well as it doesn't apply here.
- if key.depth == 0 && (key.parent_fingerprint != &[0; 4] || key.child_number != 0) {
+ if key.depth == 0 && (&key.parent_fingerprint != &[0; 4] || key.child_number != 0) {
false
} else {
true
@@ -108,26 +139,34 @@ where
/// integers.
///
/// ` := *`
-pub fn derivation_path_le<'a, Error: ParseError<&'a [u8]>>(
- input: &'a [u8],
-) -> IResult<&[u8], DerivationPathLe, Error> {
- let (next_input, len) = many0_count(le_u32)(input)?;
+pub fn derivation_path_le(
+ input: Input,
+) -> IResult, Error>
+where
+ Input: Clone + Slice> + InputIter
- + InputLength,
+ Error: ParseError,
+{
+ let (next_input, len) = many0_count(le_u32)(input.clone())?;
Ok((next_input, DerivationPathLe { buf: input, len }))
}
/// Parses a BIP-32 fingerprint.
-pub fn fingerprint<'a, Error: ParseError<&'a [u8]>>(
- i: &'a [u8],
-) -> IResult<&'a [u8], Fingerprint, Error> {
+pub fn fingerprint(i: Input) -> IResult
+where
+ Input: PartialEq + Clone + Slice> + InputIter
- + InputLength,
+ Error: ParseError,
+{
let mut buf = [0; 4];
let (i, _) = fill(u8, &mut buf)(i)?;
Ok((i, Fingerprint(buf)))
}
/// Parses a [`KeySource`].
-pub fn key_source<'a, Error: ParseError<&'a [u8]>>(
- i: &'a [u8],
-) -> IResult<&'a [u8], KeySource, Error> {
+pub fn key_source(i: Input) -> IResult, Error>
+where
+ Input: PartialEq + Clone + Slice> + InputIter
- + InputLength,
+ Error: ParseError,
+{
let fields = tuple((fingerprint, derivation_path_le));
let mut parser = map(fields, |(fingerprint, path)| KeySource {
fingerprint,
@@ -148,7 +187,8 @@ mod tests {
for test_vector in vectors.valid {
println!("Test vector: {}", test_vector.name);
for chain in &test_vector.chains {
- extended_public_key::>(&chain.extended_public_key.0).unwrap();
+ let buf = chain.extended_public_key.as_slice();
+ extended_public_key::<_, nom::error::Error<_>>(buf).unwrap();
}
}
}
@@ -162,7 +202,7 @@ mod tests {
println!("Test vector: {}", test_vector.name);
for (i, key) in test_vector.extended_keys.iter().enumerate() {
println!("Index: {}", i);
- extended_public_key::>(&key.0).unwrap_err();
+ extended_public_key::<_, nom::error::Error<_>>(key.as_slice()).unwrap_err();
}
}
}
@@ -171,7 +211,7 @@ mod tests {
fn parse_derivation_path_le() {
const INPUT: &[u8] = &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80];
- let (i, path) = derivation_path_le::>(INPUT).unwrap();
+ let (i, path) = derivation_path_le::<_, nom::error::Error<_>>(INPUT).unwrap();
assert!(i.is_empty());
assert_eq!(path.buf, INPUT);
}
@@ -180,7 +220,7 @@ mod tests {
fn parse_key_source() {
const INPUT: &[u8] = &[0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF];
- let (i, source) = key_source::>(INPUT).unwrap();
+ let (i, source) = key_source::<_, nom::error::Error<_>>(INPUT).unwrap();
assert!(i.is_empty());
assert_eq!(source.fingerprint, Fingerprint([0xAA, 0xBB, 0xCC, 0xDD]));
assert_eq!(source.path.iter().next().unwrap(), 0xFFFF_EEEE);