Checkpoint commit; tons of disorganized changes for rustc

BTW after all this is done I'm gonna indent the entire codebase...
so `git blame` is gonna be totally broken anyway, hence my
capricious cadence of commits.
This commit is contained in:
Andrew Poelstra 2015-04-05 12:58:49 -05:00
parent 160f2f9ea6
commit 7738722ab5
19 changed files with 627 additions and 586 deletions

View File

@ -23,7 +23,7 @@
//!
use std::num::Zero;
use std::marker;
use std::{marker, ptr};
use blockdata::block::{Block, BlockHeader};
use blockdata::transaction::Transaction;
@ -102,8 +102,8 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for BlockchainNode {
required_difficulty: try!(ConsensusDecodable::consensus_decode(d)),
height: try!(ConsensusDecodable::consensus_decode(d)),
has_txdata: try!(ConsensusDecodable::consensus_decode(d)),
prev: RawPtr::null(),
next: RawPtr::null()
prev: ptr::null(),
next: ptr::null()
})
}
}
@ -159,7 +159,7 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Blockchain {
let prevptr =
match unsafe { (*raw_tree).lookup(&hash, 256) } {
Some(node) => &**node as NodePtr,
None => RawPtr::null()
None => ptr::null()
};
node.prev = prevptr;
}
@ -191,7 +191,7 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Blockchain {
}
// TODO: this should maybe be public, in which case it needs to be tagged
// with a ContravariantLifetime marker tying it to the tree's lifetime.
// with a PhantomData marker tying it to the tree's lifetime.
struct LocatorHashIter {
index: NodePtr,
count: usize,
@ -215,7 +215,7 @@ impl Iterator<Sha256dHash> for LocatorHashIter {
self.index = unsafe { (*self.index).prev };
// If we are not at the genesis, rewind `self.skip` times, or until we are.
if self.index.is_not_null() {
for _ in range(1, self.skip) {
for _ in 1..self.skip {
unsafe {
if (*self.index).prev.is_null() {
break;
@ -241,7 +241,7 @@ pub struct BlockIter<'tree> {
// mutable blockchain methods call .mut_borrow() on the block
// links, which would blow up if the iterator did a regular
// borrow at the same time.
marker: marker::ContravariantLifetime<'tree>
marker: marker::PhantomData<&'tree Blockchain>
}
/// An iterator over blocks in reverse blockheight order. Note that this
@ -253,7 +253,7 @@ pub struct BlockIter<'tree> {
pub struct RevBlockIter<'tree> {
index: NodePtr,
// See comment in BlockIter for why we need this
marker: marker::ContravariantLifetime<'tree>
marker: marker::PhantomData<&'tree Blockchain>
}
/// An iterator over blocks in reverse blockheight order, which yielding only
@ -313,7 +313,7 @@ impl<'tree> Iterator<&'tree Block> for RevStaleBlockIter<'tree> {
if next_index.is_not_null() &&
(*next_index).next != self.index &&
(&*next_index).is_on_main_chain(self.chain) {
self.index = RawPtr::null();
self.index = ptr::null();
} else {
self.index = next_index;
}
@ -348,8 +348,8 @@ impl Blockchain {
block: genesis,
height: 0,
has_txdata: true,
prev: RawPtr::null(),
next: RawPtr::null()
prev: ptr::null(),
next: ptr::null()
});
let raw_ptr = &*new_node as NodePtr;
Blockchain {
@ -449,7 +449,7 @@ impl Blockchain {
let timespan = unsafe {
// Scan back DIFFCHANGE_INTERVAL blocks
let mut scan = prev;
for _ in range(0, DIFFCHANGE_INTERVAL - 1) {
for _ in 0..(DIFFCHANGE_INTERVAL - 1) {
scan = (*scan).prev;
}
// Get clamped timespan between first and last blocks
@ -498,7 +498,7 @@ impl Blockchain {
height: unsafe { (*prev).height + 1 },
has_txdata: has_txdata,
prev: prev,
next: RawPtr::null()
next: ptr::null()
});
unsafe {
let prev = prev as *mut BlockchainNode;
@ -568,11 +568,11 @@ impl Blockchain {
pub fn iter<'a>(&'a self, start_hash: Sha256dHash) -> BlockIter<'a> {
let start = match self.tree.lookup(&start_hash.into_le(), 256) {
Some(boxptr) => &**boxptr as NodePtr,
None => RawPtr::null()
None => ptr::null()
};
BlockIter {
index: start,
marker: marker::ContravariantLifetime::<'a>
marker: marker::PhantomData
}
}
@ -580,11 +580,11 @@ impl Blockchain {
pub fn rev_iter<'a>(&'a self, start_hash: Sha256dHash) -> RevBlockIter<'a> {
let start = match self.tree.lookup(&start_hash.into_le(), 256) {
Some(boxptr) => &**boxptr as NodePtr,
None => RawPtr::null()
None => ptr::null()
};
RevBlockIter {
index: start,
marker: marker::ContravariantLifetime::<'a>
marker: marker::PhantomData
}
}
@ -594,12 +594,12 @@ impl Blockchain {
Some(boxptr) => {
// If we are already on the main chain, we have a dead iterator
if boxptr.is_on_main_chain(self) {
RawPtr::null()
ptr::null()
} else {
&**boxptr as NodePtr
}
}
None => RawPtr::null()
None => ptr::null()
};
RevStaleBlockIter {
index: start,

View File

@ -564,7 +564,7 @@ impl All {
/// Classifies an Opcode into a broad class
#[inline]
pub fn classify(&self) -> OpcodeClass {
pub fn classify(&self) -> Class {
// 17 opcodes
if *self == All::OP_VERIF || *self == All::OP_VERNOTIF ||
*self == All::OP_CAT || *self == All::OP_SUBSTR ||
@ -574,30 +574,30 @@ impl All {
*self == All::OP_2MUL || *self == All::OP_2DIV ||
*self == All::OP_MUL || *self == All::OP_DIV || *self == All::OP_MOD ||
*self == All::OP_LSHIFT || *self == All::OP_RSHIFT {
OpcodeClass::IllegalOp
Class::IllegalOp
// 11 opcodes
} else if *self == All::OP_NOP ||
(All::OP_NOP1 as u8 <= *self as u8 &&
*self as u8 <= All::OP_NOP10 as u8) {
OpcodeClass::NoOp
Class::NoOp
// 75 opcodes
} else if *self == All::OP_RESERVED || *self == All::OP_VER || *self == All::OP_RETURN ||
*self == All::OP_RESERVED1 || *self == All::OP_RESERVED2 ||
*self as u8 >= All::OP_RETURN_186 as u8 {
OpcodeClass::ReturnOp
Class::ReturnOp
// 1 opcode
} else if *self == All::OP_PUSHNUM_NEG1 {
OpcodeClass::PushNum(-1)
Class::PushNum(-1)
// 16 opcodes
} else if All::OP_PUSHNUM_1 as u8 <= *self as u8 &&
*self as u8 <= All::OP_PUSHNUM_16 as u8 {
OpcodeClass::PushNum(1 + *self as isize - OP_PUSHNUM_1 as isize)
Class::PushNum(1 + *self as isize - All::OP_PUSHNUM_1 as isize)
// 76 opcodes
} else if *self as u8 <= All::OP_PUSHBYTES_75 as u8 {
OpcodeClass::PushBytes(*self as usize)
Class::PushBytes(*self as usize)
// 60 opcodes
} else {
OpcodeClass::Ordinary(unsafe { transmute(*self) })
Class::Ordinary(unsafe { transmute(*self) })
}
}
}
@ -629,7 +629,7 @@ pub static OP_TRUE: All = OP_PUSHNUM_1;
/// Broad categories of opcodes with similar behavior
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum OpcodeClass {
pub enum Class {
/// Pushes the given number onto the stack
PushNum(isize),
/// Pushes the given number of bytes onto the stack
@ -644,7 +644,7 @@ pub enum OpcodeClass {
Ordinary(Ordinary)
}
impl json::ToJson for OpcodeClass {
impl json::ToJson for Class {
fn to_json(&self) -> json::Json {
json::String(self.to_string())
}

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@ use std::default::Default;
use serialize::json;
use util::hash::Sha256dHash;
use blockdata::script::{self, Script, ScriptError, ScriptTrace, read_scriptbool};
use blockdata::script::{self, Script, ScriptTrace, read_scriptbool};
use blockdata::utxoset::UtxoSet;
use network::encodable::ConsensusEncodable;
use network::serialize::BitcoinHash;
@ -81,9 +81,9 @@ impl TxOut {
if self.script_pubkey.len() == 25 &&
self.script_pubkey.slice_to(3) == &[0x76, 0xa9, 0x14] &&
self.script_pubkey.slice_from(23) == &[0x88, 0xac] {
PayToPubkeyHash(self.script_pubkey.slice(3, 23).to_address(network))
ScriptPubkeyTemplate::PayToPubkeyHash(self.script_pubkey.slice(3, 23).to_address(network))
} else {
Unknown
ScriptPubkeyTemplate::Unknown
}
}
}
@ -104,13 +104,13 @@ pub struct Transaction {
/// A transaction error
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum TransactionError {
pub enum Error {
/// Concatenated script failed in the input half (script error)
InputScriptFailure(ScriptError),
InputScriptFailure(script::Error),
/// Concatenated script failed in the output half (script error)
OutputScriptFailure(ScriptError),
OutputScriptFailure(script::Error),
/// P2SH serialized script failed (script error)
P2shScriptFailure(ScriptError),
P2shScriptFailure(script::Error),
/// P2SH serialized script ended with false at the top of the stack
P2shScriptReturnedFalse,
/// P2SH serialized script ended with nothing in the stack
@ -123,7 +123,7 @@ pub enum TransactionError {
InputNotFound(Sha256dHash, u32),
}
impl json::ToJson for TransactionError {
impl json::ToJson for Error {
fn to_json(&self) -> json::Json {
json::String(self.to_string())
}
@ -137,7 +137,7 @@ pub struct InputTrace {
sig_trace: ScriptTrace,
pubkey_trace: Option<ScriptTrace>,
p2sh_trace: Option<ScriptTrace>,
error: Option<TransactionError>
error: Option<Error>
}
impl_json!(ScriptTrace, script, initial_stack, iterations, error);
@ -158,7 +158,7 @@ impl TxIn {
pub fn validate(&self,
utxoset: &UtxoSet,
txn: &Transaction,
index: usize) -> Result<(), TransactionError> {
index: usize) -> Result<(), Error> {
let txo = utxoset.get_utxo(self.prev_hash, self.prev_index);
match txo {
Some((_, txo)) => {
@ -168,7 +168,7 @@ impl TxIn {
let mut stack = Vec::with_capacity(6);
match self.script_sig.evaluate(&mut stack, Some((txn, index)), None) {
Ok(_) => {}
Err(e) => { return Err(InputScriptFailure(e)); }
Err(e) => { return Err(Error::InputScriptFailure(e)); }
}
if txo.script_pubkey.is_p2sh() && stack.len() > 0 {
p2sh_stack = stack.clone();
@ -180,32 +180,32 @@ impl TxIn {
}
match txo.script_pubkey.evaluate(&mut stack, Some((txn, index)), None) {
Ok(_) => {}
Err(e) => { return Err(OutputScriptFailure(e)); }
Err(e) => { return Err(Error::OutputScriptFailure(e)); }
}
match stack.pop() {
Some(v) => {
if !read_scriptbool(v.as_slice()) {
return Err(ScriptReturnedFalse);
return Err(Error::ScriptReturnedFalse);
}
}
None => { return Err(ScriptReturnedEmptyStack); }
None => { return Err(Error::ScriptReturnedEmptyStack); }
}
if txo.script_pubkey.is_p2sh() {
match p2sh_script.evaluate(&mut p2sh_stack, Some((txn, index)), None) {
Ok(_) => {}
Err(e) => { return Err(P2shScriptFailure(e)); }
Err(e) => { return Err(Error::P2shScriptFailure(e)); }
}
match p2sh_stack.pop() {
Some(v) => {
if !read_scriptbool(v.as_slice()) {
return Err(P2shScriptReturnedFalse);
return Err(Error::P2shScriptReturnedFalse);
}
}
None => { return Err(P2shScriptReturnedEmptyStack); }
None => { return Err(Error::P2shScriptReturnedEmptyStack); }
}
}
}
None => { return Err(InputNotFound(self.prev_hash, self.prev_index)); }
None => { return Err(Error::InputNotFound(self.prev_hash, self.prev_index)); }
}
Ok(())
}
@ -213,7 +213,7 @@ impl TxIn {
impl Transaction {
/// Check a transaction for validity
pub fn validate(&self, utxoset: &UtxoSet) -> Result<(), TransactionError> {
pub fn validate(&self, utxoset: &UtxoSet) -> Result<(), Error> {
for (n, input) in self.input.iter().enumerate() {
try!(input.validate(utxoset, self, n));
}
@ -249,7 +249,7 @@ impl Transaction {
let mut stack = Vec::with_capacity(6);
trace.sig_trace = input.script_sig.trace(&mut stack, Some((self, n)));
let err = trace.sig_trace.error.as_ref().map(|e| e.clone());
err.map(|e| trace.error = Some(InputScriptFailure(e)));
err.map(|e| trace.error = Some(Error::InputScriptFailure(e)));
if txo.script_pubkey.is_p2sh() && stack.len() > 0 {
p2sh_stack = stack.clone();
@ -262,32 +262,32 @@ impl Transaction {
if trace.error.is_none() {
trace.pubkey_trace = Some(txo.script_pubkey.trace(&mut stack, Some((self, n))));
let err = trace.pubkey_trace.as_ref().unwrap().error.as_ref().map(|e| e.clone());
err.map(|e| trace.error = Some(OutputScriptFailure(e)));
err.map(|e| trace.error = Some(Error::OutputScriptFailure(e)));
match stack.pop() {
Some(v) => {
if !read_scriptbool(v.as_slice()) {
trace.error = Some(ScriptReturnedFalse);
trace.error = Some(Error::ScriptReturnedFalse);
}
}
None => { trace.error = Some(ScriptReturnedEmptyStack); }
None => { trace.error = Some(Error::ScriptReturnedEmptyStack); }
}
if trace.error.is_none() && txo.script_pubkey.is_p2sh() {
trace.p2sh_trace = Some(p2sh_script.trace(&mut p2sh_stack, Some((self, n))));
let err = trace.p2sh_trace.as_ref().unwrap().error.as_ref().map(|e| e.clone());
err.map(|e| trace.error = Some(P2shScriptFailure(e)));
err.map(|e| trace.error = Some(Error::P2shScriptFailure(e)));
match p2sh_stack.pop() {
Some(v) => {
if !read_scriptbool(v.as_slice()) {
trace.error = Some(P2shScriptReturnedFalse);
trace.error = Some(Error::P2shScriptReturnedFalse);
}
}
None => { trace.error = Some(P2shScriptReturnedEmptyStack); }
None => { trace.error = Some(Error::P2shScriptReturnedEmptyStack); }
}
}
}
}
None => {
trace.error = Some(InputNotFound(input.prev_hash, input.prev_index));
trace.error = Some(Error::InputNotFound(input.prev_hash, input.prev_index));
}
}
ret.inputs.push(trace);

View File

@ -26,8 +26,7 @@ use std::mem;
use num_cpus;
use std::sync::Future;
use blockdata::transaction::{Transaction, TxOut};
use blockdata::transaction::TransactionError::{self, InputNotFound};
use blockdata::transaction::{self, Transaction, TxOut};
use blockdata::constants::genesis_block;
use blockdata::block::Block;
use network::constants::Network;
@ -38,24 +37,24 @@ use util::hash::{DumbHasher, Sha256dHash};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub enum ValidationLevel {
/// Blindly update the UTXO set (NOT recommended)
NoValidation,
Nothing,
/// Check that the blocks are at least in the right order
ChainValidation,
Chain,
/// Check that any inputs are actually txouts in the set
TxoValidation,
Inputs,
/// Execute the scripts and ensure they pass
ScriptValidation
Script
}
/// An error returned from a UTXO set operation
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum UtxoSetError {
pub enum Error {
/// prevhash of the new block is not the hash of the old block (expected, actual)
BadPrevHash(Sha256dHash, Sha256dHash),
/// A TXID was duplicated
DuplicatedTxid(Sha256dHash),
/// A tx was invalid (txid, error)
InvalidTx(Sha256dHash, TransactionError),
InvalidTx(Sha256dHash, transaction::Error),
}
struct UtxoNode {
@ -203,11 +202,11 @@ impl UtxoSet {
/// Apply the transactions contained in a block
pub fn update(&mut self, block: &Block, blockheight: usize, validation: ValidationLevel)
-> Result<(), UtxoSetError> {
-> Result<(), Error> {
// Make sure we are extending the UTXO set in order
if validation >= ChainValidation &&
if validation >= ValidationLevel::Chain &&
self.last_hash != block.header.prev_blockhash {
return Err(BadPrevHash(self.last_hash, block.header.prev_blockhash));
return Err(Error::BadPrevHash(self.last_hash, block.header.prev_blockhash));
}
// Set the next hash immediately so that if anything goes wrong,
@ -247,7 +246,7 @@ impl UtxoSet {
}
// Otherwise fail the block
self.rewind(block);
return Err(DuplicatedTxid(txid));
return Err(Error::DuplicatedTxid(txid));
}
}
// Didn't replace anything? Good.
@ -256,12 +255,12 @@ impl UtxoSet {
}
// If we are validating scripts, do all that now in parallel
if validation >= ScriptValidation {
if validation >= ValidationLevel::Script {
let mut future_vec = Vec::with_capacity(block.txdata.len() - 1);
// skip the genesis since we don't validate this script. (TODO this might
// be a consensus bug since we don't even check that the opcodes make sense.)
let n_threads = cmp::min(block.txdata.len() - 1, num_cpus::get());
for j in range(0, n_threads) {
for j in 0..n_threads {
let n_elems = block.txdata.len() - 1;
let start = 1 + j * n_elems / n_threads;
let end = cmp::min(n_elems, 1 + (j + 1) * n_elems / n_threads);
@ -273,7 +272,7 @@ impl UtxoSet {
for tx in txes.slice(start, end).iter() {
match tx.validate(unsafe {&*s}) {
Ok(_) => {},
Err(e) => { return Err(InvalidTx(tx.bitcoin_hash(), e)); }
Err(e) => { return Err(Error::InvalidTx(tx.bitcoin_hash(), e)); }
}
}
Ok(())
@ -301,10 +300,10 @@ impl UtxoSet {
match taken {
Some(txo) => { self.spent_txos.get_mut(spent_idx).push(((txid, n as u32), txo)); }
None => {
if validation >= TxoValidation {
if validation >= ValidationLevel::Inputs {
self.rewind(block);
return Err(InvalidTx(txid,
InputNotFound(input.prev_hash, input.prev_index)));
return Err(Error::InvalidTx(txid,
transaction::Error::InputNotFound(input.prev_hash, input.prev_index)));
}
}
}
@ -333,7 +332,7 @@ impl UtxoSet {
let mut skipped_genesis = false;
for tx in block.txdata.iter() {
let txhash = tx.bitcoin_hash();
for n in range(0, tx.output.len()) {
for n in 0..tx.output.len() {
// Just bomb out the whole transaction
// TODO: this does not conform to BIP30: if a duplicate txid occurs,
// the block will be (rightly) rejected, causing it to be
@ -424,7 +423,7 @@ mod tests {
use std::io::IoResult;
use serialize::hex::FromHex;
use super::{UtxoSet, TxoValidation};
use super::{UtxoSet, ValidationLevel};
use blockdata::block::Block;
use network::constants::Network::Bitcoin;
@ -437,7 +436,7 @@ mod tests {
let new_block: Block = deserialize("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000".from_hex().unwrap()).unwrap();
// Make sure we can't add the block directly, since we are missing the inputs
assert!(empty_set.update(&new_block, 1, TxoValidation).is_err());
assert!(empty_set.update(&new_block, 1, ValidationLevel::Inputs).is_err());
assert_eq!(empty_set.n_utxos(), 0);
// Add the block manually so that we'll have some UTXOs for the rest of the test
for tx in new_block.txdata.iter() {
@ -457,7 +456,7 @@ mod tests {
// Check again that we can't add the block, and that this doesn't mess up the
// existing UTXOs
assert!(empty_set.update(&new_block, 2, TxoValidation).is_err());
assert!(empty_set.update(&new_block, 2, ValidationLevel::Inputs).is_err());
assert_eq!(empty_set.n_utxos(), 2);
for tx in new_block.txdata.iter() {
let hash = tx.bitcoin_hash();
@ -497,7 +496,7 @@ mod tests {
for tx in new_block.txdata.iter() {
let hash = tx.bitcoin_hash();
for n in range(0, tx.output.len()) {
for n in 0..tx.output.len() {
let n = n as u32;
let ret = read_again.take_utxo(hash, n);
assert_eq!(ret, None);

View File

@ -46,7 +46,6 @@
extern crate alloc;
extern crate byteorder;
extern crate collections;
extern crate core;
extern crate num_cpus;
extern crate rand;
extern crate rustc_serialize as serialize;

View File

@ -107,7 +107,7 @@ macro_rules! user_enum {
impl <D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for $name {
fn decode(d: &mut D) -> Result<$name, E> {
let s = try!(d.read_str());
$( if s.as_slice() == $txt { Ok($elem) } )else*
$( if s.as_slice() == $txt { Ok($name::$elem) } )else*
else { Err(d.error(format!("unknown `{}`", s).as_slice())) }
}
}

View File

@ -28,7 +28,7 @@ pub struct Address {
/// Services provided by the peer whose address this is
pub services: u64,
/// Network byte-order ipv6 address, or ipv4-mapped ipv6 address
pub address: [u8; 16],
pub address: [u16; 8],
/// Network port
pub port: u16
}

View File

@ -40,8 +40,8 @@ pub const USER_AGENT: &'static str = "bitcoin-rust v0.1";
/// at the start of every message
pub fn magic(network: Network) -> u32 {
match network {
Bitcoin => 0xD9B4BEF9,
BitcoinTestnet => 0x0709110B
Network::Bitcoin => 0xD9B4BEF9,
Network::BitcoinTestnet => 0x0709110B
// Note: any new entries here must be added to `deserialize` below
}
}
@ -58,8 +58,8 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Network {
fn consensus_decode(d: &mut D) -> Result<Network, E> {
let magic: u32 = try!(ConsensusDecodable::consensus_decode(d));
match magic {
0xD9B4BEF9 => Ok(Bitcoin),
0x0709110B => Ok(BitcoinTestnet),
0xD9B4BEF9 => Ok(Network::Bitcoin),
0x0709110B => Ok(Network::BitcoinTestnet),
x => Err(d.error(format!("Unknown network (magic {:x})", x).as_slice()))
}
}
@ -67,17 +67,17 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Network {
#[cfg(test)]
mod tests {
use super::Network::{self, Bitcoin, BitcoinTestnet};
use super::Network;
use network::serialize::{deserialize, serialize};
#[test]
fn serialize_test() {
assert_eq!(serialize(&Bitcoin).unwrap(), vec![0xf9, 0xbe, 0xb4, 0xd9]);
assert_eq!(serialize(&BitcoinTestnet).unwrap(), vec![0x0b, 0x11, 0x09, 0x07]);
assert_eq!(serialize(&Network::Bitcoin).unwrap(), vec![0xf9, 0xbe, 0xb4, 0xd9]);
assert_eq!(serialize(&Network::BitcoinTestnet).unwrap(), vec![0x0b, 0x11, 0x09, 0x07]);
assert_eq!(deserialize(vec![0xf9, 0xbe, 0xb4, 0xd9]), Ok(Bitcoin));
assert_eq!(deserialize(vec![0x0b, 0x11, 0x09, 0x07]), Ok(BitcoinTestnet));
assert_eq!(deserialize(vec![0xf9, 0xbe, 0xb4, 0xd9]), Ok(Network::Bitcoin));
assert_eq!(deserialize(vec![0x0b, 0x11, 0x09, 0x07]), Ok(Network::BitcoinTestnet));
let bad: Result<Network, _> = deserialize("fakenet".as_bytes().to_vec());
assert!(bad.is_err());

View File

@ -108,27 +108,27 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for u8 {
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for u16 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<u16, E> { d.read_u16().map(|n| Int::from_le(n)) }
fn consensus_decode(d: &mut D) -> Result<u16, E> { d.read_u16().map(|n| u16::from_le(n)) }
}
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for u32 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<u32, E> { d.read_u32().map(|n| Int::from_le(n)) }
fn consensus_decode(d: &mut D) -> Result<u32, E> { d.read_u32().map(|n| u32::from_le(n)) }
}
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for u64 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<u64, E> { d.read_u64().map(|n| Int::from_le(n)) }
fn consensus_decode(d: &mut D) -> Result<u64, E> { d.read_u64().map(|n| u64::from_le(n)) }
}
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for i32 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<i32, E> { d.read_i32().map(|n| Int::from_le(n)) }
fn consensus_decode(d: &mut D) -> Result<i32, E> { d.read_i32().map(|n| i32::from_le(n)) }
}
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for i64 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<i64, E> { d.read_i64().map(|n| Int::from_le(n)) }
fn consensus_decode(d: &mut D) -> Result<i64, E> { d.read_i64().map(|n| i64::from_le(n)) }
}
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for VarInt {
@ -136,9 +136,9 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for VarInt {
fn consensus_decode(d: &mut D) -> Result<VarInt, E> {
let n = try!(d.read_u8());
match n {
0xFF => d.read_u64().map(|n| VarInt(Int::from_le(n))),
0xFE => d.read_u32().map(|n| VarInt(Int::from_le(n) as u64)),
0xFD => d.read_u16().map(|n| VarInt(Int::from_le(n) as u64)),
0xFF => d.read_u64().map(|n| VarInt(u64::from_le(n))),
0xFE => d.read_u32().map(|n| VarInt(u32::from_le(n) as u64)),
0xFD => d.read_u16().map(|n| VarInt(u16::from_le(n) as u64)),
n => Ok(VarInt(n as u64))
}
}
@ -188,7 +188,7 @@ macro_rules! impl_array {
// Set everything to the first decode
let mut ret = [try!(ConsensusDecodable::consensus_decode(d)); $size];
// Set the rest
for i in range(1, $size) { ret[i] = try!(ConsensusDecodable::consensus_decode(d)); }
for i in 1..$size { ret[i] = try!(ConsensusDecodable::consensus_decode(d)); }
Ok(ret)
}
}
@ -224,7 +224,7 @@ impl<D:SimpleDecoder<E>, E, T:ConsensusDecodable<D, E>> ConsensusDecodable<D, E>
fn consensus_decode(d: &mut D) -> Result<Vec<T>, E> {
let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d));
let mut ret = Vec::with_capacity(len as usize);
for _ in range(0, len) { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
for _ in 0..len { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
Ok(ret)
}
}
@ -302,7 +302,7 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for CheckedData {
let len: u32 = try!(ConsensusDecodable::consensus_decode(d));
let checksum: [u8; 4] = try!(ConsensusDecodable::consensus_decode(d));
let mut ret = Vec::with_capacity(len as usize);
for _ in range(0, len) { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
for _ in 0..len { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
let expected_checksum = sha2_checksum(ret.as_slice());
if expected_checksum != checksum {
Err(d.error("bad checksum"))
@ -380,7 +380,7 @@ impl<D:SimpleDecoder<E>, E, T,
let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d));
let mut ret = HashMap::with_capacity_and_hasher(len as usize, Default::default());
for _ in range(0, len) {
for _ in 0..len {
ret.insert(try!(ConsensusDecodable::consensus_decode(d)),
try!(ConsensusDecodable::consensus_decode(d)));
}

View File

@ -114,19 +114,19 @@ pub enum NetworkMessage {
impl RawNetworkMessage {
fn command(&self) -> String {
match self.payload {
Version(_) => "version",
Verack => "verack",
Addr(_) => "addr",
Inv(_) => "inv",
GetData(_) => "getdata",
NotFound(_) => "notfound",
GetBlocks(_) => "getblocks",
GetHeaders(_) => "getheaders",
Tx(_) => "tx",
Block(_) => "block",
Headers(_) => "headers",
Ping(_) => "ping",
Pong(_) => "pong",
NetworkMessage::Version(_) => "version",
NetworkMessage::Verack => "verack",
NetworkMessage::Addr(_) => "addr",
NetworkMessage::Inv(_) => "inv",
NetworkMessage::GetData(_) => "getdata",
NetworkMessage::NotFound(_) => "notfound",
NetworkMessage::GetBlocks(_) => "getblocks",
NetworkMessage::GetHeaders(_) => "getheaders",
NetworkMessage::Tx(_) => "tx",
NetworkMessage::Block(_) => "block",
NetworkMessage::Headers(_) => "headers",
NetworkMessage::Ping(_) => "ping",
NetworkMessage::Pong(_) => "pong",
}.to_string()
}
}
@ -136,19 +136,19 @@ impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for RawNetworkMessage {
try!(self.magic.consensus_encode(s));
try!(CommandString(self.command()).consensus_encode(s));
try!(CheckedData(match self.payload {
Version(ref dat) => serialize(dat),
Verack => Ok(vec![]),
Addr(ref dat) => serialize(dat),
Inv(ref dat) => serialize(dat),
GetData(ref dat) => serialize(dat),
NotFound(ref dat) => serialize(dat),
GetBlocks(ref dat) => serialize(dat),
GetHeaders(ref dat) => serialize(dat),
Tx(ref dat) => serialize(dat),
Block(ref dat) => serialize(dat),
Headers(ref dat) => serialize(dat),
Ping(ref dat) => serialize(dat),
Pong(ref dat) => serialize(dat),
NetworkMessage::Version(ref dat) => serialize(dat),
NetworkMessage::Verack => Ok(vec![]),
NetworkMessage::Addr(ref dat) => serialize(dat),
NetworkMessage::Inv(ref dat) => serialize(dat),
NetworkMessage::GetData(ref dat) => serialize(dat),
NetworkMessage::NotFound(ref dat) => serialize(dat),
NetworkMessage::GetBlocks(ref dat) => serialize(dat),
NetworkMessage::GetHeaders(ref dat) => serialize(dat),
NetworkMessage::Tx(ref dat) => serialize(dat),
NetworkMessage::Block(ref dat) => serialize(dat),
NetworkMessage::Headers(ref dat) => serialize(dat),
NetworkMessage::Ping(ref dat) => serialize(dat),
NetworkMessage::Pong(ref dat) => serialize(dat),
}.unwrap()).consensus_encode(s));
Ok(())
}
@ -162,19 +162,19 @@ impl<D:SimpleDecoder<io::Error>> ConsensusDecodable<D, io::Error> for RawNetwork
let mut mem_d = RawDecoder::new(Cursor::new(raw_payload));
let payload = match cmd.as_slice() {
"version" => Version(try!(prepend_err("version", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"verack" => Verack,
"addr" => Addr(try!(prepend_err("addr", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"inv" => Inv(try!(prepend_err("inv", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"getdata" => GetData(try!(prepend_err("getdata", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"notfound" => NotFound(try!(prepend_err("notfound", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"getblocks" => GetBlocks(try!(prepend_err("getblocks", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"getheaders" => GetHeaders(try!(prepend_err("getheaders", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"block" => Block(try!(prepend_err("block", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"headers" => Headers(try!(prepend_err("headers", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"ping" => Ping(try!(prepend_err("ping", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"pong" => Ping(try!(prepend_err("pong", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"tx" => Tx(try!(prepend_err("tx", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"version" => NetworkMessage::Version(try!(prepend_err("version", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"verack" => NetworkMessage::Verack,
"addr" => NetworkMessage::Addr(try!(prepend_err("addr", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"inv" => NetworkMessage::Inv(try!(prepend_err("inv", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"getdata" => NetworkMessage::GetData(try!(prepend_err("getdata", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"notfound" => NetworkMessage::NotFound(try!(prepend_err("notfound", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"getblocks" => NetworkMessage::GetBlocks(try!(prepend_err("getblocks", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"getheaders" => NetworkMessage::GetHeaders(try!(prepend_err("getheaders", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"block" => NetworkMessage::Block(try!(prepend_err("block", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"headers" => NetworkMessage::Headers(try!(prepend_err("headers", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"ping" => NetworkMessage::Ping(try!(prepend_err("ping", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"pong" => NetworkMessage::Ping(try!(prepend_err("pong", ConsensusDecodable::consensus_decode(&mut mem_d)))),
"tx" => NetworkMessage::Tx(try!(prepend_err("tx", ConsensusDecodable::consensus_decode(&mut mem_d)))),
cmd => {
return Err(io::Error {
kind: io::ErrorKind::OtherError,

View File

@ -20,7 +20,7 @@
//!
use collections::Vec;
use std::io::{self, Cursor};
use std::io::{self, Cursor, Read, Write};
use serialize::hex::ToHex;
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
@ -39,14 +39,14 @@ impl BitcoinHash for Vec<u8> {
}
/// Encode an object into a vector
pub fn serialize<T: ConsensusEncodable<RawEncoder<MemWriter>, io::Error>>(obj: &T) -> io::Result<Vec<u8>> {
let mut encoder = RawEncoder::new(MemWriter::new());
pub fn serialize<T: ConsensusEncodable<RawEncoder<Cursor>, io::Error>>(obj: &T) -> io::Result<Vec<u8>> {
let mut encoder = RawEncoder::new(Cursor::new(vec![]));
try!(obj.consensus_encode(&mut encoder));
Ok(encoder.unwrap().unwrap())
}
/// Encode an object into a hex-encoded string
pub fn serialize_hex<T: ConsensusEncodable<RawEncoder<MemWriter>, io::Error>>(obj: &T) -> io::Result<String> {
pub fn serialize_hex<T: ConsensusEncodable<RawEncoder<Cursor>, io::Error>>(obj: &T) -> io::Result<String> {
let serial = try!(serialize(obj));
Ok(serial.as_slice().to_hex())
}
@ -67,7 +67,7 @@ pub struct RawDecoder<R> {
reader: R
}
impl<W:Writer> RawEncoder<W> {
impl<W:Write> RawEncoder<W> {
/// Constructor
pub fn new(writer: W) -> RawEncoder<W> {
RawEncoder { writer: writer }
@ -79,7 +79,7 @@ impl<W:Writer> RawEncoder<W> {
}
}
impl<R:Reader> RawDecoder<R> {
impl<R:Read> RawDecoder<R> {
/// Constructor
pub fn new(reader: R) -> RawDecoder<R> {
RawDecoder { reader: reader }
@ -144,7 +144,7 @@ pub trait SimpleDecoder<E> {
// TODO: trait reform: impl SimpleEncoder for every Encoder, ditto for Decoder
impl<W:Writer> SimpleEncoder<io::Error> for RawEncoder<W> {
impl<W:Write> SimpleEncoder<io::Error> for RawEncoder<W> {
#[inline]
fn emit_u64(&mut self, v: u64) -> io::Result<()> { self.writer.write_le_u64(v) }
#[inline]
@ -167,7 +167,7 @@ impl<W:Writer> SimpleEncoder<io::Error> for RawEncoder<W> {
fn emit_bool(&mut self, v: bool) -> io::Result<()> { self.writer.write_i8(if v {1} else {0}) }
}
impl<R:Reader> SimpleDecoder<io::Error> for RawDecoder<R> {
impl<R:Read> SimpleDecoder<io::Error> for RawDecoder<R> {
#[inline]
fn read_u64(&mut self) -> io::Result<u64> { self.reader.read_le_u64() }
#[inline]

View File

@ -34,17 +34,11 @@ use network::serialize::{RawEncoder, RawDecoder};
use util::misc::prepend_err;
/// Format an IP address in the 16-byte bitcoin protocol serialization
fn ipaddr_to_bitcoin_addr(ipaddr: &ip::IpAddr) -> [u8; 16] {
fn ipaddr_to_bitcoin_addr(ipaddr: &ip::IpAddr) -> [u16; 8] {
match *ipaddr {
ip::Ipv4Addr(a, b, c, d) =>
[0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0xff, 0xff, a, b, c, d],
ip::Ipv6Addr(a, b, c, d, e, f, g, h) =>
[(a / 0x100) as u8, (a % 0x100) as u8, (b / 0x100) as u8, (b % 0x100) as u8,
(c / 0x100) as u8, (c % 0x100) as u8, (d / 0x100) as u8, (d % 0x100) as u8,
(e / 0x100) as u8, (e % 0x100) as u8, (f / 0x100) as u8, (f % 0x100) as u8,
(g / 0x100) as u8, (g % 0x100) as u8, (h / 0x100) as u8, (h % 0x100) as u8 ]
}
ip::IpAddr::V4(ref addr) => &addr.to_ipv6_mapped(),
ip::IpAddr::V6(ref addr) => addr
}.segments()
}
/// A network socket along with information about the peer
@ -72,7 +66,7 @@ impl Socket {
// TODO: we fix services to 0
/// Construct a new socket
pub fn new(network: constants::Network) -> Socket {
let mut rng = task_rng();
let mut rng = thread_rng();
Socket {
socket: None,
buffered_reader: Arc::new(Mutex::new(None)),

View File

@ -22,7 +22,7 @@ use util::hash::Sha256dHash;
/// An error that might occur during base58 decoding
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Base58Error {
pub enum Error {
/// Invalid character encountered
BadByte(u8),
/// Checksum was not correct (expected, actual)
@ -34,7 +34,7 @@ pub enum Base58Error {
/// Checked data was less than 4 bytes
TooShort(usize),
/// Any other error
OtherBase58Error(String)
Other(String)
}
static BASE58_CHARS: &'static [u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
@ -62,21 +62,21 @@ static BASE58_DIGITS: [Option<u8>; 128] = [
pub trait FromBase58 {
/// Constructs an object flrom the byte-encoding (base 256)
/// representation of its base58 format
fn from_base58_layout(data: Vec<u8>) -> Result<Self, Base58Error>;
fn from_base58_layout(data: Vec<u8>) -> Result<Self, Error>;
/// Obtain an object from its base58 encoding
fn from_base58(data: &str) -> Result<Self, Base58Error> {
fn from_base58(data: &str) -> Result<Self, Error> {
// 11/15 is just over log_256(58)
let mut scratch = Vec::from_elem(1 + data.len() * 11 / 15, 0u8);
// Build in base 256
for d58 in data.bytes() {
// Compute "X = X * 58 + next_digit" in base 256
if d58 as usize > BASE58_DIGITS.len() {
return Err(BadByte(d58));
return Err(Error::BadByte(d58));
}
let mut carry = match BASE58_DIGITS[d58 as usize] {
Some(d58) => d58 as u32,
None => { return Err(BadByte(d58)); }
None => { return Err(Error::BadByte(d58)); }
};
for d256 in scratch.iter_mut().rev() {
carry += *d256 as u32 * 58;
@ -96,16 +96,16 @@ pub trait FromBase58 {
}
/// Obtain an object from its base58check encoding
fn from_base58check(data: &str) -> Result<Self, Base58Error> {
fn from_base58check(data: &str) -> Result<Self, Error> {
let mut ret: Vec<u8> = try!(FromBase58::from_base58(data));
if ret.len() < 4 {
return Err(TooShort(ret.len()));
return Err(Error::TooShort(ret.len()));
}
let ck_start = ret.len() - 4;
let expected = Sha256dHash::from_data(ret.slice_to(ck_start)).into_le().low_u32();
let actual = LittleEndian::read_u32(&ret[ck_start..(ck_start + 4)]);
if expected != actual {
return Err(BadChecksum(expected, actual));
return Err(Error::BadChecksum(expected, actual));
}
ret.truncate(ck_start);
@ -174,7 +174,7 @@ impl ToBase58 for Vec<u8> {
}
impl FromBase58 for Vec<u8> {
fn from_base58_layout(data: Vec<u8>) -> Result<Vec<u8>, Base58Error> {
fn from_base58_layout(data: Vec<u8>) -> Result<Vec<u8>, Error> {
Ok(data)
}
}

View File

@ -15,8 +15,8 @@
//!
//! Utility functions related to hashing data, including merkleization
use core::char::from_digit;
use core::cmp::min;
use std::char::from_digit;
use std::cmp::min;
use std::default::Default;
use std::fmt;
use std::io::Cursor;
@ -75,7 +75,7 @@ impl hash::Hash<DumbHasherState> for Sha256dHash {
fn hash(&self, state: &mut DumbHasherState) {
let &Sha256dHash(ref hash) = self;
let &DumbHasherState(ref mut arr) = state;
for i in range(0, 8) {
for i in 0..8 {
arr[i] += hash[i];
}
}
@ -184,7 +184,7 @@ impl Sha256dHash {
pub fn le_hex_string(&self) -> String {
let &Sha256dHash(data) = self;
let mut ret = String::with_capacity(64);
for i in range(0, 32) {
for i in 0..32 {
ret.push_char(from_digit((data[i] / 0x10) as usize, 16).unwrap());
ret.push_char(from_digit((data[i] & 0x0f) as usize, 16).unwrap());
}
@ -195,7 +195,7 @@ impl Sha256dHash {
pub fn be_hex_string(&self) -> String {
let &Sha256dHash(data) = self;
let mut ret = String::with_capacity(64);
for i in range(0, 32).rev() {
for i in (0..32).rev() {
ret.push_char(from_digit((data[i] / 0x10) as usize, 16).unwrap());
ret.push_char(from_digit((data[i] & 0x0f) as usize, 16).unwrap());
}
@ -234,7 +234,7 @@ impl<D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for Sha256dHash
let raw_str = try!(hex_str.as_slice().from_hex()
.map_err(|_| d.error("non-hexadecimal hash string")));
let mut ret = [0u8; 32];
for i in range(0, 32) {
for i in 0..32 {
ret[i] = raw_str[31 - i];
}
Ok(Sha256dHash(ret))
@ -279,7 +279,7 @@ impl<'a, T: BitcoinHash> MerkleRoot for &'a [T] {
}
// Recursion
let mut next = vec![];
for idx in range(0, (data.len() + 1) / 2) {
for idx in 0..((data.len() + 1) / 2) {
let idx1 = 2 * idx;
let idx2 = min(idx1 + 1, data.len() - 1);
let mut encoder = RawEncoder::new(Cursor::new(vec![]));

View File

@ -88,7 +88,7 @@ pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> usize {
while i <= top {
if haystack.slice(i, i + needle.len()) == needle {
let v = haystack.as_mut_slice();
for j in range(i, top) {
for j in i..top {
v.swap(j + needle.len(), j);
}
n_deleted += 1;
@ -97,11 +97,11 @@ pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> usize {
top -= needle.len();
if overflow { break; }
} else {
i += match Opcode::from_u8((*haystack)[i]).classify() {
opcodes::PushBytes(n) => n + 1,
opcodes::Ordinary(opcodes::OP_PUSHDATA1) => 2,
opcodes::Ordinary(opcodes::OP_PUSHDATA2) => 3,
opcodes::Ordinary(opcodes::OP_PUSHDATA4) => 5,
i += match opcodes::All::from_u8((*haystack)[i]).classify() {
opcodes::Class::PushBytes(n) => n + 1,
opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA1) => 2,
opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA2) => 3,
opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA4) => 5,
_ => 1
};
}

View File

@ -20,10 +20,10 @@
//! strings; a Patricia tree uses bitstrings.
//!
use core::fmt::Debug;
use core::cmp;
use std::fmt::Debug;
use std::marker;
use std::num::{Zero, One};
use std::{cmp, ops, ptr};
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::serialize::{SimpleDecoder, SimpleEncoder};
@ -38,7 +38,7 @@ pub struct PatriciaTree<K, V> {
skip_len: u8
}
impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<usize,K>+Shr<usize,K>, V> PatriciaTree<K, V> {
impl<K:BitArray+cmp::Eq+Zero+One+ops::BitXor<K,K>+ops::Shl<usize,K>+ops::Shr<usize,K>, V> PatriciaTree<K, V> {
/// Constructs a new Patricia tree
pub fn new() -> PatriciaTree<K, V> {
PatriciaTree {
@ -214,7 +214,7 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<usize,K>+Shr<usize,K>, V> PatriciaTr
pub fn delete(&mut self, key: &K, key_len: usize) -> Option<V> {
/// Return value is (deletable, actual return value), where `deletable` is true
/// is true when the entire node can be deleted (i.e. it has no children)
fn recurse<K:BitArray+Eq+Zero+One+Add<K,K>+Shr<usize,K>+Shl<usize,K>, V>(tree: &mut PatriciaTree<K, V>, key: &K, key_len: usize) -> (bool, Option<V>) {
fn recurse<K:BitArray+cmp::Eq+Zero+One+ops::Add<K,K>+ops::Shr<usize,K>+ops::Shl<usize,K>, V>(tree: &mut PatriciaTree<K, V>, key: &K, key_len: usize) -> (bool, Option<V>) {
// If the search key is shorter than the node prefix, there is no
// way we can match, so fail.
if key_len < tree.skip_len as usize {
@ -346,7 +346,7 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<usize,K>+Shr<usize,K>, V> PatriciaTr
node: self as *mut _,
parents: vec![],
started: false,
marker: marker::ContravariantLifetime::<'a>
marker: marker::PhantomData
}
}
}
@ -355,14 +355,14 @@ impl<K:BitArray, V:Debug> PatriciaTree<K, V> {
/// Print the entire tree
pub fn print<'a>(&'a self) {
fn recurse<'a, K:BitArray, V:Debug>(tree: &'a PatriciaTree<K, V>, depth: usize) {
for i in range(0, tree.skip_len as usize) {
for i in 0..tree.skip_len as usize {
print!("{:}", if tree.skip_prefix.bit(i) { 1 } else { 0 });
}
println!(": {:}", tree.data);
// left gets no indentation
match tree.child_l {
Some(ref t) => {
for _ in range(0, depth + tree.skip_len as usize) {
for _ in 0..(depth + tree.skip_len as usize) {
print!("-");
}
print!("0");
@ -373,7 +373,7 @@ impl<K:BitArray, V:Debug> PatriciaTree<K, V> {
// right one gets indentation
match tree.child_r {
Some(ref t) => {
for _ in range(0, depth + tree.skip_len as usize) {
for _ in 0..(depth + tree.skip_len as usize) {
print!("_");
}
print!("1");
@ -422,7 +422,7 @@ pub struct MutItems<'tree, K, V> {
started: bool,
node: *mut PatriciaTree<K, V>,
parents: Vec<*mut PatriciaTree<K, V>>,
marker: marker::ContravariantLifetime<'tree>
marker: marker::PhantomData<&'tree PatriciaTree<K, V>>
}
impl<'a, K, V> Iterator<&'a V> for Items<'a, K, V> {
@ -474,7 +474,7 @@ impl<'a, K, V> Iterator<&'a mut V> for MutItems<'a, K, V> {
fn borrow_opt<'a, K, V>(opt_ptr: &'a Option<Box<PatriciaTree<K, V>>>) -> *mut PatriciaTree<K, V> {
match *opt_ptr {
Some(ref data) => &**data as *const _ as *mut _,
None => RawPtr::null()
None => ptr::null()
}
}
@ -504,7 +504,7 @@ impl<'a, K, V> Iterator<&'a mut V> for MutItems<'a, K, V> {
self.node = child_r;
break;
}
self.node = self.parents.pop().unwrap_or(RawPtr::null());
self.node = self.parents.pop().unwrap_or(ptr::null());
}
}
// Stop if we've found data.
@ -552,7 +552,7 @@ mod tests {
fn patricia_insert_lookup_delete_test() {
let mut tree = PatriciaTree::new();
let mut hashes = vec![];
for i in range(0u32, 5000) {
for i in 0u32..5000 {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 250, i);
hashes.push(hash);
@ -593,21 +593,21 @@ mod tests {
let mut tree = PatriciaTree::new();
let mut hashes = vec![];
// Start by inserting a bunch of chunder
for i in range(1u32, 500) {
for i in 1u32..500 {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 128, i * 1000);
hashes.push(hash);
}
// Do the actual test -- note that we also test insertion and deletion
// at the root here.
for i in range(0u32, 10) {
for i in 0u32..10 {
tree.insert(&Zero::zero(), i as usize, i);
}
for i in range(0u32, 10) {
for i in 0u32..10 {
let m = tree.lookup(&Zero::zero(), i as usize);
assert_eq!(m, Some(&i));
}
for i in range(0u32, 10) {
for i in 0u32..10 {
let m = tree.delete(&Zero::zero(), i as usize);
assert_eq!(m, Some(i));
}
@ -625,7 +625,7 @@ mod tests {
let mut tree = PatriciaTree::new();
let mut data = Vec::from_elem(n_elems, None);
// Start by inserting a bunch of stuff
for i in range(0, n_elems) {
for i in 0..n_elems {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 128, i);
*data.get_mut(i) = Some(());
@ -647,7 +647,7 @@ mod tests {
let mut tree = PatriciaTree::new();
let mut data = Vec::from_elem(n_elems, None);
// Start by inserting a bunch of stuff
for i in range(0, n_elems) {
for i in 0..n_elems {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 128, i);
*data.get_mut(i) = Some(());
@ -673,7 +673,7 @@ mod tests {
// Build a tree
let mut tree = PatriciaTree::new();
let mut hashes = vec![];
for i in range(0u32, 5000) {
for i in 0u32..5000 {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 250, i);
hashes.push(hash);

View File

@ -24,8 +24,7 @@ use blockdata::script::Script;
use blockdata::opcodes;
use network::constants::Network::{self, Bitcoin, BitcoinTestnet};
use util::hash::Ripemd160Hash;
use util::base58::Base58Error::{self, InvalidLength, InvalidVersion};
use util::base58::{FromBase58, ToBase58};
use util::base58::{self, FromBase58, ToBase58};
#[derive(Clone, PartialEq, Eq)]
/// A Bitcoin address
@ -100,16 +99,16 @@ impl ToBase58 for Address {
}
impl FromBase58 for Address {
fn from_base58_layout(data: Vec<u8>) -> Result<Address, Base58Error> {
fn from_base58_layout(data: Vec<u8>) -> Result<Address, base58::Error> {
if data.len() != 21 {
return Err(InvalidLength(data.len()));
return Err(base58::Error::InvalidLength(data.len()));
}
Ok(Address {
network: match data[0] {
0 => Bitcoin,
111 => BitcoinTestnet,
x => { return Err(InvalidVersion(vec![x])); }
x => { return Err(base58::Error::InvalidVersion(vec![x])); }
},
hash: Ripemd160Hash::from_slice(data.slice_from(1))
})

View File

@ -30,8 +30,7 @@ use secp256k1::key::{PublicKey, SecretKey};
use secp256k1;
use network::constants::Network::{self, Bitcoin, BitcoinTestnet};
use util::base58::Base58Error::{self, InvalidLength, InvalidVersion,
OtherBase58Error};
use util::base58;
use util::base58::{FromBase58, ToBase58};
/// A chain code
@ -310,9 +309,9 @@ impl ToBase58 for ExtendedPrivKey {
}
impl FromBase58 for ExtendedPrivKey {
fn from_base58_layout(data: Vec<u8>) -> Result<ExtendedPrivKey, Base58Error> {
fn from_base58_layout(data: Vec<u8>) -> Result<ExtendedPrivKey, base58::Error> {
if data.len() != 78 {
return Err(InvalidLength(data.len()));
return Err(base58::Error::InvalidLength(data.len()));
}
let cn_int = BigEndian::read_u32(&data[9..13]);
@ -323,7 +322,7 @@ impl FromBase58 for ExtendedPrivKey {
network: match data.slice_to(4) {
[0x04, 0x88, 0xAD, 0xE4] => Bitcoin,
[0x04, 0x35, 0x83, 0x94] => BitcoinTestnet,
_ => { return Err(InvalidVersion(data.slice_to(4).to_vec())); }
_ => { return Err(base58::Error::InvalidVersion(data.slice_to(4).to_vec())); }
},
depth: data[4],
parent_fingerprint: Fingerprint::from_slice(data.slice(5, 9)),
@ -331,7 +330,7 @@ impl FromBase58 for ExtendedPrivKey {
chain_code: ChainCode::from_slice(data.slice(13, 45)),
secret_key: try!(SecretKey::from_slice(
data.slice(46, 78)).map_err(|e|
OtherBase58Error(e.to_string())))
base58::Error::Other(e.to_string())))
})
}
}
@ -361,9 +360,9 @@ impl ToBase58 for ExtendedPubKey {
}
impl FromBase58 for ExtendedPubKey {
fn from_base58_layout(data: Vec<u8>) -> Result<ExtendedPubKey, Base58Error> {
fn from_base58_layout(data: Vec<u8>) -> Result<ExtendedPubKey, base58::Error> {
if data.len() != 78 {
return Err(InvalidLength(data.len()));
return Err(base58::Error::InvalidLength(data.len()));
}
let cn_int = BigEndian::read_u32(&data[9..13]);
@ -374,7 +373,7 @@ impl FromBase58 for ExtendedPubKey {
network: match data.slice_to(4) {
[0x04, 0x88, 0xB2, 0x1E] => Bitcoin,
[0x04, 0x35, 0x87, 0xCF] => BitcoinTestnet,
_ => { return Err(InvalidVersion(data.slice_to(4).to_vec())); }
_ => { return Err(base58::Error::InvalidVersion(data.slice_to(4).to_vec())); }
},
depth: data[4],
parent_fingerprint: Fingerprint::from_slice(data.slice(5, 9)),
@ -382,7 +381,7 @@ impl FromBase58 for ExtendedPubKey {
chain_code: ChainCode::from_slice(data.slice(13, 45)),
public_key: try!(PublicKey::from_slice(
data.slice(45, 78)).map_err(|e|
OtherBase58Error(e.to_string())))
base58::Error::Other(e.to_string())))
})
}
}