Fix encode/decode of ChildNumber so that hardened keys do not become normal ones

This commit is contained in:
Andrew Poelstra 2014-09-06 11:35:36 -05:00
parent a240d25611
commit 2aeb373e73
2 changed files with 42 additions and 4 deletions

View File

@ -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<S: Encoder<E>, E> Encodable<S, E> 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<D: Decoder<E>, E> Decodable<D, E> for ChildNumber {
fn decode(d: &mut D) -> Result<ChildNumber, E> {
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();

View File

@ -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<S: Encoder<E>, E> Encodable<S, E> for Wallet {
}
}
impl Account {
}
impl<D: Decoder<E>, E> Decodable<D, E> for Wallet {
fn decode(d: &mut D) -> Result<Wallet, E> {
d.read_struct("wallet", 2, |d| {