More changes, incl. dropping DumbHasher in favor of SipHasher

only json stuff left in this round of compiler errors :)
This commit is contained in:
Andrew Poelstra 2015-04-05 14:43:44 -05:00
parent 7738722ab5
commit 7b89c15ed5
16 changed files with 90 additions and 121 deletions

View File

@ -23,13 +23,13 @@
//!
use std::num::Zero;
use std::{marker, ptr};
use std::{marker, num, ptr};
use blockdata::block::{Block, BlockHeader};
use blockdata::transaction::Transaction;
use blockdata::constants::{DIFFCHANGE_INTERVAL, DIFFCHANGE_TIMESPAN,
TARGET_BLOCK_SPACING, max_target, genesis_block};
use network::constants::Network::{self, BitcoinTestnet};
use network::constants::Network;
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::serialize::{BitcoinHash, SimpleDecoder, SimpleEncoder};
use util::BitArray;
@ -462,7 +462,7 @@ impl Blockchain {
// Compute new target
let mut target = unsafe { (*prev).block.header.target() };
target = target.mul_u32(timespan);
target = target / FromPrimitive::from_u64(DIFFCHANGE_TIMESPAN as u64).unwrap();
target = target / num::FromPrimitive::from_u64(DIFFCHANGE_TIMESPAN as u64).unwrap();
// Clamp below MAX_TARGET (difficulty 1)
let max = max_target(self.network);
if target > max { target = max };
@ -470,13 +470,13 @@ impl Blockchain {
satoshi_the_precision(&target)
// On non-diffchange blocks, Testnet has a rule that any 20-minute-long
// block intervals result the difficulty
} else if self.network == BitcoinTestnet &&
} else if self.network == Network::BitcoinTestnet &&
block.header.time > unsafe { (*prev).block.header.time } + 2*TARGET_BLOCK_SPACING {
max_target(self.network)
// On the other hand, if we are in Testnet and the block interval is less
// than 20 minutes, we need to scan backward to find a block for which the
// previous rule did not apply, to find the "real" difficulty.
} else if self.network == BitcoinTestnet {
} else if self.network == Network::BitcoinTestnet {
// Scan back DIFFCHANGE_INTERVAL blocks
unsafe {
let mut scan = prev;

View File

@ -26,7 +26,7 @@ use blockdata::opcodes;
use blockdata::script::Script;
use blockdata::transaction::{Transaction, TxOut, TxIn};
use blockdata::block::{Block, BlockHeader};
use network::constants::Network::{Bitcoin, BitcoinTestnet};
use network::constants::Network;
use util::misc::hex_bytes;
use util::hash::MerkleRoot;
use util::uint::Uint256;
@ -74,7 +74,7 @@ fn bitcoin_genesis_tx() -> Transaction {
// Outputs
let mut out_script = Script::new();
out_script.push_slice(hex_bytes("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap().as_slice());
out_script.push_opcode(opcodes::all::OP_CHECKSIG);
out_script.push_opcode(opcodes::All::OP_CHECKSIG);
ret.output.push(TxOut {
value: 50 * COIN_VALUE,
script_pubkey: out_script
@ -87,7 +87,7 @@ fn bitcoin_genesis_tx() -> Transaction {
/// Constructs and returns the genesis block
pub fn genesis_block(network: Network) -> Block {
match network {
Bitcoin => {
Network::Bitcoin => {
let txdata = vec![bitcoin_genesis_tx()];
Block {
header: BlockHeader {
@ -101,7 +101,7 @@ pub fn genesis_block(network: Network) -> Block {
txdata: txdata
}
}
BitcoinTestnet => {
Network::Testnet => {
let txdata = vec![bitcoin_genesis_tx()];
Block {
header: BlockHeader {
@ -123,7 +123,7 @@ mod test {
use std::default::Default;
use serialize::hex::FromHex;
use network::constants::Network::{Bitcoin, BitcoinTestnet};
use network::constants::Network;
use network::serialize::{BitcoinHash, serialize};
use blockdata::constants::{genesis_block, bitcoin_genesis_tx};
use blockdata::constants::{MAX_SEQUENCE, COIN_VALUE};
@ -152,7 +152,7 @@ mod test {
#[test]
fn bitcoin_genesis_full_block() {
let gen = genesis_block(Bitcoin);
let gen = genesis_block(network::Bitcoin);
assert_eq!(gen.header.version, 1);
assert_eq!(gen.header.prev_blockhash, Default::default());
@ -167,7 +167,7 @@ mod test {
#[test]
fn testnet_genesis_full_block() {
let gen = genesis_block(BitcoinTestnet);
let gen = genesis_block(network::Testnet);
assert_eq!(gen.header.version, 1);
assert_eq!(gen.header.prev_blockhash, Default::default());
assert_eq!(gen.header.merkle_root.be_hex_string(),

View File

@ -623,9 +623,9 @@ impl json::ToJson for All {
}
/// Empty stack is also FALSE
pub static OP_FALSE: All = OP_PUSHBYTES_0;
pub static OP_FALSE: All = All::OP_PUSHBYTES_0;
/// Number 1 is also TRUE
pub static OP_TRUE: All = OP_PUSHNUM_1;
pub static OP_TRUE: All = All::OP_PUSHNUM_1;
/// Broad categories of opcodes with similar behavior
#[derive(Clone, PartialEq, Eq, Debug)]

View File

@ -50,11 +50,23 @@ use util::misc::script_find_and_remove;
/// A Bitcoin script
pub struct Script(Box<[u8]>);
impl<S: hash::Writer> hash::Hash<S> for Script {
impl hash::Hash for Script {
#[inline]
fn hash(&self, state: &mut S) {
fn hash<H>(&self, state: &mut H)
where H: hash::Hasher
{
let &Script(ref raw) = self;
(&raw[..]).hash(state)
(&raw[..]).hash(state);
}
#[inline]
fn hash_slice<H>(data: &[Script], state: &mut H)
where H: hash::Hasher
{
for s in data.iter() {
let &Script(ref raw) = s;
(&raw[..]).hash(state);
}
}
}
@ -1293,7 +1305,7 @@ impl<'a> ops::Index<ops::Range<usize>> for MaybeOwned<'a> {
type Output = [u8];
#[inline]
fn index(&self, index: Range<usize>) -> &[u8] {
fn index(&self, index: ops::Range<usize>) -> &[u8] {
match *self {
MaybeOwned::Owned(ref v) => &v[index],
MaybeOwned::Borrowed(ref s) => &s[index]
@ -1305,7 +1317,7 @@ impl<'a> ops::Index<ops::RangeTo<usize>> for MaybeOwned<'a> {
type Output = [u8];
#[inline]
fn index(&self, index: RangeTo<usize>) -> &[u8] {
fn index(&self, index: ops::RangeTo<usize>) -> &[u8] {
match *self {
MaybeOwned::Owned(ref v) => &v[index],
MaybeOwned::Borrowed(ref s) => &s[index]
@ -1317,7 +1329,7 @@ impl<'a> ops::Index<ops::RangeFrom<usize>> for MaybeOwned<'a> {
type Output = [u8];
#[inline]
fn index(&self, index: RangeFrom<usize>) -> &[u8] {
fn index(&self, index: ops::RangeFrom<usize>) -> &[u8] {
match *self {
MaybeOwned::Owned(ref v) => &v[index],
MaybeOwned::Borrowed(ref s) => &s[index]
@ -1325,11 +1337,11 @@ impl<'a> ops::Index<ops::RangeFrom<usize>> for MaybeOwned<'a> {
}
}
impl<'a> ops::Index<ops::RangeAll<usize>> for MaybeOwned<'a> {
impl<'a> ops::Index<ops::RangeFull<usize>> for MaybeOwned<'a> {
type Output = [u8];
#[inline]
fn index(&self, _: RangeAll<usize>) -> &[u8] {
fn index(&self, _: ops::RangeFull<usize>) -> &[u8] {
match *self {
MaybeOwned::Owned(ref v) => &v[..],
MaybeOwned::Borrowed(ref s) => &s[..]
@ -1833,7 +1845,7 @@ impl Script {
// If-statements take effect when not executing
(false, opcodes::Class::Ordinary(opcodes::Ordinary::OP_IF)) => exec_stack.push(false),
(false, opcodes::Class::Ordinary(opcodes::Ordinary::OP_NOTIF)) => exec_stack.push(false),
(false, opcodes::Ordinary(opcodes::Ordinary::OP_ELSE)) => {
(false, opcodes::Class::Ordinary(opcodes::Ordinary::OP_ELSE)) => {
match exec_stack.last_mut() {
Some(ref_e) => { *ref_e = !*ref_e }
None => { return Err(Error::ElseWithoutIf); }

View File

@ -173,8 +173,8 @@ impl TxIn {
if txo.script_pubkey.is_p2sh() && stack.len() > 0 {
p2sh_stack = stack.clone();
p2sh_script = match p2sh_stack.pop() {
Some(script::Owned(v)) => Script::from_vec(v),
Some(script::Borrowed(s)) => Script::from_vec(s.to_vec()),
Some(script::MaybeOwned::Owned(v)) => Script::from_vec(v),
Some(script::MaybeOwned::Borrowed(s)) => Script::from_vec(s.to_vec()),
None => unreachable!()
};
}
@ -254,8 +254,8 @@ impl Transaction {
if txo.script_pubkey.is_p2sh() && stack.len() > 0 {
p2sh_stack = stack.clone();
p2sh_script = match p2sh_stack.pop() {
Some(script::Owned(v)) => Script::from_vec(v),
Some(script::Borrowed(s)) => Script::from_vec(s.to_vec()),
Some(script::MaybeOwned::Owned(v)) => Script::from_vec(v),
Some(script::MaybeOwned::Borrowed(s)) => Script::from_vec(s.to_vec()),
None => unreachable!()
};
}

View File

@ -21,6 +21,7 @@
use std::cmp;
use std::collections::HashMap;
use std::collections::hash::map::Iter;
use std::hash::SipHasher;
use std::default::Default;
use std::mem;
use num_cpus;
@ -31,7 +32,7 @@ use blockdata::constants::genesis_block;
use blockdata::block::Block;
use network::constants::Network;
use network::serialize::BitcoinHash;
use util::hash::{DumbHasher, Sha256dHash};
use util::hash::Sha256dHash;
/// The amount of validation to do when updating the UTXO set
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
@ -101,7 +102,7 @@ impl<'a> Iterator<(Sha256dHash, u32, &'a TxOut, u32)> for UtxoIterator<'a> {
/// The UTXO set
pub struct UtxoSet {
table: HashMap<Sha256dHash, UtxoNode, DumbHasher>,
table: HashMap<Sha256dHash, UtxoNode, SipHasher>,
last_hash: Sha256dHash,
// A circular buffer of deleted utxos, grouped by block
spent_txos: Vec<Vec<((Sha256dHash, u32), (u32, TxOut))>>,
@ -121,7 +122,7 @@ impl UtxoSet {
// must follow suit, otherwise we will accept a transaction spending it
// while the reference client won't, causing us to fork off the network.
UtxoSet {
table: HashMap::with_hasher(DumbHasher),
table: HashMap::with_hasher(SipHasher::new()),
last_hash: genesis_block(network).header.bitcoin_hash(),
spent_txos: Vec::from_elem(rewind_limit, vec![]),
spent_idx: 0,

View File

@ -28,6 +28,7 @@
#![crate_type = "rlib"]
// Experimental features we need
#![feature(box_patterns)]
#![feature(custom_derive, plugin)]
#![feature(overloaded_calls)]
#![feature(unsafe_destructor)]

View File

@ -28,7 +28,7 @@ user_enum! {
#[doc="Classic Bitcoin"]
Bitcoin <-> "bitcoin",
#[doc="Bitcoin's testnet"]
BitcoinTestnet <-> "testnet"
Testnet <-> "testnet"
}
}
@ -41,7 +41,7 @@ pub const USER_AGENT: &'static str = "bitcoin-rust v0.1";
pub fn magic(network: Network) -> u32 {
match network {
Network::Bitcoin => 0xD9B4BEF9,
Network::BitcoinTestnet => 0x0709110B
Network::Testnet => 0x0709110B
// Note: any new entries here must be added to `deserialize` below
}
}
@ -59,7 +59,7 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Network {
let magic: u32 = try!(ConsensusDecodable::consensus_decode(d));
match magic {
0xD9B4BEF9 => Ok(Network::Bitcoin),
0x0709110B => Ok(Network::BitcoinTestnet),
0x0709110B => Ok(Network::Testnet),
x => Err(d.error(format!("Unknown network (magic {:x})", x).as_slice()))
}
}
@ -74,10 +74,10 @@ mod tests {
#[test]
fn serialize_test() {
assert_eq!(serialize(&Network::Bitcoin).unwrap(), vec![0xf9, 0xbe, 0xb4, 0xd9]);
assert_eq!(serialize(&Network::BitcoinTestnet).unwrap(), vec![0x0b, 0x11, 0x09, 0x07]);
assert_eq!(serialize(&Network::Testnet).unwrap(), vec![0x0b, 0x11, 0x09, 0x07]);
assert_eq!(deserialize(vec![0xf9, 0xbe, 0xb4, 0xd9]), Ok(Network::Bitcoin));
assert_eq!(deserialize(vec![0x0b, 0x11, 0x09, 0x07]), Ok(Network::BitcoinTestnet));
assert_eq!(deserialize(vec![0x0b, 0x11, 0x09, 0x07]), Ok(Network::Testnet));
let bad: Result<Network, _> = deserialize("fakenet".as_bytes().to_vec());
assert!(bad.is_err());

View File

@ -18,11 +18,11 @@
//! to connect to a peer, send network messages, and receive Bitcoin data.
//!
use std::io::{Result, Error, ErrorKind};
use std::{io, thread};
use std::sync::mpsc::{channel, Receiver};
use network::constants::Network;
use network::message;
use network::message::SocketResponse::{self, MessageReceived};
use network::message::NetworkMessage::Verack;
use network::socket::Socket;
@ -35,13 +35,13 @@ pub trait Listener {
/// Return the network this `Listener` is operating on
fn network(&self) -> Network;
/// Main listen loop
fn start(&self) -> Result<(Receiver<SocketResponse>, Socket)> {
fn start(&self) -> io::Result<(Receiver<message::SocketResponse>, Socket)> {
// Open socket
let mut ret_sock = Socket::new(self.network());
match ret_sock.connect(self.peer(), self.port()) {
Ok(_) => {},
Err(_) => return Err(Error::new(ErrorKind::ConnectionFailed,
"Listener connection failed", None))
Err(_) => return Err(io::Error::new(io::ErrorKind::ConnectionFailed,
"Listener connection failed", None))
}
let mut sock = ret_sock.clone();
@ -52,7 +52,7 @@ pub trait Listener {
try!(sock.send_message(version_message));
// Message loop
spawn(move || {
thread::spawn(move || {
let mut handshake_complete = false;
let mut sock = sock;
loop {
@ -76,7 +76,7 @@ pub trait Listener {
// We have to pass the message to the main thread for processing,
// unfortunately, because sipa says we have to handle everything
// in order.
recv_tx.send(MessageReceived(payload));
recv_tx.send(message::SocketResponse::MessageReceived(payload));
}
Err(e) => {
// On failure we send an error message to the main thread, along with
@ -84,7 +84,7 @@ pub trait Listener {
// thread. (If we simply exited immediately, the channel would be torn
// down and the main thread would never see the error message.)
let (tx, rx) = channel();
recv_tx.send(message::ConnectionFailed(e, tx));
recv_tx.send(message::SocketResponse::ConnectionFailed(e, tx));
rx.recv();
break;
}

View File

@ -20,7 +20,9 @@
//!
use collections::Vec;
use std::iter;
use std::io::{self, Cursor};
use std::sync::mpsc::Sender;
use blockdata::block;
use blockdata::transaction;
@ -50,7 +52,7 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for CommandString {
#[inline]
fn consensus_decode(d: &mut D) -> Result<CommandString, E> {
let rawbytes: [u8; 12] = try!(ConsensusDecodable::consensus_decode(d));
let rv = FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None }));
let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None }));
Ok(CommandString(rv))
}
}

View File

@ -27,11 +27,11 @@ use util::hash::Sha256dHash;
/// The type of an inventory object
pub enum InvType {
/// Error --- these inventories can be ignored
InvError,
Error,
/// Transaction
InvTransaction,
Transaction,
/// Block
InvBlock
Block
}
// Some simple messages
@ -101,9 +101,9 @@ impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for Inventory {
#[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
try!(match self.inv_type {
InvError => 0u32,
InvTransaction => 1,
InvBlock => 2
InvType::Error => 0u32,
InvType::Transaction => 1,
InvType::Block => 2
}.consensus_encode(s));
self.hash.consensus_encode(s)
}
@ -115,9 +115,9 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Inventory {
let int_type: u32 = try!(ConsensusDecodable::consensus_decode(d));
Ok(Inventory {
inv_type: match int_type {
0 => InvError,
1 => InvTransaction,
2 => InvBlock,
0 => InvType::Error,
1 => InvType::Transaction,
2 => InvType::Block,
// TODO do not fail here
_ => { panic!("bad inventory type field") }
},

View File

@ -47,15 +47,6 @@ impl ::std::fmt::Debug for Sha256dHash {
pub struct Ripemd160Hash([u8; 20]);
impl_array_newtype!(Ripemd160Hash, u8, 20);
/// A "hasher" which just truncates and adds data to its state. Should
/// only be used for hashtables indexed by "already random" data such
/// as SHA2 hashes
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct DumbHasher;
/// The state of a `DumbHasher`
pub struct DumbHasherState([u8; 8]);
/// A 32-bit hash obtained by truncating a real hash
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Hash32((u8, u8, u8, u8));
@ -68,44 +59,6 @@ pub struct Hash48((u8, u8, u8, u8, u8, u8));
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Hash64((u8, u8, u8, u8, u8, u8, u8, u8));
// Allow these to be used as a key for Rust's HashMap et. al.
impl hash::Hash<DumbHasherState> for Sha256dHash {
#[inline]
fn hash(&self, state: &mut DumbHasherState) {
let &Sha256dHash(ref hash) = self;
let &DumbHasherState(ref mut arr) = state;
for i in 0..8 {
arr[i] += hash[i];
}
}
}
impl hash::Hasher<DumbHasherState> for DumbHasher {
#[inline]
fn hash<T: hash::Hash<DumbHasherState>>(&self, value: &T) -> u64 {
let mut ret = DumbHasherState([0; 8]);
value.hash(&mut ret);
let DumbHasherState(res) = ret;
LittleEndian::read_u64(&res[0..8])
}
}
impl hash::Writer for DumbHasherState {
#[inline]
fn write(&mut self, msg: &[u8]) {
let &DumbHasherState(ref mut arr) = self;
for (n, &ch) in msg.iter().enumerate() {
arr[n % 8] += ch;
}
}
}
impl Default for DumbHasher {
#[inline]
fn default() -> DumbHasher { DumbHasher }
}
impl Ripemd160Hash {
/// Create a hash by hashing some data
pub fn from_data(data: &[u8]) -> Ripemd160Hash {

View File

@ -238,8 +238,8 @@ impl<K:BitArray+cmp::Eq+Zero+One+ops::BitXor<K,K>+ops::Shl<usize,K>+ops::Shr<usi
}
match (tree.child_l.take(), tree.child_r.take()) {
(Some(_), Some(_)) => unreachable!(),
(Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })), None) |
(None, Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len }))) => {
(Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len }), None) |
(None, Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })) => {
tree.data = data;
tree.child_l = child_l;
tree.child_r = child_r;
@ -296,8 +296,8 @@ impl<K:BitArray+cmp::Eq+Zero+One+ops::BitXor<K,K>+ops::Shl<usize,K>+ops::Shr<usi
return (false, ret);
}
// One child? Consolidate
(bit, Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })), None) |
(bit, None, Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len }))) => {
(bit, Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len }), None) |
(bit, None, Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })) => {
tree.data = data;
tree.child_l = child_l;
tree.child_r = child_r;

View File

@ -22,7 +22,7 @@ use crypto::sha2::Sha256;
use blockdata::script::Script;
use blockdata::opcodes;
use network::constants::Network::{self, Bitcoin, BitcoinTestnet};
use network::constants::Network;
use util::hash::Ripemd160Hash;
use util::base58::{self, FromBase58, ToBase58};
@ -89,8 +89,8 @@ impl ToBase58 for Address {
fn base58_layout(&self) -> Vec<u8> {
let mut ret = vec![
match self.network {
Bitcoin => 0,
BitcoinTestnet => 111
Network::Bitcoin => 0,
Network::Testnet => 111
}
];
ret.push_all(self.hash.as_slice());
@ -106,8 +106,8 @@ impl FromBase58 for Address {
Ok(Address {
network: match data[0] {
0 => Bitcoin,
111 => BitcoinTestnet,
0 => Network::Bitcoin,
111 => Network::Testnet,
x => { return Err(base58::Error::InvalidVersion(vec![x])); }
},
hash: Ripemd160Hash::from_slice(data.slice_from(1))

View File

@ -30,7 +30,7 @@ use blockdata::script::Script;
use network::constants::Network;
use wallet::address::Address;
use wallet::wallet::Wallet;
use util::hash::{DumbHasher, Sha256dHash};
use util::hash::Sha256dHash;
/// The type of a wallet-spendable txout
#[derive(Clone, PartialEq, Eq, Debug)]
@ -61,7 +61,7 @@ pub struct WalletTxOut {
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct AddressIndex {
tentative_index: HashMap<Script, Vec<WalletTxOut>>,
index: HashMap<(Sha256dHash, u32), Vec<WalletTxOut>, DumbHasher>,
index: HashMap<(Sha256dHash, u32), Vec<WalletTxOut>, SipHasher>,
network: Network,
k1: u64,
k2: u64
@ -74,7 +74,7 @@ impl AddressIndex {
let (k1, k2) = wallet.siphash_key();
let mut ret = AddressIndex {
tentative_index: HashMap::with_capacity(utxo_set.n_utxos() / 256),
index: HashMap::with_hasher(DumbHasher),
index: HashMap::with_hasher(SipHasher::new()),
network: wallet.network(),
k1: k1,
k2: k2

View File

@ -29,7 +29,7 @@ use crypto::sha2::Sha512;
use secp256k1::key::{PublicKey, SecretKey};
use secp256k1;
use network::constants::Network::{self, Bitcoin, BitcoinTestnet};
use network::constants::Network;
use util::base58;
use util::base58::{FromBase58, ToBase58};
@ -288,8 +288,8 @@ impl ToBase58 for ExtendedPrivKey {
fn base58_layout(&self) -> Vec<u8> {
let mut ret = Vec::with_capacity(78);
ret.push_all(match self.network {
Bitcoin => [0x04, 0x88, 0xAD, 0xE4],
BitcoinTestnet => [0x04, 0x35, 0x83, 0x94]
Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4],
Network::Testnet => [0x04, 0x35, 0x83, 0x94]
});
ret.push(self.depth as u8);
ret.push_all(self.parent_fingerprint.as_slice());
@ -320,8 +320,8 @@ impl FromBase58 for ExtendedPrivKey {
Ok(ExtendedPrivKey {
network: match data.slice_to(4) {
[0x04, 0x88, 0xAD, 0xE4] => Bitcoin,
[0x04, 0x35, 0x83, 0x94] => BitcoinTestnet,
[0x04, 0x88, 0xAD, 0xE4] => Network::Bitcoin,
[0x04, 0x35, 0x83, 0x94] => Network::Testnet,
_ => { return Err(base58::Error::InvalidVersion(data.slice_to(4).to_vec())); }
},
depth: data[4],
@ -340,8 +340,8 @@ impl ToBase58 for ExtendedPubKey {
assert!(self.public_key.is_compressed());
let mut ret = Vec::with_capacity(78);
ret.push_all(match self.network {
Bitcoin => [0x04, 0x88, 0xB2, 0x1E],
BitcoinTestnet => [0x04, 0x35, 0x87, 0xCF]
Network::Bitcoin => [0x04, 0x88, 0xB2, 0x1E],
Network::Testnet => [0x04, 0x35, 0x87, 0xCF]
});
ret.push(self.depth as u8);
ret.push_all(self.parent_fingerprint.as_slice());
@ -371,8 +371,8 @@ impl FromBase58 for ExtendedPubKey {
Ok(ExtendedPubKey {
network: match data.slice_to(4) {
[0x04, 0x88, 0xB2, 0x1E] => Bitcoin,
[0x04, 0x35, 0x87, 0xCF] => BitcoinTestnet,
[0x04, 0x88, 0xB2, 0x1E] => Network::Bitcoin,
[0x04, 0x35, 0x87, 0xCF] => Network::Testnet,
_ => { return Err(base58::Error::InvalidVersion(data.slice_to(4).to_vec())); }
},
depth: data[4],