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);