From 2aeb373e73cdf30367c1df434bdc4c398945000f Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sat, 6 Sep 2014 11:35:36 -0500 Subject: [PATCH] Fix encode/decode of ChildNumber so that hardened keys do not become normal ones --- src/wallet/bip32.rs | 42 +++++++++++++++++++++++++++++++++++++++++- src/wallet/wallet.rs | 4 +--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/wallet/bip32.rs b/src/wallet/bip32.rs index 4d9c0ed..358aa5c 100644 --- a/src/wallet/bip32.rs +++ b/src/wallet/bip32.rs @@ -18,6 +18,7 @@ use std::default::Default; use std::io::extensions::{u64_to_be_bytes, u64_from_be_bytes}; +use serialize::{Decoder, Decodable, Encoder, Encodable}; use crypto::digest::Digest; use crypto::hmac::Hmac; @@ -84,7 +85,7 @@ pub struct ExtendedPubKey { } /// A child number for a derived key -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)] +#[deriving(Clone, PartialEq, Eq, Show)] pub enum ChildNumber { /// Hardened key index, within [0, 2^31 - 1] Hardened(u32), @@ -92,6 +93,26 @@ pub enum ChildNumber { Normal(u32), } +impl, E> Encodable for ChildNumber { + fn encode(&self, s: &mut S) -> Result<(), E> { + match *self { + Hardened(n) => (n + (1 << 31)).encode(s), + Normal(n) => n.encode(s) + } + } +} + +impl, E> Decodable for ChildNumber { + fn decode(d: &mut D) -> Result { + let n: u32 = try!(Decodable::decode(d)); + if n < (1 << 31) { + Ok(Normal(n)) + } else { + Ok(Hardened(n - (1 << 31))) + } + } +} + /// A BIP32 error #[deriving(Clone, PartialEq, Eq, Show)] pub enum Error { @@ -476,6 +497,25 @@ mod tests { "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"); } + #[test] + pub fn encode_decode_childnumber() { + use serialize::json; + + let h1 = Hardened(1); + let n1 = Normal(1); + + let h1_str = json::encode(&h1); + let n1_str = json::encode(&n1); + + assert!(h1 != n1); + assert!(h1_str != n1_str); + + let h1_dec = json::decode(h1_str.as_slice()).unwrap(); + let n1_dec = json::decode(n1_str.as_slice()).unwrap(); + assert_eq!(h1, h1_dec); + assert_eq!(n1, n1_dec); + } + #[bench] pub fn generate_sequential_normal_children(bh: &mut Bencher) { let seed = "000102030405060708090a0b0c0d0e0f".from_hex().unwrap(); diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index 70f95d8..4eec4c9 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -30,6 +30,7 @@ use wallet::bip32::{mod, ChildNumber, ExtendedPrivKey, Normal, Hardened}; use wallet::address::Address; /// A Wallet error +#[deriving(Clone, PartialEq, Eq, Show)] pub enum Error { /// Tried to lookup an account by name, but none was found AccountNotFound, @@ -97,9 +98,6 @@ impl, E> Encodable for Wallet { } } -impl Account { -} - impl, E> Decodable for Wallet { fn decode(d: &mut D) -> Result { d.read_struct("wallet", 2, |d| {