Checkpoint commit: into warnings!
This commit is contained in:
parent
1d78dccb9e
commit
3117f95b62
|
@ -32,7 +32,7 @@ use blockdata::transaction::Transaction;
|
||||||
|
|
||||||
/// A block header, which contains all the block's information except
|
/// A block header, which contains all the block's information except
|
||||||
/// the actual transactions
|
/// the actual transactions
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
||||||
pub struct BlockHeader {
|
pub struct BlockHeader {
|
||||||
/// The protocol version. Should always be 1.
|
/// The protocol version. Should always be 1.
|
||||||
pub version: u32,
|
pub version: u32,
|
||||||
|
|
|
@ -34,7 +34,7 @@ use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
// write an #[inline] helper function which casts to u8s.
|
// write an #[inline] helper function which casts to u8s.
|
||||||
|
|
||||||
/// A script Opcode
|
/// A script Opcode
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum All {
|
pub enum All {
|
||||||
/// Push an empty array onto the stack
|
/// Push an empty array onto the stack
|
||||||
|
@ -633,7 +633,7 @@ pub static OP_FALSE: All = All::OP_PUSHBYTES_0;
|
||||||
pub static OP_TRUE: All = 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(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum Class {
|
pub enum Class {
|
||||||
/// Pushes the given number onto the stack
|
/// Pushes the given number onto the stack
|
||||||
PushNum(i32),
|
PushNum(i32),
|
||||||
|
@ -663,7 +663,7 @@ macro_rules! ordinary_opcode {
|
||||||
($($op:ident),*) => (
|
($($op:ident),*) => (
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum Ordinary {
|
pub enum Ordinary {
|
||||||
$( $op = All::$op as u8 ),*
|
$( $op = All::$op as u8 ),*
|
||||||
}
|
}
|
||||||
|
|
|
@ -1628,10 +1628,10 @@ macro_rules! stack_opcode {
|
||||||
macro_rules! num_opcode {
|
macro_rules! num_opcode {
|
||||||
($stack:ident($($var:ident),*): $op:expr) => ({
|
($stack:ident($($var:ident),*): $op:expr) => ({
|
||||||
$(
|
$(
|
||||||
let $var = try!(read_scriptint(match $stack.pop() {
|
let $var = try!(read_scriptint(&match $stack.pop() {
|
||||||
Some(elem) => &elem[..],
|
Some(elem) => elem,
|
||||||
None => { return Err(Error::PopEmptyStack); }
|
None => { return Err(Error::PopEmptyStack); }
|
||||||
}));
|
}[..]));
|
||||||
)*
|
)*
|
||||||
$stack.push(MaybeOwned::Owned(build_scriptint($op)));
|
$stack.push(MaybeOwned::Owned(build_scriptint($op)));
|
||||||
// Return a tuple of all the variables
|
// Return a tuple of all the variables
|
||||||
|
|
|
@ -153,16 +153,15 @@ pub struct TransactionTrace {
|
||||||
impl TxIn {
|
impl TxIn {
|
||||||
/// Check an input's script for validity
|
/// Check an input's script for validity
|
||||||
pub fn validate(&self,
|
pub fn validate(&self,
|
||||||
utxoset: &UtxoSet,
|
utxoset: &UtxoSet,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
index: usize) -> Result<(), Error> {
|
index: usize) -> Result<(), Error> {
|
||||||
let txo = utxoset.get_utxo(self.prev_hash, self.prev_index);
|
let txo = utxoset.get_utxo(self.prev_hash, self.prev_index);
|
||||||
match txo {
|
match txo {
|
||||||
Some((_, txo)) => {
|
Some((_, txo)) => {
|
||||||
let mut p2sh_stack = Vec::new();
|
let (mut p2sh_stack, mut p2sh_script) = (vec![], Script::new());
|
||||||
let mut p2sh_script = Script::new();
|
|
||||||
|
|
||||||
let mut stack = Vec::with_capacity(6);
|
let mut stack = vec![];
|
||||||
match self.script_sig.evaluate(&mut stack, Some((txn, index)), None) {
|
match self.script_sig.evaluate(&mut stack, Some((txn, index)), None) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => { return Err(Error::InputScriptFailure(e)); }
|
Err(e) => { return Err(Error::InputScriptFailure(e)); }
|
||||||
|
@ -220,7 +219,7 @@ impl Transaction {
|
||||||
/// Produce a trace of a transaction's execution
|
/// Produce a trace of a transaction's execution
|
||||||
pub fn trace(&self, utxoset: &UtxoSet) -> TransactionTrace {
|
pub fn trace(&self, utxoset: &UtxoSet) -> TransactionTrace {
|
||||||
let mut ret = TransactionTrace { txid: self.bitcoin_hash(),
|
let mut ret = TransactionTrace { txid: self.bitcoin_hash(),
|
||||||
inputs: Vec::with_capacity(self.input.len()) };
|
inputs: Vec::with_capacity(self.input.len()) };
|
||||||
for (n, input) in self.input.iter().enumerate() {
|
for (n, input) in self.input.iter().enumerate() {
|
||||||
// Setup trace
|
// Setup trace
|
||||||
let mut trace = InputTrace {
|
let mut trace = InputTrace {
|
||||||
|
@ -240,8 +239,7 @@ impl Transaction {
|
||||||
let txo = utxoset.get_utxo(input.prev_hash, input.prev_index);
|
let txo = utxoset.get_utxo(input.prev_hash, input.prev_index);
|
||||||
match txo {
|
match txo {
|
||||||
Some((_, txo)) => {
|
Some((_, txo)) => {
|
||||||
let mut p2sh_stack = Vec::new();
|
let (mut p2sh_stack, mut p2sh_script) = (vec![], Script::new());
|
||||||
let mut p2sh_script = Script::new();
|
|
||||||
|
|
||||||
let mut stack = Vec::with_capacity(6);
|
let mut stack = Vec::with_capacity(6);
|
||||||
trace.sig_trace = input.script_sig.trace(&mut stack, Some((self, n)));
|
trace.sig_trace = input.script_sig.trace(&mut stack, Some((self, n)));
|
||||||
|
|
|
@ -196,7 +196,7 @@ impl UtxoSet {
|
||||||
};
|
};
|
||||||
// Check that this specific output is there
|
// Check that this specific output is there
|
||||||
if vout as usize >= node.outputs.len() { return None; }
|
if vout as usize >= node.outputs.len() { return None; }
|
||||||
let replace = node.outputs[vout as usize];
|
let replace = &node.outputs[vout as usize];
|
||||||
Some((node.height as usize, replace.as_ref().unwrap()))
|
Some((node.height as usize, replace.as_ref().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ impl UtxoSet {
|
||||||
// Return the last error since we need to finish every future before
|
// Return the last error since we need to finish every future before
|
||||||
// leaving this function, and given that, it's easier to return the last.
|
// leaving this function, and given that, it's easier to return the last.
|
||||||
let mut last_err = Ok(());
|
let mut last_err = Ok(());
|
||||||
for res in future_vec.iter_mut().map(|f| f.await().unwrap()) {
|
for res in future_vec.into_iter().map(|f| f.await().unwrap()) {
|
||||||
if res.is_err() { last_err = res; }
|
if res.is_err() { last_err = res; }
|
||||||
}
|
}
|
||||||
if last_err.is_err() { return last_err; }
|
if last_err.is_err() { return last_err; }
|
||||||
|
@ -292,7 +292,7 @@ impl UtxoSet {
|
||||||
for tx in block.txdata.iter().skip(1) {
|
for tx in block.txdata.iter().skip(1) {
|
||||||
let txid = tx.bitcoin_hash();
|
let txid = tx.bitcoin_hash();
|
||||||
// Put the removed utxos into the stxo cache, in case we need to rewind
|
// Put the removed utxos into the stxo cache, in case we need to rewind
|
||||||
(&self.spent_txos[spent_idx]).reserve(tx.input.len());
|
(&mut self.spent_txos[spent_idx]).reserve(tx.input.len());
|
||||||
for (n, input) in tx.input.iter().enumerate() {
|
for (n, input) in tx.input.iter().enumerate() {
|
||||||
let taken = self.take_utxo(input.prev_hash, input.prev_index);
|
let taken = self.take_utxo(input.prev_hash, input.prev_index);
|
||||||
match taken {
|
match taken {
|
||||||
|
|
|
@ -117,6 +117,8 @@ macro_rules! impl_array_newtype {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Copy for $thing {}
|
||||||
|
|
||||||
impl ::std::hash::Hash for $thing {
|
impl ::std::hash::Hash for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H>(&self, state: &mut H)
|
fn hash<H>(&self, state: &mut H)
|
||||||
|
|
|
@ -56,9 +56,12 @@ extern crate rand;
|
||||||
extern crate rustc_serialize as serialize;
|
extern crate rustc_serialize as serialize;
|
||||||
extern crate secp256k1;
|
extern crate secp256k1;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate test;
|
#[cfg(test)] extern crate test;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[macro_use]
|
||||||
|
mod test_macros;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod internal_macros;
|
mod internal_macros;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -22,7 +22,7 @@ use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{SimpleEncoder, SimpleDecoder};
|
use network::serialize::{SimpleEncoder, SimpleDecoder};
|
||||||
|
|
||||||
user_enum! {
|
user_enum! {
|
||||||
#[derive(PartialEq, Eq, Clone, Hash)]
|
#[derive(Copy, PartialEq, Eq, Clone, Hash)]
|
||||||
#[doc="The cryptocurrency to act on"]
|
#[doc="The cryptocurrency to act on"]
|
||||||
pub enum Network {
|
pub enum Network {
|
||||||
#[doc="Classic Bitcoin"]
|
#[doc="Classic Bitcoin"]
|
||||||
|
|
|
@ -35,9 +35,9 @@ use util::{self, propagate_err};
|
||||||
/// Format an IP address in the 16-byte bitcoin protocol serialization
|
/// Format an IP address in the 16-byte bitcoin protocol serialization
|
||||||
fn ipaddr_to_bitcoin_addr(ipaddr: &net::IpAddr) -> [u16; 8] {
|
fn ipaddr_to_bitcoin_addr(ipaddr: &net::IpAddr) -> [u16; 8] {
|
||||||
match *ipaddr {
|
match *ipaddr {
|
||||||
net::IpAddr::V4(ref addr) => &addr.to_ipv6_mapped(),
|
net::IpAddr::V4(ref addr) => addr.to_ipv6_mapped().segments(),
|
||||||
net::IpAddr::V6(ref addr) => addr
|
net::IpAddr::V6(ref addr) => addr.segments()
|
||||||
}.segments()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A network socket along with information about the peer
|
/// A network socket along with information about the peer
|
||||||
|
@ -55,6 +55,31 @@ pub struct Socket {
|
||||||
pub magic: u32
|
pub magic: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! with_socket(($s:ident, $sock:ident, $body:block) => ({
|
||||||
|
use ::std::ops::DerefMut;
|
||||||
|
let mut sock_lock = $s.socket.lock();
|
||||||
|
match sock_lock {
|
||||||
|
Err(_) => {
|
||||||
|
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
||||||
|
"socket: socket mutex was poisoned");
|
||||||
|
return Err(util::Error::Io(io_err));
|
||||||
|
}
|
||||||
|
Ok(mut guard) => {
|
||||||
|
match *guard.deref_mut() {
|
||||||
|
Some(ref mut $sock) => {
|
||||||
|
$body
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
||||||
|
"socket: not connected to peer");
|
||||||
|
return Err(util::Error::Io(io_err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
impl Socket {
|
impl Socket {
|
||||||
// TODO: we fix services to 0
|
// TODO: we fix services to 0
|
||||||
/// Construct a new socket
|
/// Construct a new socket
|
||||||
|
@ -85,55 +110,36 @@ impl Socket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn socket(&mut self) -> Result<&mut net::TcpStream, util::Error> {
|
|
||||||
let mut sock_lock = self.socket.lock();
|
|
||||||
match sock_lock {
|
|
||||||
Err(_) => {
|
|
||||||
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
|
||||||
"socket: socket mutex was poisoned");
|
|
||||||
Err(util::Error::Io(io_err))
|
|
||||||
}
|
|
||||||
Ok(guard) => {
|
|
||||||
match *guard {
|
|
||||||
Some(ref mut sock) => Ok(sock),
|
|
||||||
None => {
|
|
||||||
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
|
||||||
"socket: not connected to peer");
|
|
||||||
Err(util::Error::Io(io_err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Peer address
|
/// Peer address
|
||||||
pub fn receiver_address(&mut self) -> Result<Address, util::Error> {
|
pub fn receiver_address(&mut self) -> Result<Address, util::Error> {
|
||||||
let sock = try!(self.socket());
|
with_socket!(self, sock, {
|
||||||
match sock.peer_addr() {
|
match sock.peer_addr() {
|
||||||
Ok(addr) => {
|
Ok(addr) => {
|
||||||
Ok(Address {
|
Ok(Address {
|
||||||
services: self.services,
|
services: self.services,
|
||||||
address: ipaddr_to_bitcoin_addr(&addr.ip()),
|
address: ipaddr_to_bitcoin_addr(&addr.ip()),
|
||||||
port: addr.port()
|
port: addr.port()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Err(e) => Err(util::Error::Io(e))
|
Err(e) => Err(util::Error::Io(e))
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Our own address
|
/// Our own address
|
||||||
pub fn sender_address(&mut self) -> Result<Address, util::Error> {
|
pub fn sender_address(&mut self) -> Result<Address, util::Error> {
|
||||||
let sock = try!(self.socket());
|
with_socket!(self, sock, {
|
||||||
match sock.local_addr() {
|
match sock.local_addr() {
|
||||||
Ok(addr) => {
|
Ok(addr) => {
|
||||||
Ok(Address {
|
Ok(Address {
|
||||||
services: self.services,
|
services: self.services,
|
||||||
address: ipaddr_to_bitcoin_addr(&addr.ip()),
|
address: ipaddr_to_bitcoin_addr(&addr.ip()),
|
||||||
port: addr.port()
|
port: addr.port()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Err(e) => Err(util::Error::Io(e))
|
Err(e) => Err(util::Error::Io(e))
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a version message appropriate for this socket
|
/// Produce a version message appropriate for this socket
|
||||||
|
@ -157,35 +163,37 @@ impl Socket {
|
||||||
|
|
||||||
/// Send a general message across the line
|
/// Send a general message across the line
|
||||||
pub fn send_message(&mut self, payload: NetworkMessage) -> Result<(), util::Error> {
|
pub fn send_message(&mut self, payload: NetworkMessage) -> Result<(), util::Error> {
|
||||||
let sock = try!(self.socket());
|
with_socket!(self, sock, {
|
||||||
let message = RawNetworkMessage { magic: self.magic, payload: payload };
|
let message = RawNetworkMessage { magic: self.magic, payload: payload };
|
||||||
try!(message.consensus_encode(&mut RawEncoder::new(sock)));
|
try!(message.consensus_encode(&mut RawEncoder::new(&mut *sock)));
|
||||||
sock.flush().map_err(util::Error::Io)
|
sock.flush().map_err(util::Error::Io)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receive the next message from the peer, decoding the network header
|
/// Receive the next message from the peer, decoding the network header
|
||||||
/// and verifying its correctness. Returns the undecoded payload.
|
/// and verifying its correctness. Returns the undecoded payload.
|
||||||
pub fn receive_message(&mut self) -> Result<NetworkMessage, util::Error> {
|
pub fn receive_message(&mut self) -> Result<NetworkMessage, util::Error> {
|
||||||
let sock = try!(self.socket());
|
with_socket!(self, sock, {
|
||||||
// We need a new scope since the closure in here borrows read_err,
|
// We need a new scope since the closure in here borrows read_err,
|
||||||
// and we try to read it afterward. Letting `iter` go out fixes it.
|
// and we try to read it afterward. Letting `iter` go out fixes it.
|
||||||
let mut decoder = RawDecoder::new(sock);
|
let mut decoder = RawDecoder::new(sock);
|
||||||
let decode: Result<RawNetworkMessage, _> = ConsensusDecodable::consensus_decode(&mut decoder);
|
let decode: Result<RawNetworkMessage, _> = ConsensusDecodable::consensus_decode(&mut decoder);
|
||||||
match decode {
|
match decode {
|
||||||
// Check for parse errors...
|
// Check for parse errors...
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
propagate_err("receive_message".to_string(), Err(e))
|
propagate_err("receive_message".to_string(), Err(e))
|
||||||
},
|
},
|
||||||
Ok(ret) => {
|
Ok(ret) => {
|
||||||
// Then for magic (this should come before parse error, but we can't
|
// Then for magic (this should come before parse error, but we can't
|
||||||
// get to it if the deserialization failed). TODO restructure this
|
// get to it if the deserialization failed). TODO restructure this
|
||||||
if ret.magic != self.magic {
|
if ret.magic != self.magic {
|
||||||
Err(util::Error::BadNetworkMagic(self.magic, ret.magic))
|
Err(util::Error::BadNetworkMagic(self.magic, ret.magic))
|
||||||
} else {
|
} else {
|
||||||
Ok(ret.payload)
|
Ok(ret.payload)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,15 +48,15 @@ pub struct Ripemd160Hash([u8; 20]);
|
||||||
impl_array_newtype!(Ripemd160Hash, u8, 20);
|
impl_array_newtype!(Ripemd160Hash, u8, 20);
|
||||||
|
|
||||||
/// 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(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Hash32((u8, u8, u8, u8));
|
pub struct Hash32((u8, u8, u8, u8));
|
||||||
|
|
||||||
/// A 48-bit hash obtained by truncating a real hash
|
/// A 48-bit hash obtained by truncating a real hash
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Hash48((u8, u8, u8, u8, u8, u8));
|
pub struct Hash48((u8, u8, u8, u8, u8, u8));
|
||||||
|
|
||||||
/// A 64-bit hash obtained by truncating a real hash
|
/// A 64-bit hash obtained by truncating a real hash
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, 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));
|
||||||
|
|
||||||
impl Ripemd160Hash {
|
impl Ripemd160Hash {
|
||||||
|
@ -268,8 +268,7 @@ mod tests {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::num::FromPrimitive;
|
use std::num::FromPrimitive;
|
||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
use serialize::Encodable;
|
use serde::{json, Serialize, Deserialize};
|
||||||
use serialize::json;
|
|
||||||
|
|
||||||
use network::serialize::{serialize, deserialize};
|
use network::serialize::{serialize, deserialize};
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
|
@ -296,15 +295,15 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hash_encode_decode() {
|
fn test_hash_encode_decode() {
|
||||||
let hash = Sha256dHash::from_data(&[]);
|
let hash = Sha256dHash::from_data(&[]);
|
||||||
let mut writer = Cursor::new(vec![]);
|
let mut writer = vec![];
|
||||||
{
|
{
|
||||||
let mut encoder = json::Encoder::new(&mut writer);
|
let mut serializer = json::ser::Serializer::new(&mut writer);
|
||||||
assert!(hash.encode(&mut encoder).is_ok());
|
assert!(hash.serialize(&mut serializer).is_ok());
|
||||||
}
|
}
|
||||||
let res = writer.into_inner();
|
assert_eq!(&writer[..],
|
||||||
assert_eq!(&res[..],
|
|
||||||
"\"56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d\"".as_bytes());
|
"\"56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d\"".as_bytes());
|
||||||
assert_eq!(json::decode(from_utf8(res.as_slice()).unwrap()), Ok(hash));
|
let mut deserializer = json::de::Deserializer::new(writer.iter().map(|c| Ok(*c))).unwrap();
|
||||||
|
assert_eq!(hash, Deserialize::deserialize(&mut deserializer).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub fn hex_bytes(s: &str) -> Result<Vec<u8>, Error> {
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
let mut iter = s.chars().pair();
|
let mut iter = s.chars().pair();
|
||||||
// Do the parsing
|
// Do the parsing
|
||||||
try!(iter.fold(Ok(()), |e, (f, s)|
|
try!(iter.by_ref().fold(Ok(()), |e, (f, s)|
|
||||||
if e.is_err() { e }
|
if e.is_err() { e }
|
||||||
else {
|
else {
|
||||||
match (f.to_digit(16), s.to_digit(16)) {
|
match (f.to_digit(16), s.to_digit(16)) {
|
||||||
|
@ -73,9 +73,8 @@ pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> usize {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i <= top {
|
while i <= top {
|
||||||
if &haystack[i..(i + needle.len())] == needle {
|
if &haystack[i..(i + needle.len())] == needle {
|
||||||
let v = &mut haystack;
|
|
||||||
for j in i..top {
|
for j in i..top {
|
||||||
v.swap(j + needle.len(), j);
|
haystack.swap(j + needle.len(), j);
|
||||||
}
|
}
|
||||||
n_deleted += 1;
|
n_deleted += 1;
|
||||||
// This is ugly but prevents infinite loop in case of overflow
|
// This is ugly but prevents infinite loop in case of overflow
|
||||||
|
|
|
@ -30,7 +30,7 @@ use network::serialize::{SimpleDecoder, SimpleEncoder};
|
||||||
use util::BitArray;
|
use util::BitArray;
|
||||||
|
|
||||||
/// Patricia troo
|
/// Patricia troo
|
||||||
pub struct PatriciaTree<K, V> {
|
pub struct PatriciaTree<K: Copy, V> {
|
||||||
data: Option<V>,
|
data: Option<V>,
|
||||||
child_l: Option<Box<PatriciaTree<K, V>>>,
|
child_l: Option<Box<PatriciaTree<K, V>>>,
|
||||||
child_r: Option<Box<PatriciaTree<K, V>>>,
|
child_r: Option<Box<PatriciaTree<K, V>>>,
|
||||||
|
@ -39,7 +39,7 @@ pub struct PatriciaTree<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, V> PatriciaTree<K, V>
|
impl<K, V> PatriciaTree<K, V>
|
||||||
where K: BitArray + cmp::Eq + Zero + One +
|
where K: Copy + BitArray + cmp::Eq + Zero + One +
|
||||||
ops::BitXor<K, Output=K> +
|
ops::BitXor<K, Output=K> +
|
||||||
ops::Add<K, Output=K> +
|
ops::Add<K, Output=K> +
|
||||||
ops::Shr<usize, Output=K> +
|
ops::Shr<usize, Output=K> +
|
||||||
|
@ -221,7 +221,7 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
/// Return value is (deletable, actual return value), where `deletable` is true
|
/// 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)
|
/// is true when the entire node can be deleted (i.e. it has no children)
|
||||||
fn recurse<K, V>(tree: &mut PatriciaTree<K, V>, key: &K, key_len: usize) -> (bool, Option<V>)
|
fn recurse<K, V>(tree: &mut PatriciaTree<K, V>, key: &K, key_len: usize) -> (bool, Option<V>)
|
||||||
where K: BitArray + cmp::Eq + Zero + One +
|
where K: Copy + BitArray + cmp::Eq + Zero + One +
|
||||||
ops::Add<K, Output=K> +
|
ops::Add<K, Output=K> +
|
||||||
ops::Shr<usize, Output=K> +
|
ops::Shr<usize, Output=K> +
|
||||||
ops::Shl<usize, Output=K>
|
ops::Shl<usize, Output=K>
|
||||||
|
@ -333,7 +333,7 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
|
|
||||||
/// Count all the nodes
|
/// Count all the nodes
|
||||||
pub fn node_count(&self) -> usize {
|
pub fn node_count(&self) -> usize {
|
||||||
fn recurse<K, V>(node: &Option<Box<PatriciaTree<K, V>>>) -> usize {
|
fn recurse<K: Copy, V>(node: &Option<Box<PatriciaTree<K, V>>>) -> usize {
|
||||||
match node {
|
match node {
|
||||||
&Some(ref node) => { 1 + recurse(&node.child_l) + recurse(&node.child_r) }
|
&Some(ref node) => { 1 + recurse(&node.child_l) + recurse(&node.child_r) }
|
||||||
&None => 0
|
&None => 0
|
||||||
|
@ -362,10 +362,12 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K:BitArray, V:Debug> Debug for PatriciaTree<K, V> {
|
impl<K: Copy + BitArray, V: Debug> Debug for PatriciaTree<K, V> {
|
||||||
/// Print the entire tree
|
/// Print the entire tree
|
||||||
fn fmt<'a>(&'a self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt<'a>(&'a self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
fn recurse<'a, K:BitArray, V:Debug>(tree: &'a PatriciaTree<K, V>, f: &mut fmt::Formatter, depth: usize) -> Result<(), fmt::Error> {
|
fn recurse<'a, K, V>(tree: &'a PatriciaTree<K, V>, f: &mut fmt::Formatter, depth: usize) -> Result<(), fmt::Error>
|
||||||
|
where K: Copy + BitArray, V: Debug
|
||||||
|
{
|
||||||
for i in 0..tree.skip_len as usize {
|
for i in 0..tree.skip_len as usize {
|
||||||
try!(write!(f, "{:}", if tree.skip_prefix.bit(i) { 1 } else { 0 }));
|
try!(write!(f, "{:}", if tree.skip_prefix.bit(i) { 1 } else { 0 }));
|
||||||
}
|
}
|
||||||
|
@ -400,7 +402,7 @@ impl<K:BitArray, V:Debug> Debug for PatriciaTree<K, V> {
|
||||||
|
|
||||||
impl<S, K, V> ConsensusEncodable<S> for PatriciaTree<K, V>
|
impl<S, K, V> ConsensusEncodable<S> for PatriciaTree<K, V>
|
||||||
where S: SimpleEncoder,
|
where S: SimpleEncoder,
|
||||||
K: ConsensusEncodable<S>,
|
K: Copy + ConsensusEncodable<S>,
|
||||||
V: ConsensusEncodable<S>
|
V: ConsensusEncodable<S>
|
||||||
{
|
{
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
||||||
|
@ -416,7 +418,7 @@ impl<S, K, V> ConsensusEncodable<S> for PatriciaTree<K, V>
|
||||||
|
|
||||||
impl<D, K, V> ConsensusDecodable<D> for PatriciaTree<K, V>
|
impl<D, K, V> ConsensusDecodable<D> for PatriciaTree<K, V>
|
||||||
where D: SimpleDecoder,
|
where D: SimpleDecoder,
|
||||||
K: ConsensusDecodable<D>,
|
K: Copy + ConsensusDecodable<D>,
|
||||||
V: ConsensusDecodable<D>
|
V: ConsensusDecodable<D>
|
||||||
{
|
{
|
||||||
fn consensus_decode(d: &mut D) -> Result<PatriciaTree<K, V>, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<PatriciaTree<K, V>, D::Error> {
|
||||||
|
@ -431,25 +433,25 @@ impl<D, K, V> ConsensusDecodable<D> for PatriciaTree<K, V>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator
|
/// Iterator
|
||||||
pub struct Items<'tree, K: 'tree, V: 'tree> {
|
pub struct Items<'tree, K: Copy + 'tree, V: 'tree> {
|
||||||
started: bool,
|
started: bool,
|
||||||
node: Option<&'tree PatriciaTree<K, V>>,
|
node: Option<&'tree PatriciaTree<K, V>>,
|
||||||
parents: Vec<&'tree PatriciaTree<K, V>>
|
parents: Vec<&'tree PatriciaTree<K, V>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutable iterator
|
/// Mutable iterator
|
||||||
pub struct MutItems<'tree, K: 'tree, V: 'tree> {
|
pub struct MutItems<'tree, K: Copy + 'tree, V: 'tree> {
|
||||||
started: bool,
|
started: bool,
|
||||||
node: *mut PatriciaTree<K, V>,
|
node: *mut PatriciaTree<K, V>,
|
||||||
parents: Vec<*mut PatriciaTree<K, V>>,
|
parents: Vec<*mut PatriciaTree<K, V>>,
|
||||||
marker: marker::PhantomData<&'tree PatriciaTree<K, V>>
|
marker: marker::PhantomData<&'tree PatriciaTree<K, V>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K, V> Iterator for Items<'a, K, V> {
|
impl<'a, K: Copy, V> Iterator for Items<'a, K, V> {
|
||||||
type Item = &'a V;
|
type Item = &'a V;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<&'a V> {
|
fn next(&mut self) -> Option<&'a V> {
|
||||||
fn borrow_opt<'a, K, V>(opt_ptr: &'a Option<Box<PatriciaTree<K, V>>>) -> Option<&'a PatriciaTree<K, V>> {
|
fn borrow_opt<'a, K: Copy, V>(opt_ptr: &'a Option<Box<PatriciaTree<K, V>>>) -> Option<&'a PatriciaTree<K, V>> {
|
||||||
opt_ptr.as_ref().map(|b| &**b)
|
opt_ptr.as_ref().map(|b| &**b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,11 +493,11 @@ impl<'a, K, V> Iterator for Items<'a, K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K, V> Iterator for MutItems<'a, K, V> {
|
impl<'a, K: Copy, V> Iterator for MutItems<'a, K, V> {
|
||||||
type Item = &'a mut V;
|
type Item = &'a mut V;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<&'a mut V> {
|
fn next(&mut self) -> Option<&'a mut V> {
|
||||||
fn borrow_opt<'a, K, V>(opt_ptr: &'a Option<Box<PatriciaTree<K, V>>>) -> *mut PatriciaTree<K, V> {
|
fn borrow_opt<'a, K: Copy, V>(opt_ptr: &'a Option<Box<PatriciaTree<K, V>>>) -> *mut PatriciaTree<K, V> {
|
||||||
match *opt_ptr {
|
match *opt_ptr {
|
||||||
Some(ref data) => &**data as *const _ as *mut _,
|
Some(ref data) => &**data as *const _ as *mut _,
|
||||||
None => ptr::null_mut()
|
None => ptr::null_mut()
|
||||||
|
|
|
@ -51,7 +51,7 @@ impl Default for Fingerprint {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extended private key
|
/// Extended private key
|
||||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
pub struct ExtendedPrivKey {
|
pub struct ExtendedPrivKey {
|
||||||
/// The network this key is to be used on
|
/// The network this key is to be used on
|
||||||
pub network: Network,
|
pub network: Network,
|
||||||
|
@ -68,7 +68,7 @@ pub struct ExtendedPrivKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extended public key
|
/// Extended public key
|
||||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
pub struct ExtendedPubKey {
|
pub struct ExtendedPubKey {
|
||||||
/// The network this key is to be used on
|
/// The network this key is to be used on
|
||||||
pub network: Network,
|
pub network: Network,
|
||||||
|
@ -85,7 +85,7 @@ pub struct ExtendedPubKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A child number for a derived key
|
/// A child number for a derived key
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum ChildNumber {
|
pub enum ChildNumber {
|
||||||
/// Hardened key index, within [0, 2^31 - 1]
|
/// Hardened key index, within [0, 2^31 - 1]
|
||||||
Hardened(u32),
|
Hardened(u32),
|
||||||
|
@ -292,9 +292,9 @@ impl ExtendedPubKey {
|
||||||
impl ToBase58 for ExtendedPrivKey {
|
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 {
|
||||||
Network::Bitcoin => &[0x04, 0x88, 0xAD, 0xE4],
|
Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4],
|
||||||
Network::Testnet => &[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[..]);
|
ret.push_all(&self.parent_fingerprint[..]);
|
||||||
|
@ -346,9 +346,9 @@ impl ToBase58 for ExtendedPubKey {
|
||||||
fn base58_layout(&self) -> Vec<u8> {
|
fn base58_layout(&self) -> Vec<u8> {
|
||||||
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 {
|
||||||
Network::Bitcoin => &[0x04u8, 0x88, 0xB2, 0x1E],
|
Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E],
|
||||||
Network::Testnet => &[0x04u8, 0x35, 0x87, 0xCF]
|
Network::Testnet => [0x04u8, 0x35, 0x87, 0xCF]
|
||||||
});
|
});
|
||||||
ret.push(self.depth as u8);
|
ret.push(self.depth as u8);
|
||||||
ret.push_all(&self.parent_fingerprint[..]);
|
ret.push_all(&self.parent_fingerprint[..]);
|
||||||
|
@ -510,21 +510,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn encode_decode_childnumber() {
|
pub fn encode_decode_childnumber() {
|
||||||
use serialize::json;
|
serde_round_trip!(Normal(0));
|
||||||
|
serde_round_trip!(Normal(1));
|
||||||
let h1 = Hardened(1);
|
serde_round_trip!(Normal((1 << 31) - 1));
|
||||||
let n1 = Normal(1);
|
serde_round_trip!(Hardened(0));
|
||||||
|
serde_round_trip!(Hardened(1));
|
||||||
let h1_str = json::encode(&h1);
|
serde_round_trip!(Hardened((1 << 31) - 1));
|
||||||
let n1_str = json::encode(&n1);
|
|
||||||
|
|
||||||
assert!(h1 != n1);
|
|
||||||
assert!(h1_str != n1_str);
|
|
||||||
|
|
||||||
let h1_dec = json::decode(&h1_str).unwrap();
|
|
||||||
let n1_dec = json::decode(&n1_str).unwrap();
|
|
||||||
assert_eq!(h1, h1_dec);
|
|
||||||
assert_eq!(n1, n1_dec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
|
|
Loading…
Reference in New Issue