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::num::Zero;
use std::{marker, ptr}; use std::{marker, num, ptr};
use blockdata::block::{Block, BlockHeader}; use blockdata::block::{Block, BlockHeader};
use blockdata::transaction::Transaction; use blockdata::transaction::Transaction;
use blockdata::constants::{DIFFCHANGE_INTERVAL, DIFFCHANGE_TIMESPAN, use blockdata::constants::{DIFFCHANGE_INTERVAL, DIFFCHANGE_TIMESPAN,
TARGET_BLOCK_SPACING, max_target, genesis_block}; TARGET_BLOCK_SPACING, max_target, genesis_block};
use network::constants::Network::{self, BitcoinTestnet}; use network::constants::Network;
use network::encodable::{ConsensusDecodable, ConsensusEncodable}; use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::serialize::{BitcoinHash, SimpleDecoder, SimpleEncoder}; use network::serialize::{BitcoinHash, SimpleDecoder, SimpleEncoder};
use util::BitArray; use util::BitArray;
@ -462,7 +462,7 @@ impl Blockchain {
// Compute new target // Compute new target
let mut target = unsafe { (*prev).block.header.target() }; let mut target = unsafe { (*prev).block.header.target() };
target = target.mul_u32(timespan); 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) // Clamp below MAX_TARGET (difficulty 1)
let max = max_target(self.network); let max = max_target(self.network);
if target > max { target = max }; if target > max { target = max };
@ -470,13 +470,13 @@ impl Blockchain {
satoshi_the_precision(&target) satoshi_the_precision(&target)
// On non-diffchange blocks, Testnet has a rule that any 20-minute-long // On non-diffchange blocks, Testnet has a rule that any 20-minute-long
// block intervals result the difficulty // 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 { block.header.time > unsafe { (*prev).block.header.time } + 2*TARGET_BLOCK_SPACING {
max_target(self.network) max_target(self.network)
// On the other hand, if we are in Testnet and the block interval is less // 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 // 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. // 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 // Scan back DIFFCHANGE_INTERVAL blocks
unsafe { unsafe {
let mut scan = prev; let mut scan = prev;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,9 @@
//! //!
use collections::Vec; use collections::Vec;
use std::iter;
use std::io::{self, Cursor}; use std::io::{self, Cursor};
use std::sync::mpsc::Sender;
use blockdata::block; use blockdata::block;
use blockdata::transaction; use blockdata::transaction;
@ -50,7 +52,7 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for CommandString {
#[inline] #[inline]
fn consensus_decode(d: &mut D) -> Result<CommandString, E> { fn consensus_decode(d: &mut D) -> Result<CommandString, E> {
let rawbytes: [u8; 12] = try!(ConsensusDecodable::consensus_decode(d)); 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)) Ok(CommandString(rv))
} }
} }

View File

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

View File

@ -47,15 +47,6 @@ impl ::std::fmt::Debug for Sha256dHash {
pub struct Ripemd160Hash([u8; 20]); pub struct Ripemd160Hash([u8; 20]);
impl_array_newtype!(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 /// A 32-bit hash obtained by truncating a real hash
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct Hash32((u8, u8, u8, u8)); 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)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct Hash64((u8, u8, u8, u8, u8, u8, u8, u8)); 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 { impl Ripemd160Hash {
/// Create a hash by hashing some data /// Create a hash by hashing some data
pub fn from_data(data: &[u8]) -> Ripemd160Hash { 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()) { match (tree.child_l.take(), tree.child_r.take()) {
(Some(_), Some(_)) => unreachable!(), (Some(_), Some(_)) => unreachable!(),
(Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })), None) | (Some(box 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 }))) => { (None, Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })) => {
tree.data = data; tree.data = data;
tree.child_l = child_l; tree.child_l = child_l;
tree.child_r = child_r; 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); return (false, ret);
} }
// One child? Consolidate // One child? Consolidate
(bit, Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })), None) | (bit, Some(box 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, None, Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })) => {
tree.data = data; tree.data = data;
tree.child_l = child_l; tree.child_l = child_l;
tree.child_r = child_r; tree.child_r = child_r;

View File

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

View File

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

View File

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