*** IT COMPILES ON RUSTC NIGHTLY ***
Many unit test failures, but this is progress.
This commit is contained in:
parent
3117f95b62
commit
17e27ec09f
|
@ -16,6 +16,7 @@ git = "https://github.com/carllerche/eventual"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = "*"
|
byteorder = "*"
|
||||||
|
num = "*"
|
||||||
num_cpus = "*"
|
num_cpus = "*"
|
||||||
rand = "*"
|
rand = "*"
|
||||||
rust-crypto = "*"
|
rust-crypto = "*"
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
//! these blocks and the blockchain.
|
//! these blocks and the blockchain.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::num::{Zero, from_u64};
|
use num::{FromPrimitive, Zero};
|
||||||
|
|
||||||
use util;
|
use util;
|
||||||
use util::Error::{SpvBadTarget, SpvBadProofOfWork};
|
use util::Error::{SpvBadTarget, SpvBadProofOfWork};
|
||||||
|
@ -90,7 +90,7 @@ impl BlockHeader {
|
||||||
if mant > 0x7FFFFF {
|
if mant > 0x7FFFFF {
|
||||||
Zero::zero()
|
Zero::zero()
|
||||||
} else {
|
} else {
|
||||||
from_u64::<Uint256>(mant as u64).unwrap() << (expt as usize)
|
<Uint256 as FromPrimitive>::from_u64(mant as u64).unwrap() << (expt as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
//! to make sure we are holding the only references.
|
//! to make sure we are holding the only references.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::num::Zero;
|
use num::{FromPrimitive, Zero};
|
||||||
use std::{marker, num, ptr};
|
use std::{marker, ptr};
|
||||||
|
|
||||||
use blockdata::block::{Block, BlockHeader};
|
use blockdata::block::{Block, BlockHeader};
|
||||||
use blockdata::transaction::Transaction;
|
use blockdata::transaction::Transaction;
|
||||||
|
@ -470,7 +470,7 @@ impl Blockchain {
|
||||||
// Compute new target
|
// Compute new target
|
||||||
let mut target = unsafe { (*prev).block.header.target() };
|
let mut target = unsafe { (*prev).block.header.target() };
|
||||||
target = target.mul_u32(timespan);
|
target = target.mul_u32(timespan);
|
||||||
target = target / 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)
|
// Clamp below MAX_TARGET (difficulty 1)
|
||||||
let max = max_target(self.network);
|
let max = max_target(self.network);
|
||||||
if target > max { target = max };
|
if target > max { target = max };
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::num::from_u64;
|
use num::FromPrimitive;
|
||||||
|
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use blockdata::script;
|
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)
|
/// In Bitcoind this is insanely described as ~((u256)0 >> 32)
|
||||||
pub fn max_target(_: Network) -> Uint256 {
|
pub fn max_target(_: Network) -> Uint256 {
|
||||||
from_u64::<Uint256>(0xFFFF).unwrap() << 208
|
<Uint256 as FromPrimitive>::from_u64(0xFFFF).unwrap() << 208
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The maximum value allowed in an output (useful for sanity checking,
|
/// The maximum value allowed in an output (useful for sanity checking,
|
||||||
|
@ -73,7 +73,7 @@ fn bitcoin_genesis_tx() -> Transaction {
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
let mut out_script = script::Builder::new();
|
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);
|
out_script.push_opcode(opcodes::All::OP_CHECKSIG);
|
||||||
ret.output.push(TxOut {
|
ret.output.push(TxOut {
|
||||||
value: 50 * COIN_VALUE,
|
value: 50 * COIN_VALUE,
|
||||||
|
|
|
@ -24,7 +24,6 @@ use serde;
|
||||||
|
|
||||||
// Heavy stick to translate between opcode types
|
// Heavy stick to translate between opcode types
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use network::serialize::{SimpleDecoder, SimpleEncoder};
|
use network::serialize::{SimpleDecoder, SimpleEncoder};
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
|
|
|
@ -28,7 +28,6 @@ use std::hash;
|
||||||
use std::char::from_digit;
|
use std::char::from_digit;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use serialize::json;
|
|
||||||
use serialize::hex::ToHex;
|
use serialize::hex::ToHex;
|
||||||
|
|
||||||
use crypto::digest::Digest;
|
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
|
/// An object which can be used to construct a script piece by piece
|
||||||
pub struct Builder(Vec<u8>);
|
pub struct Builder(Vec<u8>);
|
||||||
|
display_from_debug!(Builder);
|
||||||
|
|
||||||
impl hash::Hash for Script {
|
impl hash::Hash for Script {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -875,7 +875,7 @@ impl AbstractStackElem {
|
||||||
}
|
}
|
||||||
|
|
||||||
let validators = self.validators.clone();
|
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));
|
try!((v.update)(self, &v.args));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2084,12 +2084,10 @@ impl Script {
|
||||||
/// Checks whether a script pubkey is a p2sh output
|
/// Checks whether a script pubkey is a p2sh output
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_p2sh(&self) -> bool {
|
pub fn is_p2sh(&self) -> bool {
|
||||||
unsafe {
|
self.0.len() == 23 &&
|
||||||
self.0.len() == 23 &&
|
self.0[0] == opcodes::All::OP_HASH160 as u8 &&
|
||||||
self.0[0] == opcodes::All::OP_HASH160 as u8 &&
|
self.0[1] == opcodes::All::OP_PUSHBYTES_20 as u8 &&
|
||||||
self.0[1] == opcodes::All::OP_PUSHBYTES_20 as u8 &&
|
self.0[22] == opcodes::All::OP_EQUAL as u8
|
||||||
self.0[22] == opcodes::All::OP_EQUAL as u8
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a script can be proven to have no satisfying input
|
/// 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!")
|
_ => panic!("tried to put a 4bn+ sized object into a script!")
|
||||||
}
|
}
|
||||||
// Then push the acraw
|
// 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) {
|
pub fn push_opcode(&mut self, data: opcodes::All) {
|
||||||
self.0.push(data as u8);
|
self.0.push(data as u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts the `Builder` into an unmodifiable `Script`
|
||||||
pub fn into_script(self) -> Script {
|
pub fn into_script(self) -> Script {
|
||||||
Script(self.0.into_boxed_slice())
|
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(4); comp.push(85u8); assert_eq!(&script[..], &comp[..]);
|
||||||
script.push_int(-1); comp.push(80u8); assert_eq!(&script[..], &comp[..]);
|
script.push_int(-1); comp.push(80u8); assert_eq!(&script[..], &comp[..]);
|
||||||
// forced scriptint
|
// 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
|
// big ints
|
||||||
script.push_int(17); comp.push_all(&[1u8, 17]); assert_eq!(&script[..], &comp[..]);
|
script.push_int(17); comp.extend([1u8, 17].iter().cloned()); assert_eq!(&script[..], &comp[..]);
|
||||||
script.push_int(10000); comp.push_all(&[2u8, 16, 39]); 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
|
// 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.extend([4u8, 128, 150, 152, 0].iter().cloned()); 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, 128].iter().cloned()); assert_eq!(&script[..], &comp[..]);
|
||||||
|
|
||||||
// data
|
// 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
|
// opcodes
|
||||||
script.push_opcode(opcodes::All::OP_CHECKSIG); comp.push(0xACu8); assert_eq!(&script[..], &comp[..]);
|
script.push_opcode(opcodes::All::OP_CHECKSIG); comp.push(0xACu8); assert_eq!(&script[..], &comp[..]);
|
||||||
|
|
|
@ -134,7 +134,7 @@ impl UtxoSet {
|
||||||
fn add_utxos(&mut self, tx: &Transaction, height: u32) -> Option<UtxoNode> {
|
fn add_utxos(&mut self, tx: &Transaction, height: u32) -> Option<UtxoNode> {
|
||||||
let txid = tx.bitcoin_hash();
|
let txid = tx.bitcoin_hash();
|
||||||
// Locate node if it's already there
|
// Locate node if it's already there
|
||||||
let new_node = unsafe {
|
let new_node = {
|
||||||
let mut new_node = Vec::with_capacity(tx.output.len());
|
let mut new_node = Vec::with_capacity(tx.output.len());
|
||||||
for txo in tx.output.iter() {
|
for txo in tx.output.iter() {
|
||||||
// Unsafe since we are not uninitializing the old data in the vector
|
// Unsafe since we are not uninitializing the old data in the vector
|
||||||
|
@ -353,14 +353,12 @@ impl UtxoSet {
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
unsafe {
|
let mut thinvec = Vec::with_capacity(n as usize + 1);
|
||||||
let mut thinvec = Vec::with_capacity(n as usize + 1);
|
for _ in 0..n {
|
||||||
for _ in 0..n {
|
thinvec.push(None);
|
||||||
thinvec.push(None);
|
|
||||||
}
|
|
||||||
thinvec.push(Some(txo));
|
|
||||||
UtxoNode { outputs: thinvec.into_boxed_slice(), height: height }
|
|
||||||
}
|
}
|
||||||
|
thinvec.push(Some(txo));
|
||||||
|
UtxoNode { outputs: thinvec.into_boxed_slice(), height: height }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Ram it back into the tree
|
// Ram it back into the tree
|
||||||
|
@ -416,7 +414,6 @@ impl UtxoSet {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::prelude::*;
|
|
||||||
use serialize::hex::FromHex;
|
use serialize::hex::FromHex;
|
||||||
|
|
||||||
use super::{UtxoSet, ValidationLevel};
|
use super::{UtxoSet, ValidationLevel};
|
||||||
|
|
|
@ -167,7 +167,7 @@ macro_rules! impl_array_newtype_encodable {
|
||||||
None => return Err(::serde::de::Error::end_of_stream_error())
|
None => return Err(::serde::de::Error::end_of_stream_error())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
v.end();
|
try!(v.end());
|
||||||
Ok($thing(ret))
|
Ok($thing(ret))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
src/lib.rs
20
src/lib.rs
|
@ -29,28 +29,27 @@
|
||||||
|
|
||||||
// Experimental features we need
|
// Experimental features we need
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(custom_derive, plugin)]
|
|
||||||
#![feature(overloaded_calls)]
|
|
||||||
#![feature(unsafe_destructor)]
|
|
||||||
#![feature(unboxed_closure_sugar)]
|
|
||||||
#![feature(unboxed_closures)]
|
|
||||||
#![feature(concat_idents)]
|
#![feature(concat_idents)]
|
||||||
|
#![feature(custom_derive, plugin)]
|
||||||
|
#![feature(hash)]
|
||||||
|
#![feature(ip_addr)]
|
||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
|
#![feature(std_misc)]
|
||||||
|
#![cfg_attr(test, feature(test))]
|
||||||
|
|
||||||
// Coding conventions
|
// Coding conventions
|
||||||
#![warn(non_uppercase_statics)]
|
#![deny(non_upper_case_globals)]
|
||||||
#![deny(non_camel_case_types)]
|
#![deny(non_camel_case_types)]
|
||||||
#![deny(non_snake_case)]
|
#![deny(non_snake_case)]
|
||||||
#![deny(unused_mut)]
|
#![deny(unused_mut)]
|
||||||
#![warn(missing_doc)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
#![plugin(serde_macros)]
|
#![plugin(serde_macros)]
|
||||||
|
|
||||||
extern crate alloc;
|
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
extern crate collections;
|
|
||||||
extern crate crypto;
|
extern crate crypto;
|
||||||
extern crate eventual;
|
extern crate eventual;
|
||||||
|
extern crate num;
|
||||||
extern crate num_cpus;
|
extern crate num_cpus;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate rustc_serialize as serialize;
|
extern crate rustc_serialize as serialize;
|
||||||
|
@ -71,6 +70,3 @@ pub mod blockdata;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod wallet;
|
pub mod wallet;
|
||||||
|
|
||||||
/// I dunno where else to put this..
|
|
||||||
fn assert_type_is_copy<T: Copy>() { }
|
|
||||||
|
|
||||||
|
|
|
@ -203,7 +203,7 @@ impl_array!(12);
|
||||||
impl_array!(16);
|
impl_array!(16);
|
||||||
impl_array!(32);
|
impl_array!(32);
|
||||||
|
|
||||||
impl<'a, S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for &'a [T] {
|
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for [T] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
||||||
try!(VarInt(self.len() as u64).consensus_encode(s));
|
try!(VarInt(self.len() as u64).consensus_encode(s));
|
||||||
|
@ -239,12 +239,10 @@ impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Box<[
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Box<[T]>, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Box<[T]>, D::Error> {
|
||||||
let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d));
|
let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d));
|
||||||
unsafe {
|
let len = len as usize;
|
||||||
let len = len as usize;
|
let mut ret = Vec::with_capacity(len);
|
||||||
let mut ret = Vec::with_capacity(len);
|
for _ in 0..len { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
|
||||||
for i in 0..len { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
|
Ok(ret.into_boxed_slice())
|
||||||
Ok(ret.into_boxed_slice())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,7 +455,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_vector_test() {
|
fn serialize_vector_test() {
|
||||||
assert_eq!(serialize(&vec![1u8, 2, 3]).ok(), Some(vec![3u8, 1, 2, 3]));
|
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
|
// TODO: test vectors of more interesting objects
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +529,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deserialize_strbuf_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]
|
#[test]
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
//! to connect to a peer, send network messages, and receive Bitcoin data.
|
//! to connect to a peer, send network messages, and receive Bitcoin data.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::{io, thread};
|
use std::thread;
|
||||||
use std::sync::mpsc::{channel, Receiver};
|
use std::sync::mpsc::{channel, Receiver};
|
||||||
|
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
|
@ -75,7 +75,7 @@ pub trait Listener {
|
||||||
// We have to pass the message to the main thread for processing,
|
// We have to pass the message to the main thread for processing,
|
||||||
// unfortunately, because sipa says we have to handle everything
|
// unfortunately, because sipa says we have to handle everything
|
||||||
// in order.
|
// in order.
|
||||||
recv_tx.send(message::SocketResponse::MessageReceived(payload));
|
recv_tx.send(message::SocketResponse::MessageReceived(payload)).unwrap();
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// On failure we send an error message to the main thread, along with
|
// On failure we send an error message to the main thread, along with
|
||||||
|
@ -83,8 +83,8 @@ pub trait Listener {
|
||||||
// thread. (If we simply exited immediately, the channel would be torn
|
// thread. (If we simply exited immediately, the channel would be torn
|
||||||
// down and the main thread would never see the error message.)
|
// down and the main thread would never see the error message.)
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
recv_tx.send(message::SocketResponse::ConnectionFailed(e, tx));
|
recv_tx.send(message::SocketResponse::ConnectionFailed(e, tx)).unwrap();
|
||||||
rx.recv();
|
rx.recv().unwrap();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,8 @@
|
||||||
//! also defines (de)serialization routines for many primitives.
|
//! also defines (de)serialization routines for many primitives.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use collections::Vec;
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::io::{self, Cursor};
|
use std::io::Cursor;
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
use blockdata::block;
|
use blockdata::block;
|
||||||
|
@ -41,9 +40,14 @@ pub struct CommandString(pub String);
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for CommandString {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for CommandString {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
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 &CommandString(ref inner_str) = self;
|
||||||
let mut rawbytes = [0u8; 12];
|
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)
|
rawbytes.consensus_encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +169,7 @@ impl<D: SimpleDecoder<Error=util::Error>> ConsensusDecodable<D> for RawNetworkMe
|
||||||
let CheckedData(raw_payload): CheckedData = try!(ConsensusDecodable::consensus_decode(d));
|
let CheckedData(raw_payload): CheckedData = try!(ConsensusDecodable::consensus_decode(d));
|
||||||
|
|
||||||
let mut mem_d = RawDecoder::new(Cursor::new(raw_payload));
|
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)))),
|
"version" => NetworkMessage::Version(try!(propagate_err("version".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"verack" => NetworkMessage::Verack,
|
"verack" => NetworkMessage::Verack,
|
||||||
"addr" => NetworkMessage::Addr(try!(propagate_err("addr".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"addr" => NetworkMessage::Addr(try!(propagate_err("addr".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
|
@ -196,7 +200,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_commandstring_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]));
|
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() {
|
fn deserialize_commandstring_test() {
|
||||||
let cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
|
let cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
|
||||||
assert!(cs.is_ok());
|
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<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
|
let short_cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
|
||||||
assert!(short_cs.is_err());
|
assert!(short_cs.is_err());
|
||||||
|
|
|
@ -96,7 +96,7 @@ mod tests {
|
||||||
assert_eq!(real_decode.timestamp, 1401217254);
|
assert_eq!(real_decode.timestamp, 1401217254);
|
||||||
// address decodes should be covered by Address tests
|
// address decodes should be covered by Address tests
|
||||||
assert_eq!(real_decode.nonce, 16735069437859780935);
|
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.start_height, 302892);
|
||||||
assert_eq!(real_decode.relay, true);
|
assert_eq!(real_decode.relay, true);
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,7 @@
|
||||||
//! It also defines (de)serialization routines for many primitives.
|
//! It also defines (de)serialization routines for many primitives.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use collections::Vec;
|
use std::io::{Cursor, Read, Write};
|
||||||
use std::io::{self, Cursor, Read, Write};
|
|
||||||
use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt};
|
use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt};
|
||||||
use serialize::hex::ToHex;
|
use serialize::hex::ToHex;
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ impl BitcoinHash for Vec<u8> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode an object into a vector
|
/// Encode an object into a vector
|
||||||
pub fn serialize<T>(data: &T) -> Result<Vec<u8>, util::Error>
|
pub fn serialize<T: ?Sized>(data: &T) -> Result<Vec<u8>, util::Error>
|
||||||
where T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>,
|
where T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>,
|
||||||
{
|
{
|
||||||
let mut encoder = RawEncoder::new(Cursor::new(vec![]));
|
let mut encoder = RawEncoder::new(Cursor::new(vec![]));
|
||||||
|
@ -51,7 +50,7 @@ pub fn serialize<T>(data: &T) -> Result<Vec<u8>, util::Error>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode an object into a hex-encoded string
|
/// Encode an object into a hex-encoded string
|
||||||
pub fn serialize_hex<T>(data: &T) -> Result<String, util::Error>
|
pub fn serialize_hex<T: ?Sized>(data: &T) -> Result<String, util::Error>
|
||||||
where T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>
|
where T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>
|
||||||
{
|
{
|
||||||
let serial = try!(serialize(data));
|
let serial = try!(serialize(data));
|
||||||
|
@ -92,57 +91,59 @@ impl<R: Read> RawDecoder<R> {
|
||||||
|
|
||||||
/// A simple Encoder trait
|
/// A simple Encoder trait
|
||||||
pub trait SimpleEncoder {
|
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
|
/// Output a 64-bit int
|
||||||
fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
|
fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
|
||||||
/// Output a 32-bit uint
|
/// Output a 32-bit int
|
||||||
fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>;
|
fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>;
|
||||||
/// Output a 16-bit uint
|
/// Output a 16-bit int
|
||||||
fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>;
|
fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>;
|
||||||
/// Output a 8-bit uint
|
/// Output a 8-bit int
|
||||||
fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>;
|
fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
/// Output a 64-bit int
|
/// Output a boolean
|
||||||
fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
|
fn emit_bool(&mut self, v: bool) -> 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>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple Decoder trait
|
/// A simple Decoder trait
|
||||||
pub trait SimpleDecoder {
|
pub trait SimpleDecoder {
|
||||||
type Error;
|
/// A decoding error
|
||||||
|
type Error;
|
||||||
|
|
||||||
/// Read a 64-bit uint
|
/// Read a 64-bit uint
|
||||||
fn read_u64(&mut self) -> Result<u64, Self::Error>;
|
fn read_u64(&mut self) -> Result<u64, Self::Error>;
|
||||||
/// Read a 32-bit uint
|
/// Read a 32-bit uint
|
||||||
fn read_u32(&mut self) -> Result<u32, Self::Error>;
|
fn read_u32(&mut self) -> Result<u32, Self::Error>;
|
||||||
/// Read a 16-bit uint
|
/// Read a 16-bit uint
|
||||||
fn read_u16(&mut self) -> Result<u16, Self::Error>;
|
fn read_u16(&mut self) -> Result<u16, Self::Error>;
|
||||||
/// Read a 8-bit uint
|
/// Read a 8-bit uint
|
||||||
fn read_u8(&mut self) -> Result<u8, Self::Error>;
|
fn read_u8(&mut self) -> Result<u8, Self::Error>;
|
||||||
|
|
||||||
/// Read a 64-bit int
|
/// Read a 64-bit int
|
||||||
fn read_i64(&mut self) -> Result<i64, Self::Error>;
|
fn read_i64(&mut self) -> Result<i64, Self::Error>;
|
||||||
/// Read a 32-bit int
|
/// Read a 32-bit int
|
||||||
fn read_i32(&mut self) -> Result<i32, Self::Error>;
|
fn read_i32(&mut self) -> Result<i32, Self::Error>;
|
||||||
/// Read a 16-bit int
|
/// Read a 16-bit int
|
||||||
fn read_i16(&mut self) -> Result<i16, Self::Error>;
|
fn read_i16(&mut self) -> Result<i16, Self::Error>;
|
||||||
/// Read a 8-bit int
|
/// Read a 8-bit int
|
||||||
fn read_i8(&mut self) -> Result<i8, Self::Error>;
|
fn read_i8(&mut self) -> Result<i8, Self::Error>;
|
||||||
|
|
||||||
/// Read a boolean
|
/// Read a boolean
|
||||||
fn read_bool(&mut self) -> Result<bool, Self::Error>;
|
fn read_bool(&mut self) -> Result<bool, Self::Error>;
|
||||||
|
|
||||||
/// Signal a decoding error
|
/// Signal a decoding error
|
||||||
fn error(&mut self, err: String) -> Self::Error;
|
fn error(&mut self, err: String) -> Self::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! encoder_fn {
|
macro_rules! encoder_fn {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
use time::now;
|
use time::now;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use std::io::{self, Cursor, Write};
|
use std::io::{self, Write};
|
||||||
use std::net;
|
use std::net;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ pub struct Socket {
|
||||||
|
|
||||||
macro_rules! with_socket(($s:ident, $sock:ident, $body:block) => ({
|
macro_rules! with_socket(($s:ident, $sock:ident, $body:block) => ({
|
||||||
use ::std::ops::DerefMut;
|
use ::std::ops::DerefMut;
|
||||||
let mut sock_lock = $s.socket.lock();
|
let sock_lock = $s.socket.lock();
|
||||||
match sock_lock {
|
match sock_lock {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
||||||
|
@ -89,7 +89,7 @@ impl Socket {
|
||||||
socket: Arc::new(Mutex::new(None)),
|
socket: Arc::new(Mutex::new(None)),
|
||||||
services: 0,
|
services: 0,
|
||||||
version_nonce: rng.gen(),
|
version_nonce: rng.gen(),
|
||||||
user_agent: String::from_str(constants::USER_AGENT),
|
user_agent: constants::USER_AGENT.to_string(),
|
||||||
magic: constants::magic(network)
|
magic: constants::magic(network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Rust Bitcoin Library
|
||||||
|
// Written in 2014 by
|
||||||
|
// Andrew Poelstra <apoelstra@wpsoftware.net>
|
||||||
|
//
|
||||||
|
// 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 <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//! # 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());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
//! # Base58 encoder and decoder
|
//! # Base58 encoder and decoder
|
||||||
|
|
||||||
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
|
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
|
||||||
|
|
||||||
use std::{iter, str};
|
|
||||||
|
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
|
|
||||||
/// An error that might occur during base58 decoding
|
/// An error that might occur during base58 decoding
|
||||||
|
@ -129,17 +126,14 @@ pub fn base58_encode_slice(data: &[u8]) -> String {
|
||||||
assert_eq!(carry, 0);
|
assert_eq!(carry, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsafely translate the bytes to a utf8 string
|
// Copy leading zeroes directly
|
||||||
unsafe {
|
let mut ret: Vec<u8> = data.iter().take_while(|&&x| x == 0)
|
||||||
// Copy leading zeroes directly
|
.map(|_| BASE58_CHARS[0])
|
||||||
let mut ret: Vec<u8> = data.iter().take_while(|&&x| x == 0)
|
.collect();
|
||||||
.map(|_| BASE58_CHARS[0])
|
// Copy rest of string
|
||||||
.collect();
|
ret.extend(scratch.into_iter().skip_while(|&x| x == 0)
|
||||||
// Copy rest of string
|
.map(|x| BASE58_CHARS[x as usize]));
|
||||||
ret.extend(scratch.into_iter().skip_while(|&x| x == 0)
|
String::from_utf8(ret).unwrap()
|
||||||
.map(|x| BASE58_CHARS[x as usize]));
|
|
||||||
String::from_utf8(ret).unwrap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for objects which can be written as base58
|
/// Trait for objects which can be written as base58
|
||||||
|
@ -157,7 +151,7 @@ pub trait ToBase58 {
|
||||||
fn to_base58check(&self) -> String {
|
fn to_base58check(&self) -> String {
|
||||||
let mut data = self.base58_layout();
|
let mut data = self.base58_layout();
|
||||||
let checksum = Sha256dHash::from_data(&data).into_le().low_u32();
|
let checksum = Sha256dHash::from_data(&data).into_le().low_u32();
|
||||||
data.write_u32::<LittleEndian>(checksum);
|
data.write_u32::<LittleEndian>(checksum).unwrap();
|
||||||
base58_encode_slice(&data)
|
base58_encode_slice(&data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,16 +21,14 @@ use std::default::Default;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
use std::hash;
|
|
||||||
use serde;
|
use serde;
|
||||||
|
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
use crypto::sha2::Sha256;
|
use crypto::sha2::Sha256;
|
||||||
use crypto::ripemd160::Ripemd160;
|
use crypto::ripemd160::Ripemd160;
|
||||||
|
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder};
|
use network::serialize::{RawEncoder, BitcoinHash};
|
||||||
use util::uint::Uint256;
|
use util::uint::Uint256;
|
||||||
|
|
||||||
/// A Bitcoin hash, 32-bytes, computed from x as SHA256(SHA256(x))
|
/// 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 {
|
impl ::std::fmt::Debug for Sha256dHash {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
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 {
|
impl fmt::LowerHex for Sha256dHash {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let &Sha256dHash(data) = self;
|
let &Sha256dHash(data) = self;
|
||||||
let mut rv = [0; 64];
|
|
||||||
for ch in data.iter().rev() {
|
for ch in data.iter().rev() {
|
||||||
try!(write!(f, "{:02x}", ch));
|
try!(write!(f, "{:02x}", ch));
|
||||||
}
|
}
|
||||||
|
@ -264,10 +261,7 @@ impl <T: BitcoinHash> MerkleRoot for Vec<T> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::prelude::*;
|
use num::FromPrimitive;
|
||||||
use std::io::Cursor;
|
|
||||||
use std::num::FromPrimitive;
|
|
||||||
use std::str::from_utf8;
|
|
||||||
use serde::{json, Serialize, Deserialize};
|
use serde::{json, Serialize, Deserialize};
|
||||||
|
|
||||||
use network::serialize::{serialize, deserialize};
|
use network::serialize::{serialize, deserialize};
|
||||||
|
|
|
@ -97,8 +97,6 @@ pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> usize {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::prelude::*;
|
|
||||||
|
|
||||||
use super::script_find_and_remove;
|
use super::script_find_and_remove;
|
||||||
use super::hex_bytes;
|
use super::hex_bytes;
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::marker;
|
use std::marker;
|
||||||
use std::num::{Zero, One};
|
|
||||||
use std::{cmp, fmt, ops, ptr};
|
use std::{cmp, fmt, ops, ptr};
|
||||||
|
use num::{Zero, One};
|
||||||
|
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{SimpleDecoder, SimpleEncoder};
|
use network::serialize::{SimpleDecoder, SimpleEncoder};
|
||||||
|
@ -549,9 +549,8 @@ impl<'a, K: Copy, V> Iterator for MutItems<'a, K, V> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::prelude::*;
|
use num::Zero;
|
||||||
use std::num::Zero;
|
use num::FromPrimitive;
|
||||||
use std::num::FromPrimitive;
|
|
||||||
|
|
||||||
use network::serialize::{deserialize, serialize};
|
use network::serialize::{deserialize, serialize};
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
|
|
|
@ -19,9 +19,8 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::num::{Zero, One};
|
use num::{FromPrimitive, Zero, One};
|
||||||
|
|
||||||
use network::serialize::RawEncoder;
|
|
||||||
use util::BitArray;
|
use util::BitArray;
|
||||||
|
|
||||||
macro_rules! construct_uint {
|
macro_rules! construct_uint {
|
||||||
|
@ -66,7 +65,7 @@ macro_rules! construct_uint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::num::FromPrimitive for $name {
|
impl FromPrimitive for $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_u64(init: u64) -> Option<$name> {
|
fn from_u64(init: u64) -> Option<$name> {
|
||||||
let mut ret = [0; $n_words];
|
let mut ret = [0; $n_words];
|
||||||
|
@ -76,15 +75,17 @@ macro_rules! construct_uint {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_i64(init: i64) -> Option<$name> {
|
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 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 {
|
fn one() -> $name {
|
||||||
$name({ let mut ret = [0; $n_words]; ret[0] = 1; ret })
|
$name({ let mut ret = [0; $n_words]; ret[0] = 1; ret })
|
||||||
}
|
}
|
||||||
|
@ -289,7 +290,6 @@ macro_rules! construct_uint {
|
||||||
impl ::std::ops::Shr<usize> for $name {
|
impl ::std::ops::Shr<usize> for $name {
|
||||||
type Output = $name;
|
type Output = $name;
|
||||||
|
|
||||||
#[allow(unsigned_negate)]
|
|
||||||
fn shr(self, shift: usize) -> $name {
|
fn shr(self, shift: usize) -> $name {
|
||||||
let $name(ref original) = self;
|
let $name(ref original) = self;
|
||||||
let mut ret = [0u64; $n_words];
|
let mut ret = [0u64; $n_words];
|
||||||
|
@ -388,7 +388,7 @@ impl Uint256 {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::num::from_u64;
|
use num::FromPrimitive;
|
||||||
|
|
||||||
use network::serialize::{deserialize, serialize};
|
use network::serialize::{deserialize, serialize};
|
||||||
use util::uint::Uint256;
|
use util::uint::Uint256;
|
||||||
|
@ -396,14 +396,14 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn uint256_bits_test() {
|
pub fn uint256_bits_test() {
|
||||||
assert_eq!(from_u64::<Uint256>(255).unwrap().bits(), 8);
|
assert_eq!(<Uint256 as FromPrimitive>::from_u64(255).unwrap().bits(), 8);
|
||||||
assert_eq!(from_u64::<Uint256>(256).unwrap().bits(), 9);
|
assert_eq!(<Uint256 as FromPrimitive>::from_u64(256).unwrap().bits(), 9);
|
||||||
assert_eq!(from_u64::<Uint256>(300).unwrap().bits(), 9);
|
assert_eq!(<Uint256 as FromPrimitive>::from_u64(300).unwrap().bits(), 9);
|
||||||
assert_eq!(from_u64::<Uint256>(60000).unwrap().bits(), 16);
|
assert_eq!(<Uint256 as FromPrimitive>::from_u64(60000).unwrap().bits(), 16);
|
||||||
assert_eq!(from_u64::<Uint256>(70000).unwrap().bits(), 17);
|
assert_eq!(<Uint256 as FromPrimitive>::from_u64(70000).unwrap().bits(), 17);
|
||||||
|
|
||||||
// Try to read the following lines out loud quickly
|
// Try to read the following lines out loud quickly
|
||||||
let mut shl: Uint256 = from_u64(70000).unwrap();
|
let mut shl = <Uint256 as FromPrimitive>::from_u64(70000).unwrap();
|
||||||
shl = shl << 100;
|
shl = shl << 100;
|
||||||
assert_eq!(shl.bits(), 117);
|
assert_eq!(shl.bits(), 117);
|
||||||
shl = shl << 100;
|
shl = shl << 100;
|
||||||
|
@ -412,11 +412,11 @@ mod tests {
|
||||||
assert_eq!(shl.bits(), 0);
|
assert_eq!(shl.bits(), 0);
|
||||||
|
|
||||||
// Bit set check
|
// Bit set check
|
||||||
assert!(!from_u64::<Uint256>(10).unwrap().bit(0));
|
assert!(!<Uint256 as FromPrimitive>::from_u64(10).unwrap().bit(0));
|
||||||
assert!(from_u64::<Uint256>(10).unwrap().bit(1));
|
assert!(<Uint256 as FromPrimitive>::from_u64(10).unwrap().bit(1));
|
||||||
assert!(!from_u64::<Uint256>(10).unwrap().bit(2));
|
assert!(!<Uint256 as FromPrimitive>::from_u64(10).unwrap().bit(2));
|
||||||
assert!(from_u64::<Uint256>(10).unwrap().bit(3));
|
assert!(<Uint256 as FromPrimitive>::from_u64(10).unwrap().bit(3));
|
||||||
assert!(!from_u64::<Uint256>(10).unwrap().bit(4));
|
assert!(!<Uint256 as FromPrimitive>::from_u64(10).unwrap().bit(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -438,7 +438,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn uint256_arithmetic_test() {
|
pub fn uint256_arithmetic_test() {
|
||||||
let init: Uint256 = from_u64(0xDEADBEEFDEADBEEF).unwrap();
|
let init = <Uint256 as FromPrimitive>::from_u64(0xDEADBEEFDEADBEEF).unwrap();
|
||||||
let copy = init;
|
let copy = init;
|
||||||
|
|
||||||
let add = init + copy;
|
let add = init + copy;
|
||||||
|
@ -459,17 +459,17 @@ mod tests {
|
||||||
let mult = sub.mul_u32(300);
|
let mult = sub.mul_u32(300);
|
||||||
assert_eq!(mult, Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]));
|
assert_eq!(mult, Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]));
|
||||||
// Division
|
// Division
|
||||||
assert_eq!(from_u64::<Uint256>(105).unwrap() /
|
assert_eq!(<Uint256 as FromPrimitive>::from_u64(105).unwrap() /
|
||||||
from_u64::<Uint256>(5).unwrap(),
|
<Uint256 as FromPrimitive>::from_u64(5).unwrap(),
|
||||||
from_u64::<Uint256>(21).unwrap());
|
<Uint256 as FromPrimitive>::from_u64(21).unwrap());
|
||||||
let div = mult / from_u64::<Uint256>(300).unwrap();
|
let div = mult / <Uint256 as FromPrimitive>::from_u64(300).unwrap();
|
||||||
assert_eq!(div, Uint256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0]));
|
assert_eq!(div, Uint256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0]));
|
||||||
// TODO: bit inversion
|
// TODO: bit inversion
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn uint256_bitslice_test() {
|
pub fn uint256_bitslice_test() {
|
||||||
let init = from_u64::<Uint256>(0xDEADBEEFDEADBEEF).unwrap();
|
let init = <Uint256 as FromPrimitive>::from_u64(0xDEADBEEFDEADBEEF).unwrap();
|
||||||
let add = init + (init << 64);
|
let add = init + (init << 64);
|
||||||
assert_eq!(add.bit_slice(64, 128), init);
|
assert_eq!(add.bit_slice(64, 128), init);
|
||||||
assert_eq!(add.mask(64), init);
|
assert_eq!(add.mask(64), init);
|
||||||
|
@ -479,7 +479,7 @@ mod tests {
|
||||||
pub fn uint256_extreme_bitshift_test() {
|
pub fn uint256_extreme_bitshift_test() {
|
||||||
// Shifting a u64 by 64 bits gives an undefined value, so make sure that
|
// Shifting a u64 by 64 bits gives an undefined value, so make sure that
|
||||||
// we're doing the Right Thing here
|
// we're doing the Right Thing here
|
||||||
let init = from_u64::<Uint256>(0xDEADBEEFDEADBEEF).unwrap();
|
let init = <Uint256 as FromPrimitive>::from_u64(0xDEADBEEFDEADBEEF).unwrap();
|
||||||
|
|
||||||
assert_eq!(init << 64, Uint256([0, 0xDEADBEEFDEADBEEF, 0, 0]));
|
assert_eq!(init << 64, Uint256([0, 0xDEADBEEFDEADBEEF, 0, 0]));
|
||||||
let add = (init << 64) + init;
|
let add = (init << 64) + init;
|
||||||
|
|
|
@ -127,7 +127,7 @@ impl ToBase58 for Address {
|
||||||
Network::Testnet => 111
|
Network::Testnet => 111
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
ret.push_all(&self.hash[..]);
|
ret.extend(self.hash[..].iter().cloned());
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::{hash, Hash, Hasher, SipHasher};
|
use std::hash::{Hash, Hasher, SipHasher};
|
||||||
|
|
||||||
use secp256k1::key::SecretKey;
|
use secp256k1::key::SecretKey;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ impl AddressIndex {
|
||||||
txo: txo.clone(),
|
txo: txo.clone(),
|
||||||
kind: WalletTxOutType::Unknown
|
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![]);
|
let txos = entry.or_insert(vec![]);
|
||||||
txos.push(new);
|
txos.push(new);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ impl AddressIndex {
|
||||||
pub fn index_wallet_txo(&mut self, wtx: &WalletTxOut, kind: WalletTxOutType) {
|
pub fn index_wallet_txo(&mut self, wtx: &WalletTxOut, kind: WalletTxOutType) {
|
||||||
let mut new = wtx.clone();
|
let mut new = wtx.clone();
|
||||||
new.kind = kind;
|
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![]);
|
let txos = entry.or_insert(vec![]);
|
||||||
txos.push(new);
|
txos.push(new);
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,12 +292,12 @@ 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.extend(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]
|
||||||
});
|
}.iter().cloned());
|
||||||
ret.push(self.depth as u8);
|
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];
|
let mut be_n = [0; 32];
|
||||||
match self.child_number {
|
match self.child_number {
|
||||||
ChildNumber::Hardened(n) => {
|
ChildNumber::Hardened(n) => {
|
||||||
|
@ -307,10 +307,10 @@ impl ToBase58 for ExtendedPrivKey {
|
||||||
BigEndian::write_u32(&mut be_n, n);
|
BigEndian::write_u32(&mut be_n, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret.push_all(&be_n);
|
ret.extend(be_n.iter().cloned());
|
||||||
ret.push_all(&self.chain_code[..]);
|
ret.extend(self.chain_code[..].iter().cloned());
|
||||||
ret.push(0);
|
ret.push(0);
|
||||||
ret.push_all(&self.secret_key[..]);
|
ret.extend(self.secret_key[..].iter().cloned());
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,12 +346,12 @@ 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.extend(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]
|
||||||
});
|
}.iter().cloned());
|
||||||
ret.push(self.depth as u8);
|
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];
|
let mut be_n = [0; 32];
|
||||||
match self.child_number {
|
match self.child_number {
|
||||||
ChildNumber::Hardened(n) => {
|
ChildNumber::Hardened(n) => {
|
||||||
|
@ -361,9 +361,9 @@ impl ToBase58 for ExtendedPubKey {
|
||||||
BigEndian::write_u32(&mut be_n, n);
|
BigEndian::write_u32(&mut be_n, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret.push_all(&be_n);
|
ret.extend(be_n.iter().cloned());
|
||||||
ret.push_all(&self.chain_code[..]);
|
ret.extend(self.chain_code[..].iter().cloned());
|
||||||
ret.push_all(&self.public_key[..]);
|
ret.extend(self.public_key[..].iter().cloned());
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,7 +524,7 @@ mod tests {
|
||||||
let msk = ExtendedPrivKey::new_master(Bitcoin, &seed).unwrap();
|
let msk = ExtendedPrivKey::new_master(Bitcoin, &seed).unwrap();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
bh.iter( || {
|
bh.iter( || {
|
||||||
black_box(msk.ckd_priv(Normal(i)));
|
black_box(msk.ckd_priv(Normal(i)).unwrap());
|
||||||
i += 1;
|
i += 1;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -535,7 +535,7 @@ mod tests {
|
||||||
let msk = ExtendedPrivKey::new_master(Bitcoin, &seed).unwrap();
|
let msk = ExtendedPrivKey::new_master(Bitcoin, &seed).unwrap();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
bh.iter( || {
|
bh.iter( || {
|
||||||
black_box(msk.ckd_priv(Hardened(i)));
|
black_box(msk.ckd_priv(Hardened(i)).unwrap());
|
||||||
i += 1;
|
i += 1;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -548,7 +548,7 @@ mod tests {
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
bh.iter( || {
|
bh.iter( || {
|
||||||
black_box(mpk.ckd_pub(Normal(i)));
|
black_box(mpk.ckd_pub(Normal(i)).unwrap());
|
||||||
i += 1;
|
i += 1;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,6 @@ pub struct Wallet {
|
||||||
impl Serialize for Wallet {
|
impl Serialize for Wallet {
|
||||||
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer {
|
where S: Serializer {
|
||||||
let len = self.accounts.len();
|
|
||||||
try!(self.master.serialize(s));
|
try!(self.master.serialize(s));
|
||||||
self.accounts.serialize(s)
|
self.accounts.serialize(s)
|
||||||
}
|
}
|
||||||
|
@ -176,11 +175,11 @@ impl Wallet {
|
||||||
AccountChain::Internal => (account.internal_next,
|
AccountChain::Internal => (account.internal_next,
|
||||||
try!(ExtendedPrivKey::from_path(
|
try!(ExtendedPrivKey::from_path(
|
||||||
&self.master,
|
&self.master,
|
||||||
account.internal_path.as_slice()).map_err(Error::Bip32Error))),
|
&account.internal_path).map_err(Error::Bip32Error))),
|
||||||
AccountChain::External => (account.external_next,
|
AccountChain::External => (account.external_next,
|
||||||
try!(ExtendedPrivKey::from_path(
|
try!(ExtendedPrivKey::from_path(
|
||||||
&self.master,
|
&self.master,
|
||||||
account.external_path.as_slice()).map_err(Error::Bip32Error))),
|
&account.external_path).map_err(Error::Bip32Error))),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Scan for next admissible address
|
// Scan for next admissible address
|
||||||
|
@ -247,7 +246,7 @@ impl Wallet {
|
||||||
// Sum internal balance
|
// Sum internal balance
|
||||||
let master = try!(ExtendedPrivKey::from_path(
|
let master = try!(ExtendedPrivKey::from_path(
|
||||||
&self.master,
|
&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() {
|
for &cnum in account.internal_used.iter() {
|
||||||
let sk = try!(master.ckd_priv(cnum).map_err(Error::Bip32Error));
|
let sk = try!(master.ckd_priv(cnum).map_err(Error::Bip32Error));
|
||||||
let pk = ExtendedPubKey::from_private(&sk);
|
let pk = ExtendedPubKey::from_private(&sk);
|
||||||
|
@ -259,7 +258,7 @@ impl Wallet {
|
||||||
// Sum external balance
|
// Sum external balance
|
||||||
let master = try!(ExtendedPrivKey::from_path(
|
let master = try!(ExtendedPrivKey::from_path(
|
||||||
&self.master,
|
&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() {
|
for &cnum in account.external_used.iter() {
|
||||||
let sk = try!(master.ckd_priv(cnum).map_err(Error::Bip32Error));
|
let sk = try!(master.ckd_priv(cnum).map_err(Error::Bip32Error));
|
||||||
let pk = ExtendedPubKey::from_private(&sk);
|
let pk = ExtendedPubKey::from_private(&sk);
|
||||||
|
|
Loading…
Reference in New Issue