diff --git a/Cargo.toml b/Cargo.toml index 5cc6e6f..d2fe92c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ git = "https://github.com/carllerche/eventual" [dependencies] byteorder = "*" +num = "*" num_cpus = "*" rand = "*" rust-crypto = "*" diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 1f4de27..29e99b5 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -20,7 +20,7 @@ //! these blocks and the blockchain. //! -use std::num::{Zero, from_u64}; +use num::{FromPrimitive, Zero}; use util; use util::Error::{SpvBadTarget, SpvBadProofOfWork}; @@ -90,7 +90,7 @@ impl BlockHeader { if mant > 0x7FFFFF { Zero::zero() } else { - from_u64::(mant as u64).unwrap() << (expt as usize) + ::from_u64(mant as u64).unwrap() << (expt as usize) } } diff --git a/src/blockdata/blockchain.rs b/src/blockdata/blockchain.rs index eb52e01..d1de5af 100644 --- a/src/blockdata/blockchain.rs +++ b/src/blockdata/blockchain.rs @@ -22,8 +22,8 @@ //! to make sure we are holding the only references. //! -use std::num::Zero; -use std::{marker, num, ptr}; +use num::{FromPrimitive, Zero}; +use std::{marker, ptr}; use blockdata::block::{Block, BlockHeader}; use blockdata::transaction::Transaction; @@ -470,7 +470,7 @@ impl Blockchain { // Compute new target let mut target = unsafe { (*prev).block.header.target() }; target = target.mul_u32(timespan); - target = target / num::FromPrimitive::from_u64(DIFFCHANGE_TIMESPAN as u64).unwrap(); + target = target / FromPrimitive::from_u64(DIFFCHANGE_TIMESPAN as u64).unwrap(); // Clamp below MAX_TARGET (difficulty 1) let max = max_target(self.network); if target > max { target = max }; diff --git a/src/blockdata/constants.rs b/src/blockdata/constants.rs index 33fbe6f..88d026d 100644 --- a/src/blockdata/constants.rs +++ b/src/blockdata/constants.rs @@ -20,7 +20,7 @@ //! use std::default::Default; -use std::num::from_u64; +use num::FromPrimitive; use blockdata::opcodes; use blockdata::script; @@ -39,7 +39,7 @@ pub static DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600; /// In Bitcoind this is insanely described as ~((u256)0 >> 32) pub fn max_target(_: Network) -> Uint256 { - from_u64::(0xFFFF).unwrap() << 208 + ::from_u64(0xFFFF).unwrap() << 208 } /// The maximum value allowed in an output (useful for sanity checking, @@ -73,7 +73,7 @@ fn bitcoin_genesis_tx() -> Transaction { // Outputs let mut out_script = script::Builder::new(); - out_script.push_slice(hex_bytes("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap().as_slice()); + out_script.push_slice(&hex_bytes("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap()); out_script.push_opcode(opcodes::All::OP_CHECKSIG); ret.output.push(TxOut { value: 50 * COIN_VALUE, diff --git a/src/blockdata/opcodes.rs b/src/blockdata/opcodes.rs index c2d5e87..f648601 100644 --- a/src/blockdata/opcodes.rs +++ b/src/blockdata/opcodes.rs @@ -24,7 +24,6 @@ use serde; // Heavy stick to translate between opcode types use std::mem::transmute; -use std::fmt; use network::serialize::{SimpleDecoder, SimpleEncoder}; use network::encodable::{ConsensusDecodable, ConsensusEncodable}; diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 8bcc621..b2dfb20 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -28,7 +28,6 @@ use std::hash; use std::char::from_digit; use std::default::Default; use std::ops; -use serialize::json; use serialize::hex::ToHex; use crypto::digest::Digest; @@ -56,9 +55,10 @@ impl Clone for Script { } } -#[derive(PartialEq, Eq, Debug, Clone, Display)] +#[derive(PartialEq, Eq, Debug, Clone)] /// An object which can be used to construct a script piece by piece pub struct Builder(Vec); +display_from_debug!(Builder); impl hash::Hash for Script { #[inline] @@ -875,7 +875,7 @@ impl AbstractStackElem { } let validators = self.validators.clone(); - for v in validators.iter().map(|v| v.clone()) { + for v in validators.iter().cloned() { try!((v.update)(self, &v.args)); } Ok(()) @@ -2084,12 +2084,10 @@ impl Script { /// Checks whether a script pubkey is a p2sh output #[inline] pub fn is_p2sh(&self) -> bool { - unsafe { - self.0.len() == 23 && - self.0[0] == opcodes::All::OP_HASH160 as u8 && - self.0[1] == opcodes::All::OP_PUSHBYTES_20 as u8 && - self.0[22] == opcodes::All::OP_EQUAL as u8 - } + self.0.len() == 23 && + self.0[0] == opcodes::All::OP_HASH160 as u8 && + self.0[1] == opcodes::All::OP_PUSHBYTES_20 as u8 && + self.0[22] == opcodes::All::OP_EQUAL as u8 } /// Whether a script can be proven to have no satisfying input @@ -2503,13 +2501,15 @@ impl Builder { _ => panic!("tried to put a 4bn+ sized object into a script!") } // Then push the acraw - self.0.extend(data.iter().map(|n| *n)); + self.0.extend(data.iter().cloned()); } + /// Adds a single opcode to the script pub fn push_opcode(&mut self, data: opcodes::All) { self.0.push(data as u8); } + /// Converts the `Builder` into an unmodifiable `Script` pub fn into_script(self) -> Script { Script(self.0.into_boxed_slice()) } @@ -2594,16 +2594,16 @@ mod test { script.push_int(4); comp.push(85u8); assert_eq!(&script[..], &comp[..]); script.push_int(-1); comp.push(80u8); assert_eq!(&script[..], &comp[..]); // forced scriptint - script.push_scriptint(4); comp.push_all(&[1u8, 4]); assert_eq!(&script[..], &comp[..]); + script.push_scriptint(4); comp.extend([1u8, 4].iter().cloned()); assert_eq!(&script[..], &comp[..]); // big ints - script.push_int(17); comp.push_all(&[1u8, 17]); assert_eq!(&script[..], &comp[..]); - script.push_int(10000); comp.push_all(&[2u8, 16, 39]); assert_eq!(&script[..], &comp[..]); + script.push_int(17); comp.extend([1u8, 17].iter().cloned()); assert_eq!(&script[..], &comp[..]); + script.push_int(10000); comp.extend([2u8, 16, 39].iter().cloned()); assert_eq!(&script[..], &comp[..]); // notice the sign bit set here, hence the extra zero/128 at the end - script.push_int(10000000); comp.push_all(&[4u8, 128, 150, 152, 0]); assert_eq!(&script[..], &comp[..]); - script.push_int(-10000000); comp.push_all(&[4u8, 128, 150, 152, 128]); assert_eq!(&script[..], &comp[..]); + script.push_int(10000000); comp.extend([4u8, 128, 150, 152, 0].iter().cloned()); assert_eq!(&script[..], &comp[..]); + script.push_int(-10000000); comp.extend([4u8, 128, 150, 152, 128].iter().cloned()); assert_eq!(&script[..], &comp[..]); // data - script.push_slice("NRA4VR".as_bytes()); comp.push_all(&[6u8, 78, 82, 65, 52, 86, 82]); assert_eq!(&script[..], &comp[..]); + script.push_slice("NRA4VR".as_bytes()); comp.extend([6u8, 78, 82, 65, 52, 86, 82].iter().cloned()); assert_eq!(&script[..], &comp[..]); // opcodes script.push_opcode(opcodes::All::OP_CHECKSIG); comp.push(0xACu8); assert_eq!(&script[..], &comp[..]); diff --git a/src/blockdata/utxoset.rs b/src/blockdata/utxoset.rs index 77ee3e3..95867f8 100644 --- a/src/blockdata/utxoset.rs +++ b/src/blockdata/utxoset.rs @@ -134,7 +134,7 @@ impl UtxoSet { fn add_utxos(&mut self, tx: &Transaction, height: u32) -> Option { let txid = tx.bitcoin_hash(); // Locate node if it's already there - let new_node = unsafe { + let new_node = { let mut new_node = Vec::with_capacity(tx.output.len()); for txo in tx.output.iter() { // Unsafe since we are not uninitializing the old data in the vector @@ -353,14 +353,12 @@ impl UtxoSet { node } None => { - unsafe { - let mut thinvec = Vec::with_capacity(n as usize + 1); - for _ in 0..n { - thinvec.push(None); - } - thinvec.push(Some(txo)); - UtxoNode { outputs: thinvec.into_boxed_slice(), height: height } + let mut thinvec = Vec::with_capacity(n as usize + 1); + for _ in 0..n { + thinvec.push(None); } + thinvec.push(Some(txo)); + UtxoNode { outputs: thinvec.into_boxed_slice(), height: height } } }; // Ram it back into the tree @@ -416,7 +414,6 @@ impl UtxoSet { #[cfg(test)] mod tests { - use std::prelude::*; use serialize::hex::FromHex; use super::{UtxoSet, ValidationLevel}; diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 0f36991..a9bacad 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -167,7 +167,7 @@ macro_rules! impl_array_newtype_encodable { None => return Err(::serde::de::Error::end_of_stream_error()) }; } - v.end(); + try!(v.end()); Ok($thing(ret)) } } diff --git a/src/lib.rs b/src/lib.rs index 07e2968..2cd5574 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,28 +29,27 @@ // Experimental features we need #![feature(box_patterns)] -#![feature(custom_derive, plugin)] -#![feature(overloaded_calls)] -#![feature(unsafe_destructor)] -#![feature(unboxed_closure_sugar)] -#![feature(unboxed_closures)] #![feature(concat_idents)] +#![feature(custom_derive, plugin)] +#![feature(hash)] +#![feature(ip_addr)] #![feature(slice_patterns)] +#![feature(std_misc)] +#![cfg_attr(test, feature(test))] // Coding conventions -#![warn(non_uppercase_statics)] +#![deny(non_upper_case_globals)] #![deny(non_camel_case_types)] #![deny(non_snake_case)] #![deny(unused_mut)] -#![warn(missing_doc)] +#![deny(missing_docs)] #![plugin(serde_macros)] -extern crate alloc; extern crate byteorder; -extern crate collections; extern crate crypto; extern crate eventual; +extern crate num; extern crate num_cpus; extern crate rand; extern crate rustc_serialize as serialize; @@ -71,6 +70,3 @@ pub mod blockdata; pub mod util; pub mod wallet; -/// I dunno where else to put this.. -fn assert_type_is_copy() { } - diff --git a/src/network/encodable.rs b/src/network/encodable.rs index aea476a..8b0f7a0 100644 --- a/src/network/encodable.rs +++ b/src/network/encodable.rs @@ -203,7 +203,7 @@ impl_array!(12); impl_array!(16); impl_array!(32); -impl<'a, S: SimpleEncoder, T: ConsensusEncodable> ConsensusEncodable for &'a [T] { +impl> ConsensusEncodable for [T] { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { try!(VarInt(self.len() as u64).consensus_encode(s)); @@ -239,12 +239,10 @@ impl> ConsensusDecodable for Box<[ #[inline] fn consensus_decode(d: &mut D) -> Result, D::Error> { let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d)); - unsafe { - let len = len as usize; - let mut ret = Vec::with_capacity(len); - for i in 0..len { ret.push(try!(ConsensusDecodable::consensus_decode(d))); } - Ok(ret.into_boxed_slice()) - } + let len = len as usize; + let mut ret = Vec::with_capacity(len); + for _ in 0..len { ret.push(try!(ConsensusDecodable::consensus_decode(d))); } + Ok(ret.into_boxed_slice()) } } @@ -457,7 +455,7 @@ mod tests { #[test] fn serialize_vector_test() { assert_eq!(serialize(&vec![1u8, 2, 3]).ok(), Some(vec![3u8, 1, 2, 3])); - assert_eq!(serialize(&[1u8, 2, 3].as_slice()).ok(), Some(vec![3u8, 1, 2, 3])); + assert_eq!(serialize(&[1u8, 2, 3][..]).ok(), Some(vec![3u8, 1, 2, 3])); // TODO: test vectors of more interesting objects } @@ -531,7 +529,7 @@ mod tests { #[test] fn deserialize_strbuf_test() { - assert_eq!(deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), Some(String::from_str("Andrew"))); + assert_eq!(deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), Some("Andrew".to_string())); } #[test] diff --git a/src/network/listener.rs b/src/network/listener.rs index 2be156c..fe2d1af 100644 --- a/src/network/listener.rs +++ b/src/network/listener.rs @@ -18,7 +18,7 @@ //! to connect to a peer, send network messages, and receive Bitcoin data. //! -use std::{io, thread}; +use std::thread; use std::sync::mpsc::{channel, Receiver}; use network::constants::Network; @@ -75,7 +75,7 @@ pub trait Listener { // We have to pass the message to the main thread for processing, // unfortunately, because sipa says we have to handle everything // in order. - recv_tx.send(message::SocketResponse::MessageReceived(payload)); + recv_tx.send(message::SocketResponse::MessageReceived(payload)).unwrap(); } Err(e) => { // On failure we send an error message to the main thread, along with @@ -83,8 +83,8 @@ pub trait Listener { // thread. (If we simply exited immediately, the channel would be torn // down and the main thread would never see the error message.) let (tx, rx) = channel(); - recv_tx.send(message::SocketResponse::ConnectionFailed(e, tx)); - rx.recv(); + recv_tx.send(message::SocketResponse::ConnectionFailed(e, tx)).unwrap(); + rx.recv().unwrap(); break; } } diff --git a/src/network/message.rs b/src/network/message.rs index 67db4d9..a47aeeb 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -19,9 +19,8 @@ //! also defines (de)serialization routines for many primitives. //! -use collections::Vec; use std::iter; -use std::io::{self, Cursor}; +use std::io::Cursor; use std::sync::mpsc::Sender; use blockdata::block; @@ -41,9 +40,14 @@ pub struct CommandString(pub String); impl ConsensusEncodable for CommandString { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { + use std::intrinsics::copy_nonoverlapping; + use std::mem; + let &CommandString(ref inner_str) = self; let mut rawbytes = [0u8; 12]; - rawbytes.clone_from_slice(inner_str.as_bytes().as_slice()); + unsafe { copy_nonoverlapping(inner_str.as_bytes().as_ptr(), + rawbytes.as_mut_ptr(), + mem::size_of::<[u8; 12]>()); } rawbytes.consensus_encode(s) } } @@ -165,7 +169,7 @@ impl> ConsensusDecodable for RawNetworkMe let CheckedData(raw_payload): CheckedData = try!(ConsensusDecodable::consensus_decode(d)); let mut mem_d = RawDecoder::new(Cursor::new(raw_payload)); - let payload = match cmd.as_slice() { + let payload = match &cmd[..] { "version" => NetworkMessage::Version(try!(propagate_err("version".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))), "verack" => NetworkMessage::Verack, "addr" => NetworkMessage::Addr(try!(propagate_err("addr".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))), @@ -196,7 +200,7 @@ mod test { #[test] fn serialize_commandstring_test() { - let cs = CommandString(String::from_str("Andrew")); + let cs = CommandString("Andrew".to_string()); assert_eq!(serialize(&cs).ok(), Some(vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0])); } @@ -204,7 +208,7 @@ mod test { fn deserialize_commandstring_test() { let cs: Result = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]); assert!(cs.is_ok()); - assert_eq!(cs.unwrap(), CommandString(String::from_str("Andrew"))); + assert_eq!(cs.unwrap(), CommandString("Andrew".to_string())); let short_cs: Result = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]); assert!(short_cs.is_err()); diff --git a/src/network/message_network.rs b/src/network/message_network.rs index 34a19b8..f6a113d 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -96,7 +96,7 @@ mod tests { assert_eq!(real_decode.timestamp, 1401217254); // address decodes should be covered by Address tests assert_eq!(real_decode.nonce, 16735069437859780935); - assert_eq!(real_decode.user_agent, String::from_str("/Satoshi:0.9.99/")); + assert_eq!(real_decode.user_agent, "/Satoshi:0.9.99/".to_string()); assert_eq!(real_decode.start_height, 302892); assert_eq!(real_decode.relay, true); diff --git a/src/network/serialize.rs b/src/network/serialize.rs index 826160f..456edaa 100644 --- a/src/network/serialize.rs +++ b/src/network/serialize.rs @@ -19,8 +19,7 @@ //! It also defines (de)serialization routines for many primitives. //! -use collections::Vec; -use std::io::{self, Cursor, Read, Write}; +use std::io::{Cursor, Read, Write}; use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt}; use serialize::hex::ToHex; @@ -42,7 +41,7 @@ impl BitcoinHash for Vec { } /// Encode an object into a vector -pub fn serialize(data: &T) -> Result, util::Error> +pub fn serialize(data: &T) -> Result, util::Error> where T: ConsensusEncodable>>>, { let mut encoder = RawEncoder::new(Cursor::new(vec![])); @@ -51,7 +50,7 @@ pub fn serialize(data: &T) -> Result, util::Error> } /// Encode an object into a hex-encoded string -pub fn serialize_hex(data: &T) -> Result +pub fn serialize_hex(data: &T) -> Result where T: ConsensusEncodable>>> { let serial = try!(serialize(data)); @@ -92,57 +91,59 @@ impl RawDecoder { /// A simple Encoder trait pub trait SimpleEncoder { - type Error; + /// An encoding error + type Error; + + /// Output a 64-bit uint + fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>; + /// Output a 32-bit uint + fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>; + /// Output a 16-bit uint + fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>; + /// Output a 8-bit uint + fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>; - /// Output a 64-bit uint - fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>; - /// Output a 32-bit uint - fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>; - /// Output a 16-bit uint - fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>; - /// Output a 8-bit uint - fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>; + /// Output a 64-bit int + fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>; + /// Output a 32-bit int + fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>; + /// Output a 16-bit int + fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>; + /// Output a 8-bit int + fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>; - /// Output a 64-bit int - fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>; - /// Output a 32-bit int - fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>; - /// Output a 16-bit int - fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>; - /// Output a 8-bit int - fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>; - - /// Output a boolean - fn emit_bool(&mut self, v: bool) -> Result<(), Self::Error>; + /// Output a boolean + fn emit_bool(&mut self, v: bool) -> Result<(), Self::Error>; } /// A simple Decoder trait pub trait SimpleDecoder { - type Error; + /// A decoding error + type Error; - /// Read a 64-bit uint - fn read_u64(&mut self) -> Result; - /// Read a 32-bit uint - fn read_u32(&mut self) -> Result; - /// Read a 16-bit uint - fn read_u16(&mut self) -> Result; - /// Read a 8-bit uint - fn read_u8(&mut self) -> Result; + /// Read a 64-bit uint + fn read_u64(&mut self) -> Result; + /// Read a 32-bit uint + fn read_u32(&mut self) -> Result; + /// Read a 16-bit uint + fn read_u16(&mut self) -> Result; + /// Read a 8-bit uint + fn read_u8(&mut self) -> Result; - /// Read a 64-bit int - fn read_i64(&mut self) -> Result; - /// Read a 32-bit int - fn read_i32(&mut self) -> Result; - /// Read a 16-bit int - fn read_i16(&mut self) -> Result; - /// Read a 8-bit int - fn read_i8(&mut self) -> Result; + /// Read a 64-bit int + fn read_i64(&mut self) -> Result; + /// Read a 32-bit int + fn read_i32(&mut self) -> Result; + /// Read a 16-bit int + fn read_i16(&mut self) -> Result; + /// Read a 8-bit int + fn read_i8(&mut self) -> Result; - /// Read a boolean - fn read_bool(&mut self) -> Result; + /// Read a boolean + fn read_bool(&mut self) -> Result; - /// Signal a decoding error - fn error(&mut self, err: String) -> Self::Error; + /// Signal a decoding error + fn error(&mut self, err: String) -> Self::Error; } macro_rules! encoder_fn { diff --git a/src/network/socket.rs b/src/network/socket.rs index d1b032d..525e9a9 100644 --- a/src/network/socket.rs +++ b/src/network/socket.rs @@ -19,7 +19,7 @@ use time::now; use rand::{thread_rng, Rng}; -use std::io::{self, Cursor, Write}; +use std::io::{self, Write}; use std::net; use std::sync::{Arc, Mutex}; @@ -57,7 +57,7 @@ pub struct Socket { macro_rules! with_socket(($s:ident, $sock:ident, $body:block) => ({ use ::std::ops::DerefMut; - let mut sock_lock = $s.socket.lock(); + let sock_lock = $s.socket.lock(); match sock_lock { Err(_) => { let io_err = io::Error::new(io::ErrorKind::NotConnected, @@ -89,7 +89,7 @@ impl Socket { socket: Arc::new(Mutex::new(None)), services: 0, version_nonce: rng.gen(), - user_agent: String::from_str(constants::USER_AGENT), + user_agent: constants::USER_AGENT.to_string(), magic: constants::magic(network) } } diff --git a/src/test_macros.rs b/src/test_macros.rs new file mode 100644 index 0000000..44b55b1 --- /dev/null +++ b/src/test_macros.rs @@ -0,0 +1,35 @@ +// Rust Bitcoin Library +// Written in 2014 by +// Andrew Poelstra +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +//! # Macros +//! +//! Internal macros used for unit tests + +#[macro_export] +macro_rules! serde_round_trip ( + ($var:expr) => ({ + use serde::{json, Serialize, Deserialize}; + + let start = $var; + let mut encoded = Vec::new(); + { + let mut serializer = json::ser::Serializer::new(&mut encoded); + start.serialize(&mut serializer).unwrap(); + } + let mut deserializer = json::de::Deserializer::new(encoded.iter().map(|c| Ok(*c))).unwrap(); + let decoded = Deserialize::deserialize(&mut deserializer); + assert_eq!(Some(start), decoded.ok()); + }) +); + diff --git a/src/util/base58.rs b/src/util/base58.rs index 5ef522a..6238d8a 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -15,9 +15,6 @@ //! # Base58 encoder and decoder use byteorder::{ByteOrder, LittleEndian, WriteBytesExt}; - -use std::{iter, str}; - use util::hash::Sha256dHash; /// An error that might occur during base58 decoding @@ -129,17 +126,14 @@ pub fn base58_encode_slice(data: &[u8]) -> String { assert_eq!(carry, 0); } - // Unsafely translate the bytes to a utf8 string - unsafe { - // Copy leading zeroes directly - let mut ret: Vec = data.iter().take_while(|&&x| x == 0) - .map(|_| BASE58_CHARS[0]) - .collect(); - // Copy rest of string - ret.extend(scratch.into_iter().skip_while(|&x| x == 0) - .map(|x| BASE58_CHARS[x as usize])); - String::from_utf8(ret).unwrap() - } + // Copy leading zeroes directly + let mut ret: Vec = data.iter().take_while(|&&x| x == 0) + .map(|_| BASE58_CHARS[0]) + .collect(); + // Copy rest of string + ret.extend(scratch.into_iter().skip_while(|&x| x == 0) + .map(|x| BASE58_CHARS[x as usize])); + String::from_utf8(ret).unwrap() } /// Trait for objects which can be written as base58 @@ -157,7 +151,7 @@ pub trait ToBase58 { fn to_base58check(&self) -> String { let mut data = self.base58_layout(); let checksum = Sha256dHash::from_data(&data).into_le().low_u32(); - data.write_u32::(checksum); + data.write_u32::(checksum).unwrap(); base58_encode_slice(&data) } } diff --git a/src/util/hash.rs b/src/util/hash.rs index 90a095e..3ef97ad 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -21,16 +21,14 @@ use std::default::Default; use std::fmt::{self, Write}; use std::io::Cursor; use std::mem::transmute; -use std::hash; use serde; -use byteorder::{ByteOrder, LittleEndian}; use crypto::digest::Digest; use crypto::sha2::Sha256; use crypto::ripemd160::Ripemd160; use network::encodable::{ConsensusDecodable, ConsensusEncodable}; -use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder}; +use network::serialize::{RawEncoder, BitcoinHash}; use util::uint::Uint256; /// A Bitcoin hash, 32-bytes, computed from x as SHA256(SHA256(x)) @@ -39,7 +37,7 @@ impl_array_newtype!(Sha256dHash, u8, 32); impl ::std::fmt::Debug for Sha256dHash { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", self.be_hex_string().as_slice()) + write!(f, "{}", self.be_hex_string()) } } @@ -214,7 +212,6 @@ impl_newtype_consensus_encoding!(Sha256dHash); impl fmt::LowerHex for Sha256dHash { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let &Sha256dHash(data) = self; - let mut rv = [0; 64]; for ch in data.iter().rev() { try!(write!(f, "{:02x}", ch)); } @@ -264,10 +261,7 @@ impl MerkleRoot for Vec { #[cfg(test)] mod tests { - use std::prelude::*; - use std::io::Cursor; - use std::num::FromPrimitive; - use std::str::from_utf8; + use num::FromPrimitive; use serde::{json, Serialize, Deserialize}; use network::serialize::{serialize, deserialize}; diff --git a/src/util/misc.rs b/src/util/misc.rs index 0c9dd31..23808ce 100644 --- a/src/util/misc.rs +++ b/src/util/misc.rs @@ -97,8 +97,6 @@ pub fn script_find_and_remove(haystack: &mut Vec, needle: &[u8]) -> usize { #[cfg(test)] mod tests { - use std::prelude::*; - use super::script_find_and_remove; use super::hex_bytes; diff --git a/src/util/patricia_tree.rs b/src/util/patricia_tree.rs index c49106a..e84098b 100644 --- a/src/util/patricia_tree.rs +++ b/src/util/patricia_tree.rs @@ -22,8 +22,8 @@ use std::fmt::Debug; use std::marker; -use std::num::{Zero, One}; use std::{cmp, fmt, ops, ptr}; +use num::{Zero, One}; use network::encodable::{ConsensusDecodable, ConsensusEncodable}; use network::serialize::{SimpleDecoder, SimpleEncoder}; @@ -549,9 +549,8 @@ impl<'a, K: Copy, V> Iterator for MutItems<'a, K, V> { #[cfg(test)] mod tests { - use std::prelude::*; - use std::num::Zero; - use std::num::FromPrimitive; + use num::Zero; + use num::FromPrimitive; use network::serialize::{deserialize, serialize}; use util::hash::Sha256dHash; diff --git a/src/util/uint.rs b/src/util/uint.rs index 252e5a5..cb2e52b 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -19,9 +19,8 @@ //! use std::fmt; -use std::num::{Zero, One}; +use num::{FromPrimitive, Zero, One}; -use network::serialize::RawEncoder; use util::BitArray; macro_rules! construct_uint { @@ -66,7 +65,7 @@ macro_rules! construct_uint { } } - impl ::std::num::FromPrimitive for $name { + impl FromPrimitive for $name { #[inline] fn from_u64(init: u64) -> Option<$name> { let mut ret = [0; $n_words]; @@ -76,15 +75,17 @@ macro_rules! construct_uint { #[inline] fn from_i64(init: i64) -> Option<$name> { - ::std::num::FromPrimitive::from_u64(init as u64) + assert!(init >= 0); + FromPrimitive::from_u64(init as u64) } } - impl ::std::num::Zero for $name { + impl Zero for $name { fn zero() -> $name { $name([0; $n_words]) } + fn is_zero(&self) -> bool { self.0.iter().all(|&n| n == 0) } } - impl ::std::num::One for $name { + impl One for $name { fn one() -> $name { $name({ let mut ret = [0; $n_words]; ret[0] = 1; ret }) } @@ -289,7 +290,6 @@ macro_rules! construct_uint { impl ::std::ops::Shr for $name { type Output = $name; - #[allow(unsigned_negate)] fn shr(self, shift: usize) -> $name { let $name(ref original) = self; let mut ret = [0u64; $n_words]; @@ -388,7 +388,7 @@ impl Uint256 { #[cfg(test)] mod tests { - use std::num::from_u64; + use num::FromPrimitive; use network::serialize::{deserialize, serialize}; use util::uint::Uint256; @@ -396,14 +396,14 @@ mod tests { #[test] pub fn uint256_bits_test() { - assert_eq!(from_u64::(255).unwrap().bits(), 8); - assert_eq!(from_u64::(256).unwrap().bits(), 9); - assert_eq!(from_u64::(300).unwrap().bits(), 9); - assert_eq!(from_u64::(60000).unwrap().bits(), 16); - assert_eq!(from_u64::(70000).unwrap().bits(), 17); + assert_eq!(::from_u64(255).unwrap().bits(), 8); + assert_eq!(::from_u64(256).unwrap().bits(), 9); + assert_eq!(::from_u64(300).unwrap().bits(), 9); + assert_eq!(::from_u64(60000).unwrap().bits(), 16); + assert_eq!(::from_u64(70000).unwrap().bits(), 17); // Try to read the following lines out loud quickly - let mut shl: Uint256 = from_u64(70000).unwrap(); + let mut shl = ::from_u64(70000).unwrap(); shl = shl << 100; assert_eq!(shl.bits(), 117); shl = shl << 100; @@ -412,11 +412,11 @@ mod tests { assert_eq!(shl.bits(), 0); // Bit set check - assert!(!from_u64::(10).unwrap().bit(0)); - assert!(from_u64::(10).unwrap().bit(1)); - assert!(!from_u64::(10).unwrap().bit(2)); - assert!(from_u64::(10).unwrap().bit(3)); - assert!(!from_u64::(10).unwrap().bit(4)); + assert!(!::from_u64(10).unwrap().bit(0)); + assert!(::from_u64(10).unwrap().bit(1)); + assert!(!::from_u64(10).unwrap().bit(2)); + assert!(::from_u64(10).unwrap().bit(3)); + assert!(!::from_u64(10).unwrap().bit(4)); } #[test] @@ -438,7 +438,7 @@ mod tests { #[test] pub fn uint256_arithmetic_test() { - let init: Uint256 = from_u64(0xDEADBEEFDEADBEEF).unwrap(); + let init = ::from_u64(0xDEADBEEFDEADBEEF).unwrap(); let copy = init; let add = init + copy; @@ -459,17 +459,17 @@ mod tests { let mult = sub.mul_u32(300); assert_eq!(mult, Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0])); // Division - assert_eq!(from_u64::(105).unwrap() / - from_u64::(5).unwrap(), - from_u64::(21).unwrap()); - let div = mult / from_u64::(300).unwrap(); + assert_eq!(::from_u64(105).unwrap() / + ::from_u64(5).unwrap(), + ::from_u64(21).unwrap()); + let div = mult / ::from_u64(300).unwrap(); assert_eq!(div, Uint256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); // TODO: bit inversion } #[test] pub fn uint256_bitslice_test() { - let init = from_u64::(0xDEADBEEFDEADBEEF).unwrap(); + let init = ::from_u64(0xDEADBEEFDEADBEEF).unwrap(); let add = init + (init << 64); assert_eq!(add.bit_slice(64, 128), init); assert_eq!(add.mask(64), init); @@ -479,7 +479,7 @@ mod tests { pub fn uint256_extreme_bitshift_test() { // Shifting a u64 by 64 bits gives an undefined value, so make sure that // we're doing the Right Thing here - let init = from_u64::(0xDEADBEEFDEADBEEF).unwrap(); + let init = ::from_u64(0xDEADBEEFDEADBEEF).unwrap(); assert_eq!(init << 64, Uint256([0, 0xDEADBEEFDEADBEEF, 0, 0])); let add = (init << 64) + init; diff --git a/src/wallet/address.rs b/src/wallet/address.rs index 0e95a97..ca95847 100644 --- a/src/wallet/address.rs +++ b/src/wallet/address.rs @@ -127,7 +127,7 @@ impl ToBase58 for Address { Network::Testnet => 111 } ]; - ret.push_all(&self.hash[..]); + ret.extend(self.hash[..].iter().cloned()); ret } } diff --git a/src/wallet/address_index.rs b/src/wallet/address_index.rs index 0d1d9a8..bd1f691 100644 --- a/src/wallet/address_index.rs +++ b/src/wallet/address_index.rs @@ -19,7 +19,7 @@ //! use std::collections::HashMap; -use std::hash::{hash, Hash, Hasher, SipHasher}; +use std::hash::{Hash, Hasher, SipHasher}; use secp256k1::key::SecretKey; @@ -88,7 +88,7 @@ impl AddressIndex { txo: txo.clone(), kind: WalletTxOutType::Unknown }; - let mut entry = ret.tentative_index.entry(txo.script_pubkey.clone()); + let entry = ret.tentative_index.entry(txo.script_pubkey.clone()); let txos = entry.or_insert(vec![]); txos.push(new); } @@ -101,7 +101,7 @@ impl AddressIndex { pub fn index_wallet_txo(&mut self, wtx: &WalletTxOut, kind: WalletTxOutType) { let mut new = wtx.clone(); new.kind = kind; - let mut entry = self.index.entry((wtx.txid, wtx.vout)); + let entry = self.index.entry((wtx.txid, wtx.vout)); let txos = entry.or_insert(vec![]); txos.push(new); } diff --git a/src/wallet/bip32.rs b/src/wallet/bip32.rs index f51f224..1bfab8c 100644 --- a/src/wallet/bip32.rs +++ b/src/wallet/bip32.rs @@ -292,12 +292,12 @@ impl ExtendedPubKey { impl ToBase58 for ExtendedPrivKey { fn base58_layout(&self) -> Vec { let mut ret = Vec::with_capacity(78); - ret.push_all(&match self.network { + ret.extend(match self.network { Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4], Network::Testnet => [0x04, 0x35, 0x83, 0x94] - }); + }.iter().cloned()); ret.push(self.depth as u8); - ret.push_all(&self.parent_fingerprint[..]); + ret.extend(self.parent_fingerprint[..].iter().cloned()); let mut be_n = [0; 32]; match self.child_number { ChildNumber::Hardened(n) => { @@ -307,10 +307,10 @@ impl ToBase58 for ExtendedPrivKey { BigEndian::write_u32(&mut be_n, n); } } - ret.push_all(&be_n); - ret.push_all(&self.chain_code[..]); + ret.extend(be_n.iter().cloned()); + ret.extend(self.chain_code[..].iter().cloned()); ret.push(0); - ret.push_all(&self.secret_key[..]); + ret.extend(self.secret_key[..].iter().cloned()); ret } } @@ -346,12 +346,12 @@ impl ToBase58 for ExtendedPubKey { fn base58_layout(&self) -> Vec { assert!(self.public_key.is_compressed()); let mut ret = Vec::with_capacity(78); - ret.push_all(&match self.network { + ret.extend(match self.network { Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E], Network::Testnet => [0x04u8, 0x35, 0x87, 0xCF] - }); + }.iter().cloned()); ret.push(self.depth as u8); - ret.push_all(&self.parent_fingerprint[..]); + ret.extend(self.parent_fingerprint[..].iter().cloned()); let mut be_n = [0; 32]; match self.child_number { ChildNumber::Hardened(n) => { @@ -361,9 +361,9 @@ impl ToBase58 for ExtendedPubKey { BigEndian::write_u32(&mut be_n, n); } } - ret.push_all(&be_n); - ret.push_all(&self.chain_code[..]); - ret.push_all(&self.public_key[..]); + ret.extend(be_n.iter().cloned()); + ret.extend(self.chain_code[..].iter().cloned()); + ret.extend(self.public_key[..].iter().cloned()); ret } } @@ -524,7 +524,7 @@ mod tests { let msk = ExtendedPrivKey::new_master(Bitcoin, &seed).unwrap(); let mut i = 0; bh.iter( || { - black_box(msk.ckd_priv(Normal(i))); + black_box(msk.ckd_priv(Normal(i)).unwrap()); i += 1; }) } @@ -535,7 +535,7 @@ mod tests { let msk = ExtendedPrivKey::new_master(Bitcoin, &seed).unwrap(); let mut i = 0; bh.iter( || { - black_box(msk.ckd_priv(Hardened(i))); + black_box(msk.ckd_priv(Hardened(i)).unwrap()); i += 1; }) } @@ -548,7 +548,7 @@ mod tests { let mut i = 0; bh.iter( || { - black_box(mpk.ckd_pub(Normal(i))); + black_box(mpk.ckd_pub(Normal(i)).unwrap()); i += 1; }) } diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index bed2e0b..36fb08c 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -88,7 +88,6 @@ pub struct Wallet { impl Serialize for Wallet { fn serialize(&self, s: &mut S) -> Result<(), S::Error> where S: Serializer { - let len = self.accounts.len(); try!(self.master.serialize(s)); self.accounts.serialize(s) } @@ -176,11 +175,11 @@ impl Wallet { AccountChain::Internal => (account.internal_next, try!(ExtendedPrivKey::from_path( &self.master, - account.internal_path.as_slice()).map_err(Error::Bip32Error))), + &account.internal_path).map_err(Error::Bip32Error))), AccountChain::External => (account.external_next, try!(ExtendedPrivKey::from_path( &self.master, - account.external_path.as_slice()).map_err(Error::Bip32Error))), + &account.external_path).map_err(Error::Bip32Error))), }; // Scan for next admissible address @@ -247,7 +246,7 @@ impl Wallet { // Sum internal balance let master = try!(ExtendedPrivKey::from_path( &self.master, - account.internal_path.as_slice()).map_err(Error::Bip32Error)); + &account.internal_path).map_err(Error::Bip32Error)); for &cnum in account.internal_used.iter() { let sk = try!(master.ckd_priv(cnum).map_err(Error::Bip32Error)); let pk = ExtendedPubKey::from_private(&sk); @@ -259,7 +258,7 @@ impl Wallet { // Sum external balance let master = try!(ExtendedPrivKey::from_path( &self.master, - account.external_path.as_slice()).map_err(Error::Bip32Error)); + &account.external_path).map_err(Error::Bip32Error)); for &cnum in account.external_used.iter() { let sk = try!(master.ckd_priv(cnum).map_err(Error::Bip32Error)); let pk = ExtendedPubKey::from_private(&sk);