Drop ThinVec, many other changes toward updating for librustc

This commit is contained in:
Andrew Poelstra 2015-04-04 22:13:19 -05:00
parent 7a2cfe95e7
commit 160f2f9ea6
16 changed files with 247 additions and 567 deletions

View File

@ -17,5 +17,6 @@ num_cpus = "*"
rand = "*"
rust-crypto = "*"
rustc-serialize = "*"
serde = "*"
time = "*"

View File

@ -22,25 +22,20 @@
use serialize::json;
/// Submodule to handle -all- opcodes. Outside of this module we use
/// a restricted set where the push/return/noop/illegal opcodes have
/// a more convienient representation.
pub mod all {
use serialize::json;
// Heavy stick to translate between opcode types
use std::mem::transmute;
// Heavy stick to translate between opcode types
use std::mem::transmute;
use network::serialize::{SimpleDecoder, SimpleEncoder};
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::serialize::{SimpleDecoder, SimpleEncoder};
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
// Note: I am deliberately not implementing PartialOrd or Ord on the
// opcode enum. If you want to check ranges of opcodes, etc.,
// write an #[inline] helper function which casts to u8s.
// Note: I am deliberately not implementing PartialOrd or Ord on the
// opcode enum. If you want to check ranges of opcodes, etc.,
// write an #[inline] helper function which casts to u8s.
/// A script Opcode
#[derive(Clone, PartialEq, Eq, Debug)]
#[repr(u8)]
pub enum Opcode {
/// A script Opcode
#[derive(Clone, PartialEq, Eq, Debug)]
#[repr(u8)]
pub enum All {
/// Push an empty array onto the stack
OP_PUSHBYTES_0 = 0x0,
/// Push the next byte as an array onto the stack
@ -558,79 +553,80 @@ pub mod all {
OP_RETURN_254 = 0xfe,
/// Synonym for OP_RETURN
OP_RETURN_255 = 0xff,
}
}
impl Opcode {
/// Translates a u8 to an Opcode
impl All {
/// Translates a u8 to an opcode
#[inline]
pub fn from_u8(b: u8) -> Opcode {
pub fn from_u8(b: u8) -> All {
unsafe { transmute(b) }
}
/// Classifies an Opcode into a broad class
#[inline]
pub fn classify(&self) -> super::OpcodeClass {
pub fn classify(&self) -> OpcodeClass {
// 17 opcodes
if *self == OP_VERIF || *self == OP_VERNOTIF ||
*self == OP_CAT || *self == OP_SUBSTR ||
*self == OP_LEFT || *self == OP_RIGHT ||
*self == OP_INVERT || *self == OP_AND ||
*self == OP_OR || *self == OP_XOR ||
*self == OP_2MUL || *self == OP_2DIV ||
*self == OP_MUL || *self == OP_DIV || *self == OP_MOD ||
*self == OP_LSHIFT || *self == OP_RSHIFT {
super::IllegalOp
if *self == All::OP_VERIF || *self == All::OP_VERNOTIF ||
*self == All::OP_CAT || *self == All::OP_SUBSTR ||
*self == All::OP_LEFT || *self == All::OP_RIGHT ||
*self == All::OP_INVERT || *self == All::OP_AND ||
*self == All::OP_OR || *self == All::OP_XOR ||
*self == All::OP_2MUL || *self == All::OP_2DIV ||
*self == All::OP_MUL || *self == All::OP_DIV || *self == All::OP_MOD ||
*self == All::OP_LSHIFT || *self == All::OP_RSHIFT {
OpcodeClass::IllegalOp
// 11 opcodes
} else if *self == OP_NOP ||
(OP_NOP1 as u8 <= *self as u8 && *self as u8 <= OP_NOP10 as u8) {
super::NoOp
} else if *self == All::OP_NOP ||
(All::OP_NOP1 as u8 <= *self as u8 &&
*self as u8 <= All::OP_NOP10 as u8) {
OpcodeClass::NoOp
// 75 opcodes
} else if *self == OP_RESERVED || *self == OP_VER || *self == OP_RETURN ||
*self == OP_RESERVED1 || *self == OP_RESERVED2 ||
*self as u8 >= OP_RETURN_186 as u8 {
super::ReturnOp
} else if *self == All::OP_RESERVED || *self == All::OP_VER || *self == All::OP_RETURN ||
*self == All::OP_RESERVED1 || *self == All::OP_RESERVED2 ||
*self as u8 >= All::OP_RETURN_186 as u8 {
OpcodeClass::ReturnOp
// 1 opcode
} else if *self == OP_PUSHNUM_NEG1 {
super::PushNum(-1)
} else if *self == All::OP_PUSHNUM_NEG1 {
OpcodeClass::PushNum(-1)
// 16 opcodes
} else if OP_PUSHNUM_1 as u8 <= *self as u8 && *self as u8 <= OP_PUSHNUM_16 as u8 {
super::PushNum(1 + *self as isize - OP_PUSHNUM_1 as isize)
} else if All::OP_PUSHNUM_1 as u8 <= *self as u8 &&
*self as u8 <= All::OP_PUSHNUM_16 as u8 {
OpcodeClass::PushNum(1 + *self as isize - OP_PUSHNUM_1 as isize)
// 76 opcodes
} else if *self as u8 <= OP_PUSHBYTES_75 as u8 {
super::PushBytes(*self as usize)
} else if *self as u8 <= All::OP_PUSHBYTES_75 as u8 {
OpcodeClass::PushBytes(*self as usize)
// 60 opcodes
} else {
super::Ordinary(unsafe { transmute(*self) })
}
OpcodeClass::Ordinary(unsafe { transmute(*self) })
}
}
}
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Opcode {
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for All {
#[inline]
fn consensus_decode(d: &mut D) -> Result<Opcode, E> {
Ok(Opcode::from_u8(try!(d.read_u8())))
}
fn consensus_decode(d: &mut D) -> Result<All, E> {
Ok(All::from_u8(try!(d.read_u8())))
}
}
impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for Opcode {
impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for All {
#[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
s.emit_u8(*self as u8)
}
}
}
impl json::ToJson for Opcode {
impl json::ToJson for All {
fn to_json(&self) -> json::Json {
json::String(self.to_string())
}
}
/// Empty stack is also FALSE
pub static OP_FALSE: Opcode = OP_PUSHBYTES_0;
/// Number 1 is also TRUE
pub static OP_TRUE: Opcode = OP_PUSHNUM_1;
}
/// Empty stack is also FALSE
pub static OP_FALSE: All = OP_PUSHBYTES_0;
/// Number 1 is also TRUE
pub static OP_TRUE: All = OP_PUSHNUM_1;
/// Broad categories of opcodes with similar behavior
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum OpcodeClass {
@ -645,7 +641,7 @@ pub enum OpcodeClass {
/// Does nothing
NoOp,
/// Any opcode not covered above
Ordinary(Opcode)
Ordinary(Ordinary)
}
impl json::ToJson for OpcodeClass {
@ -659,8 +655,8 @@ macro_rules! ordinary_opcode {
#[repr(u8)]
#[doc(hidden)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Opcode {
$( $op = all::$op as u8 ),*
pub enum Ordinary {
$( $op = All::$op as u8 ),*
}
);
}

File diff suppressed because one or more lines are too long

View File

@ -33,7 +33,6 @@ use blockdata::block::Block;
use network::constants::Network;
use network::serialize::BitcoinHash;
use util::hash::{DumbHasher, Sha256dHash};
use util::thinvec::ThinVec;
/// The amount of validation to do when updating the UTXO set
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
@ -63,7 +62,7 @@ struct UtxoNode {
/// Blockheight at which this UTXO appeared in the blockchain
height: u32,
/// Vector of outputs; None indicates a nonexistent or already spent output
outputs: ThinVec<Option<TxOut>>
outputs: Box<[Option<TxOut>]>
}
impl_consensus_encoding!(UtxoNode, height, outputs);
@ -137,22 +136,22 @@ impl UtxoSet {
let txid = tx.bitcoin_hash();
// Locate node if it's already there
let new_node = unsafe {
let mut new_node = ThinVec::with_capacity(tx.output.len() as u32);
for (vout, txo) in tx.output.iter().enumerate() {
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
if txo.script_pubkey.is_provably_unspendable() {
new_node.init(vout as usize, None);
new_node.push(None);
self.n_utxos -= 1;
self.n_pruned += 1;
} else {
new_node.init(vout as usize, Some(txo.clone()));
new_node.push(Some(txo.clone()));
}
}
UtxoNode { outputs: new_node, height: height }
UtxoNode { outputs: new_node.into_boxed_slice(), height: height }
};
// Get the old value, if any (this is suprisingly possible, c.f. BIP30
// and the other comments in this file referring to it)
let ret = self.table.swap(txid, new_node);
let ret = self.table.swap(txid, new_node.into_boxed_slice());
if ret.is_none() {
self.n_utxos += tx.output.len() as u64;
}
@ -354,26 +353,17 @@ impl UtxoSet {
let new_node =
match self.table.pop(&txid) {
Some(mut node) => {
let old_len = node.outputs.len() as u32;
if old_len < n + 1 {
unsafe {
node.outputs.reserve(n + 1);
for i in range(old_len, n + 1) {
node.outputs.init(i as usize, None);
}
}
}
unsafe { *node.outputs.get_mut(n as usize) = Some(txo); }
node.outputs[n as usize] = Some(txo);
node
}
None => {
unsafe {
let mut thinvec = ThinVec::with_capacity(n + 1);
for i in range(0, n) {
thinvec.init(i as usize, None);
let mut thinvec = Vec::with_capacity(n + 1);
for _ in 0..n {
thinvec.push(None);
}
thinvec.init(n as usize, Some(txo));
UtxoNode { outputs: thinvec, height: height }
thinvec.push(Some(txo));
UtxoNode { outputs: thinvec.into_boxed_slice(), height: height }
}
}
};

View File

@ -131,11 +131,53 @@ macro_rules! impl_array_newtype {
}
}
impl Index<usize, $ty> for $thing {
impl ::std::ops::Index<usize> for $thing {
type Output = $ty;
#[inline]
fn index<'a>(&'a self, idx: &usize) -> &'a $ty {
let &$thing(ref data) = self;
&data[*idx]
fn index(&self, index: usize) -> &$ty {
let &$thing(ref dat) = self;
&dat[index]
}
}
impl ::std::ops::Index<::std::ops::Range<usize>> for $thing {
type Output = [$ty];
#[inline]
fn index(&self, index: ::std::ops::Range<usize>) -> &[$ty] {
let &$thing(ref dat) = self;
&dat[index.start..index.end]
}
}
impl ::std::ops::Index<::std::ops::RangeTo<usize>> for $thing {
type Output = [$ty];
#[inline]
fn index(&self, index: ::std::ops::RangeTo<usize>) -> &[$ty] {
let &$thing(ref dat) = self;
&dat[..index.end]
}
}
impl ::std::ops::Index<::std::ops::RangeFrom<usize>> for $thing {
type Output = [$ty];
#[inline]
fn index(&self, index: ::std::ops::RangeFrom<usize>) -> &[$ty] {
let &$thing(ref dat) = self;
&dat[index.start..]
}
}
impl ::std::ops::Index<::std::ops::RangeFull> for $thing {
type Output = [$ty];
#[inline]
fn index(&self, _: ::std::ops::RangeFull) -> &[$ty] {
let &$thing(ref dat) = self;
&dat[..]
}
}
@ -160,7 +202,7 @@ macro_rules! impl_array_newtype {
macro_rules! impl_array_newtype_encodable {
($thing:ident, $ty:ty, $len:expr) => {
impl<D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for $thing {
fn decode(d: &mut D) -> ::std::prelude::Result<$thing, E> {
fn decode(d: &mut D) -> Result<$thing, E> {
use serialize::Decodable;
::assert_type_is_copy::<$ty>();
@ -172,7 +214,7 @@ macro_rules! impl_array_newtype_encodable {
unsafe {
use std::mem;
let mut ret: [$ty; $len] = mem::uninitialized();
for i in range(0, len) {
for i in 0..len {
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
}
Ok($thing(ret))
@ -183,7 +225,7 @@ macro_rules! impl_array_newtype_encodable {
}
impl<E: ::serialize::Encoder<S>, S> ::serialize::Encodable<E, S> for $thing {
fn encode(&self, e: &mut E) -> ::std::prelude::Result<(), S> {
fn encode(&self, e: &mut E) -> Result<(), S> {
self.as_slice().encode(e)
}
}

View File

@ -28,6 +28,7 @@
#![crate_type = "rlib"]
// Experimental features we need
#![feature(custom_derive, plugin)]
#![feature(overloaded_calls)]
#![feature(unsafe_destructor)]
#![feature(unboxed_closure_sugar)]
@ -49,6 +50,8 @@ extern crate core;
extern crate num_cpus;
extern crate rand;
extern crate rustc_serialize as serialize;
extern crate serde;
#[plugin(serde_macros)]
extern crate test;
extern crate time;

View File

@ -34,7 +34,6 @@ use std::default::Default;
use std::hash::{Hash, Hasher};
use std::u32;
use util::thinvec::ThinVec;
use util::hash::Sha256dHash;
use network::serialize::{SimpleDecoder, SimpleEncoder};
@ -230,25 +229,20 @@ impl<D:SimpleDecoder<E>, E, T:ConsensusDecodable<D, E>> ConsensusDecodable<D, E>
}
}
impl<S:SimpleEncoder<E>, E, T:ConsensusEncodable<S, E>> ConsensusEncodable<S, E> for ThinVec<T> {
impl<S:SimpleEncoder<E>, E, T:ConsensusEncodable<S, E>> ConsensusEncodable<S, E> for Box<[T]> {
#[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), E> { self.as_slice().consensus_encode(s) }
fn consensus_encode(&self, s: &mut S) -> Result<(), E> { (&self[..]).consensus_encode(s) }
}
impl<D:SimpleDecoder<E>, E, T:ConsensusDecodable<D, E>> ConsensusDecodable<D, E> for ThinVec<T> {
impl<D:SimpleDecoder<E>, E, T:ConsensusDecodable<D, E>> ConsensusDecodable<D, E> for Box<[T]> {
#[inline]
fn consensus_decode(d: &mut D) -> Result<ThinVec<T>, E> {
fn consensus_decode(d: &mut D) -> Result<Box<[T]>, E> {
let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d));
if len > u32::MAX as u64 {
return Err(d.error("ThinVec length out of range!"));
}
unsafe {
let mut ret = ThinVec::with_capacity(len as u32);
// Huge danger: if this fails, the remaining uninitialized part of the ThinVec
// will be freed. This is ok, but only because the memory is u8, which has no
// destructor...and assuming there are no trap representations...very fragile.
for i in range(0, len as usize) { ret.init(i, try!(ConsensusDecodable::consensus_decode(d))); }
Ok(ret)
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())
}
}
}

View File

@ -18,7 +18,6 @@ use byteorder::{ByteOrder, LittleEndian};
use std::string;
use util::thinvec::ThinVec;
use util::hash::Sha256dHash;
/// An error that might occur during base58 decoding
@ -174,24 +173,12 @@ impl ToBase58 for Vec<u8> {
fn to_base58(&self) -> String { base58_encode_slice(self.as_slice()) }
}
impl ToBase58 for ThinVec<u8> {
fn base58_layout(&self) -> Vec<u8> { self.as_slice().to_vec() }
fn to_base58(&self) -> String { base58_encode_slice(self.as_slice()) }
}
impl FromBase58 for Vec<u8> {
fn from_base58_layout(data: Vec<u8>) -> Result<Vec<u8>, Base58Error> {
Ok(data)
}
}
impl FromBase58 for ThinVec<u8> {
fn from_base58_layout(data: Vec<u8>) -> Result<ThinVec<u8>, Base58Error> {
Ok(ThinVec::from_vec(data))
}
}
#[cfg(test)]
mod tests {
use serialize::hex::FromHex;

View File

@ -19,7 +19,6 @@
use std::io::{Error, Result, ErrorKind};
use blockdata::opcodes;
use blockdata::opcodes::all::Opcode;
use util::iter::Pairable;
/// Convert a hexadecimal-encoded string to its corresponding bytes

View File

@ -22,7 +22,6 @@ pub mod hash;
pub mod iter;
pub mod misc;
pub mod patricia_tree;
pub mod thinvec;
pub mod uint;
/// A trait which allows numbers to act as fixed-size bit arrays

View File

@ -1,309 +0,0 @@
// 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/>.
//
//! # Thin vectors
//!
//! A vector type designed to take as little memory as possible by limiting
//! its size to 4bn elements and not distinguishing between size and capacity.
//! It is very easy to read uninitialized memory: make sure you assign all
//! values after calling `reserve` or `with_capacity`.
//!
use alloc::heap::{allocate, reallocate, deallocate};
use std::raw;
use std::slice::{Iter, IterMut};
use std::{fmt, mem, ptr};
use std::u32;
/// A vector type designed to take very little memory
pub struct ThinVec<T> {
ptr: *mut T,
cap: u32 // capacity and length are the same
}
impl<T> ThinVec<T> {
/// Constructor
#[inline]
pub fn new() -> ThinVec<T> { ThinVec { ptr: RawPtr::null(), cap: 0 } }
/// Constructor with predetermined capacity
#[inline]
pub unsafe fn with_capacity(capacity: u32) -> ThinVec<T> {
if mem::size_of::<T>() == 0 {
ThinVec { ptr: RawPtr::null(), cap: capacity }
} else if capacity == 0 {
ThinVec::new()
} else {
let size = (capacity as usize).checked_mul(&mem::size_of::<T>())
.expect("ThinVec::reserve: capacity overflow");
let ptr = allocate(size, mem::min_align_of::<T>());
ThinVec { ptr: ptr as *mut T, cap: capacity }
}
}
/// Constructor from an ordinary vector
#[inline]
pub fn from_vec(mut v: Vec<T>) -> ThinVec<T> {
v.shrink_to_fit();
assert!(v.len() <= u32::MAX as usize);
let ret = ThinVec { ptr: v.as_mut_ptr(), cap: v.len() as u32 };
unsafe { mem::forget(v); }
ret
}
/// Iterator over elements of the vector
#[inline]
pub fn iter<'a>(&'a self) -> Iter<'a, T> {
self.as_slice().iter()
}
/// Mutable iterator over elements of the vector
#[inline]
pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
self.as_mut_slice().iter_mut()
}
/// Get vector as mutable slice
#[inline]
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
unsafe { mem::transmute(raw::Slice { data: self.ptr as *const T, len: self.cap as usize }) }
}
/// Accessor
#[inline]
pub unsafe fn get<'a>(&'a self, index: usize) -> &'a T {
&self.as_slice()[index]
}
/// Mutable accessor NOT for first use
#[inline]
pub unsafe fn get_mut<'a>(&'a mut self, index: usize) -> &'a mut T {
&mut self.as_mut_slice()[index]
}
/// Mutable accessor for first use
#[inline]
pub unsafe fn init<'a>(&'a mut self, index: usize, value: T) {
ptr::write(&mut *self.ptr.offset(index as isize), value);
}
/// Returns a slice starting from `index`
#[inline]
pub fn slice_from<'a>(&'a self, index: usize) -> &'a [T] {
self.as_slice().slice_from(index)
}
/// Returns a slice ending just before `index`
#[inline]
pub fn slice_to<'a>(&'a self, index: usize) -> &'a [T] {
self.as_slice().slice_to(index)
}
/// Returns a slice starting from `s` ending just before `e`
#[inline]
pub fn slice<'a>(&'a self, s: usize, e: usize) -> &'a [T] {
self.as_slice().slice(s, e)
}
/// Push: always reallocates, try not to use this
#[inline]
pub fn push(&mut self, value: T) {
self.cap = self.cap.checked_add(&1).expect("ThinVec::push: length overflow");
if mem::size_of::<T>() == 0 {
unsafe { mem::forget(value); }
} else {
let old_size = (self.cap - 1) as usize * mem::size_of::<T>();
let new_size = self.cap as usize * mem::size_of::<T>();
if new_size < old_size { panic!("ThinVec::push: cap overflow") }
unsafe {
self.ptr =
if old_size == 0 {
allocate(new_size, mem::min_align_of::<T>()) as *mut T
} else {
reallocate(self.ptr as *mut u8, new_size,
mem::min_align_of::<T>(), self.cap as usize) as *mut T
};
ptr::write(&mut *self.ptr.offset((self.cap - 1) as isize), value);
}
}
}
/// Set the length of the vector to the minimum of the current capacity and new capacity
pub unsafe fn reserve(&mut self, new_cap: u32) {
if new_cap > self.cap {
let new_size = (new_cap as usize).checked_mul(&mem::size_of::<T>())
.expect("ThinVec::reserve: capacity overflow");
self.ptr =
if self.cap == 0 {
allocate(new_size, mem::min_align_of::<T>()) as *mut T
} else {
reallocate(self.ptr as *mut u8, new_size,
mem::min_align_of::<T>(), self.cap as usize) as *mut T
};
self.cap = new_cap;
}
}
/// Increase the length of the vector
pub unsafe fn reserve_additional(&mut self, extra: u32) {
let new_cap = self.cap.checked_add(&extra).expect("ThinVec::reserve_additional: length overflow");
self.reserve(new_cap);
}
}
impl<T:Clone> ThinVec<T> {
/// Push an entire slice onto the ThinVec
#[inline]
pub fn push_all(&mut self, other: &[T]) {
let old_cap = self.cap as usize;
unsafe { self.reserve_additional(other.len() as u32); }
// Copied from vec.rs, which claims this will be optimized to a memcpy
// if T is Copy
for i in range(0, other.len()) {
unsafe {
ptr::write(self.as_mut_slice().unsafe_mut(old_cap + i),
other.unsafe_get(i).clone());
}
}
}
}
impl<T:Clone> CloneableVector<T> for ThinVec<T> {
fn to_vec(&self) -> Vec<T> {
self.as_slice().to_vec()
}
fn into_vec(self) -> Vec<T> {
unsafe { Vec::from_raw_parts(self.cap as usize, self.cap as usize, self.ptr) }
}
}
impl<T> Slice<T> for ThinVec<T> {
#[inline]
fn as_slice<'a>(&'a self) -> &'a [T] {
unsafe { mem::transmute(raw::Slice { data: self.ptr as *const T, len: self.cap as usize }) }
}
}
impl<T:Clone> Clone for ThinVec<T> {
fn clone(&self) -> ThinVec<T> {
unsafe {
let mut ret = ThinVec::with_capacity(self.len() as u32);
// Copied from vec.rs, which claims this will be optimized to a memcpy
// if T is Copy
for i in range(0, self.len()) {
ptr::write(ret.as_mut_slice().unsafe_mut(i),
self.as_slice().unsafe_get(i).clone());
}
ret
}
}
// TODO: clone_from
}
impl<T> FromIterator<T> for ThinVec<T> {
#[inline]
fn from_iter<I: Iterator<T>>(iter: I) -> ThinVec<T> {
let (lower, _) = iter.size_hint();
assert!(lower <= u32::MAX as usize);
unsafe {
let mut vector = ThinVec::with_capacity(lower as u32);
for (n, elem) in iter.enumerate() {
if n < lower {
vector.init(n, elem);
} else {
vector.push(elem);
}
}
vector
}
}
}
impl<T> Extendable<T> for ThinVec<T> {
#[inline]
fn extend<I: Iterator<T>>(&mut self, iter: I) {
let old_cap = self.cap;
let (lower, _) = iter.size_hint();
unsafe { self.reserve_additional(lower as u32); }
for (n, elem) in iter.enumerate() {
if n < lower {
unsafe { self.init(old_cap as usize + n, elem) };
} else {
self.push(elem);
}
}
}
}
impl<T> Collection for ThinVec<T> {
#[inline]
fn len(&self) -> usize { self.cap as usize }
}
impl<T:fmt::Debug> fmt::Debug for ThinVec<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.as_slice().fmt(f)
}
}
impl<T: PartialEq> PartialEq for ThinVec<T> {
#[inline]
fn eq(&self, other: &ThinVec<T>) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: Eq> Eq for ThinVec<T> {}
#[unsafe_destructor]
impl<T> Drop for ThinVec<T> {
fn drop(&mut self) {
if self.cap != 0 {
unsafe {
for x in self.as_mut_slice().iter() {
ptr::read(x);
}
if mem::size_of::<T>() != 0 {
deallocate(self.ptr as *mut u8,
self.cap as usize * mem::size_of::<T>(),
mem::min_align_of::<T>());
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::ThinVec;
#[test]
fn simple_destructor_thinvec_test() {
let cap = 2;
unsafe {
let mut thinvec = ThinVec::with_capacity(cap);
for i in range(0, cap) {
thinvec.init(i, Some(Box::new(i)));
}
for i in range(0, cap) {
assert_eq!(thinvec.get_mut(i).take(), Some(Box::new(i)));
assert_eq!(thinvec.get_mut(i).take(), None);
}
}
}
}

View File

@ -41,9 +41,9 @@ macro_rules! construct_uint {
/// Return the least number of bits needed to represent the number
#[inline]
pub fn bits(&self) -> uzise {
pub fn bits(&self) -> usize {
let &$name(ref arr) = self;
for i in range(1, $n_words) {
for i in 1..$n_words {
if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as usize; }
}
0x40 - arr[0].leading_zeros()
@ -54,7 +54,7 @@ macro_rules! construct_uint {
let &$name(ref arr) = self;
let mut carry = [0u64; $n_words];
let mut ret = [0u64; $n_words];
for i in range(0, $n_words) {
for i in 0..$n_words {
let upper = other as u64 * (arr[i] >> 32);
let lower = other as u64 * (arr[i] & 0xFFFFFFFF);
if i < 3 {
@ -66,7 +66,7 @@ macro_rules! construct_uint {
}
}
impl FromPrimitive for $name {
impl ::std::num::FromPrimitive for $name {
#[inline]
fn from_u64(init: u64) -> Option<$name> {
let mut ret = [0; $n_words];
@ -76,29 +76,28 @@ macro_rules! construct_uint {
#[inline]
fn from_i64(init: i64) -> Option<$name> {
FromPrimitive::from_u64(init as u64)
::std::num::FromPrimitive::from_u64(init as u64)
}
}
impl Zero for $name {
impl ::std::num::Zero for $name {
fn zero() -> $name { $name([0; $n_words]) }
fn is_zero(&self) -> bool { *self == Zero::zero() }
}
impl One for $name {
impl ::std::num::One for $name {
fn one() -> $name {
$name({ let mut ret = [0; $n_words]; ret[0] = 1; ret })
}
}
impl Add<$name,$name> for $name {
impl ::std::ops::Add<$name,$name> for $name {
fn add(&self, other: &$name) -> $name {
let &$name(ref me) = self;
let &$name(ref you) = other;
let mut ret = [0u64; $n_words];
let mut carry = [0u64; $n_words];
let mut b_carry = false;
for i in range(0, $n_words) {
for i in 0..$n_words {
ret[i] = me[i] + you[i];
if i < $n_words - 1 && ret[i] < me[i] {
carry[i + 1] = 1;
@ -109,25 +108,25 @@ macro_rules! construct_uint {
}
}
impl Sub<$name,$name> for $name {
impl ::std::ops::Sub<$name,$name> for $name {
#[inline]
fn sub(&self, other: &$name) -> $name {
*self + !*other + One::one()
}
}
impl Mul<$name,$name> for $name {
impl ::std::ops::Mul<$name,$name> for $name {
fn mul(&self, other: &$name) -> $name {
let mut me = *self;
// TODO: be more efficient about this
for i in range(0, 2 * $n_words) {
for i in 0..(2 * $n_words) {
me = me + me.mul_u32((other >> (32 * i)).low_u32()) << (32 * i);
}
me
}
}
impl Div<$name,$name> for $name {
impl ::std::ops::Div<$name,$name> for $name {
fn div(&self, other: &$name) -> $name {
let mut sub_copy = *self;
let mut shift_copy = *other;
@ -177,7 +176,7 @@ macro_rules! construct_uint {
fn mask(&self, n: usize) -> $name {
let &$name(ref arr) = self;
let mut ret = [0; $n_words];
for i in range(0, $n_words) {
for i in 0..$n_words {
if n >= 0x40 * (i + 1) {
ret[i] = arr[i];
} else {
@ -191,71 +190,71 @@ macro_rules! construct_uint {
#[inline]
fn trailing_zeros(&self) -> usize {
let &$name(ref arr) = self;
for i in range(0, $n_words - 1) {
for i in 0..($n_words - 1) {
if arr[i] > 0 { return (0x40 * i) + arr[i].trailing_zeros(); }
}
(0x40 * ($n_words - 1)) + arr[3].trailing_zeros()
}
}
impl BitAnd<$name,$name> for $name {
impl ::std::ops::BitAnd<$name,$name> for $name {
#[inline]
fn bitand(&self, other: &$name) -> $name {
let &$name(ref arr1) = self;
let &$name(ref arr2) = other;
let mut ret = [0u64; $n_words];
for i in range(0, $n_words) {
for i in 0..$n_words {
ret[i] = arr1[i] & arr2[i];
}
$name(ret)
}
}
impl BitXor<$name,$name> for $name {
impl ::std::ops::BitXor<$name,$name> for $name {
#[inline]
fn bitxor(&self, other: &$name) -> $name {
let &$name(ref arr1) = self;
let &$name(ref arr2) = other;
let mut ret = [0u64; $n_words];
for i in range(0, $n_words) {
for i in 0..$n_words {
ret[i] = arr1[i] ^ arr2[i];
}
$name(ret)
}
}
impl BitOr<$name,$name> for $name {
impl ::std::ops::BitOr<$name,$name> for $name {
#[inline]
fn bitor(&self, other: &$name) -> $name {
let &$name(ref arr1) = self;
let &$name(ref arr2) = other;
let mut ret = [0u64; $n_words];
for i in range(0, $n_words) {
for i in 0..$n_words {
ret[i] = arr1[i] | arr2[i];
}
$name(ret)
}
}
impl Not<$name> for $name {
impl ::std::ops::Not<$name> for $name {
#[inline]
fn not(&self) -> $name {
let &$name(ref arr) = self;
let mut ret = [0u64; $n_words];
for i in range(0, $n_words) {
for i in 0..$n_words {
ret[i] = !arr[i];
}
$name(ret)
}
}
impl Shl<usize, $name> for $name {
impl ::std::ops::Shl<usize, $name> for $name {
fn shl(&self, shift: &usize) -> $name {
let &$name(ref original) = self;
let mut ret = [0u64; $n_words];
let word_shift = *shift / 64;
let bit_shift = *shift % 64;
for i in range(0, $n_words) {
for i in 0..$n_words {
// Shift
if bit_shift < 64 && i + word_shift < $n_words {
ret[i + word_shift] += original[i] << bit_shift;
@ -269,14 +268,14 @@ macro_rules! construct_uint {
}
}
impl Shr<usize, $name> for $name {
impl ::std::ops::Shr<usize, $name> for $name {
#[allow(unsigned_negate)]
fn shr(&self, shift: &usize) -> $name {
let &$name(ref original) = self;
let mut ret = [0u64; $n_words];
let word_shift = *shift / 64;
let bit_shift = *shift % 64;
for i in range(0, $n_words) {
for i in 0..$n_words {
// Shift
if bit_shift < 64 && i - word_shift < $n_words {
ret[i - word_shift] += original[i] >> bit_shift;
@ -290,20 +289,20 @@ macro_rules! construct_uint {
}
}
impl Ord for $name {
fn cmp(&self, other: &$name) -> Ordering {
impl ::std::cmp::Ord for $name {
fn cmp(&self, other: &$name) -> ::std::cmp::Ordering {
let &$name(ref me) = self;
let &$name(ref you) = other;
for i in range(0, $n_words) {
if me[$n_words - 1 - i] < you[$n_words - 1 - i] { return Less; }
if me[$n_words - 1 - i] > you[$n_words - 1 - i] { return Greater; }
for i in 0..$n_words {
if me[$n_words - 1 - i] < you[$n_words - 1 - i] { return ::std::cmp::Ordering::Less; }
if me[$n_words - 1 - i] > you[$n_words - 1 - i] { return ::std::cmp::Ordering::Greater; }
}
return Equal;
return ::std::cmp::Ordering::Equal;
}
}
impl PartialOrd for $name {
fn partial_cmp(&self, other: &$name) -> Option<Ordering> {
impl ::std::cmp::PartialOrd for $name {
fn partial_cmp(&self, other: &$name) -> Option<::std::cmp::Ordering> {
Some(self.cmp(other))
}
}

View File

@ -21,7 +21,7 @@ use crypto::digest::Digest;
use crypto::sha2::Sha256;
use blockdata::script::Script;
use blockdata::opcodes::all;
use blockdata::opcodes;
use network::constants::Network::{self, Bitcoin, BitcoinTestnet};
use util::hash::Ripemd160Hash;
use util::base58::Base58Error::{self, InvalidLength, InvalidVersion};
@ -61,11 +61,11 @@ impl Address {
#[inline]
pub fn script_pubkey(&self) -> Script {
let mut script = Script::new();
script.push_opcode(all::OP_DUP);
script.push_opcode(all::OP_HASH160);
script.push_opcode(opcodes::All::OP_DUP);
script.push_opcode(opcodes::All::OP_HASH160);
script.push_slice(self.hash.as_slice());
script.push_opcode(all::OP_EQUALVERIFY);
script.push_opcode(all::OP_CHECKSIG);
script.push_opcode(opcodes::All::OP_EQUALVERIFY);
script.push_opcode(opcodes::All::OP_CHECKSIG);
script
}
}

View File

@ -86,7 +86,7 @@ impl AddressIndex {
vout: idx,
height: height,
txo: txo.clone(),
kind: Unknown
kind: WalletTxOutType::Unknown
};
ret.tentative_index.find_or_insert(txo.script_pubkey.clone(), vec![]).push(new);
}

View File

@ -17,7 +17,7 @@
//! at https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
use std::default::Default;
use serialize::{Decoder, Encoder};
use serde;
use byteorder::{ByteOrder, BigEndian};
use crypto::digest::Digest;
@ -51,7 +51,7 @@ impl Default for Fingerprint {
}
/// Extended private key
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct ExtendedPrivKey {
/// The network this key is to be used on
pub network: Network,
@ -68,7 +68,7 @@ pub struct ExtendedPrivKey {
}
/// Extended public key
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct ExtendedPubKey {
/// The network this key is to be used on
pub network: Network,
@ -93,18 +93,20 @@ pub enum ChildNumber {
Normal(u32),
}
impl<S: Encoder<E>, E> Encodable<S, E> for ChildNumber {
fn encode(&self, s: &mut S) -> Result<(), E> {
impl serde::Serialize for ChildNumber {
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
where S: serde::Serializer {
match *self {
ChildNumber::Hardened(n) => (n + (1 << 31)).encode(s),
ChildNumber::Normal(n) => n.encode(s)
ChildNumber::Hardened(n) => (n + (1 << 31)).serialize(s),
ChildNumber::Normal(n) => n.serialize(s)
}
}
}
impl<D: Decoder<E>, E> RustcDecodable<D, E> for ChildNumber {
fn decode(d: &mut D) -> Result<ChildNumber, E> {
let n: u32 = try!(RustcDecodable::decode(d));
impl serde::Deserialize for ChildNumber {
fn deserialize<D>(&self, d: &mut D) -> Result<ChildNumber, D::Error>
where D: serde::Deserializer {
let n: u32 = try!(serde::Deserialize::decode(d));
if n < (1 << 31) {
Ok(ChildNumber::Normal(n))
} else {
@ -139,7 +141,7 @@ impl ExtendedPrivKey {
depth: 0,
parent_fingerprint: Default::default(),
child_number: ChildNumber::Normal(0),
secret_key: try!(SecretKey::from_slice(result.slice_to(32)).map_err(EcdsaError)),
secret_key: try!(SecretKey::from_slice(result.slice_to(32)).map_err(Error::EcdsaError)),
chain_code: ChainCode::from_slice(result.slice_from(32))
})
}
@ -160,7 +162,7 @@ impl ExtendedPrivKey {
let mut hmac = Hmac::new(Sha512::new(), self.chain_code.as_slice());
match i {
ChildNumber::Normal(n) => {
if n >= (1 << 31) { return Err(InvalidChildNumber(i)) }
if n >= (1 << 31) { return Err(Error::InvalidChildNumber(i)) }
// Non-hardened key: compute public data and use that
secp256k1::init();
// Note the unwrap: this is fine, we checked the SK when we created it
@ -168,7 +170,7 @@ impl ExtendedPrivKey {
hmac.write_u32::<BigEndian>(n);
}
ChildNumber::Hardened(n) => {
if n >= (1 << 31) { return Err(InvalidChildNumber(i)) }
if n >= (1 << 31) { return Err(Error::InvalidChildNumber(i)) }
// Hardened key: use only secret data to prevent public derivation
hmac.input([0]);
hmac.input(self.secret_key.as_slice());
@ -176,8 +178,8 @@ impl ExtendedPrivKey {
}
}
hmac.raw_result(result.as_mut_slice());
let mut sk = try!(SecretKey::from_slice(result.slice_to(32)).map_err(EcdsaError));
try!(sk.add_assign(&self.secret_key).map_err(EcdsaError));
let mut sk = try!(SecretKey::from_slice(result.slice_to(32)).map_err(Error::EcdsaError));
try!(sk.add_assign(&self.secret_key).map_err(Error::EcdsaError));
Ok(ExtendedPrivKey {
network: self.network,
@ -232,9 +234,9 @@ impl ExtendedPubKey {
match i {
ChildNumber::Hardened(n) => {
if n >= (1 << 31) {
Err(InvalidChildNumber(i))
Err(Error::InvalidChildNumber(i))
} else {
Err(CannotDeriveFromHardenedKey)
Err(Error::CannotDeriveFromHardenedKey)
}
}
ChildNumber::Normal(n) => {
@ -245,9 +247,9 @@ impl ExtendedPubKey {
let mut result = [0; 64];
hmac.raw_result(result.as_mut_slice());
let sk = try!(SecretKey::from_slice(result.slice_to(32)).map_err(EcdsaError));
let sk = try!(SecretKey::from_slice(result.slice_to(32)).map_err(Error::EcdsaError));
let mut pk = self.public_key.clone();
try!(pk.add_exp_assign(&sk).map_err(EcdsaError));
try!(pk.add_exp_assign(&sk).map_err(Error::EcdsaError));
Ok(ExtendedPubKey {
network: self.network,

View File

@ -18,7 +18,7 @@
use std::collections::HashMap;
use std::default::Default;
use serialize::{Decoder, Encoder};
use serde;
use secp256k1::key::PublicKey;
@ -54,9 +54,8 @@ pub enum AccountChain {
}
/// An account
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct Account {
name: String,
internal_path: Vec<ChildNumber>,
internal_used: Vec<ChildNumber>,
internal_next: u32,
@ -68,7 +67,6 @@ pub struct Account {
impl Default for Account {
fn default() -> Account {
Account {
name: String::new(),
internal_path: vec![Hardened(0), Normal(1)],
internal_used: vec![],
internal_next: 0,
@ -87,39 +85,23 @@ pub struct Wallet {
index: Option<AddressIndex>
}
impl<S: Encoder<E>, E> Encodable<S, E> for Wallet {
fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_struct("wallet", 2, |s| {
try!(s.emit_struct_field("master", 0, |s| self.master.encode(s)));
s.emit_struct_field("accounts", 1,
|s| s.emit_seq(self.accounts.len(), |s| {
for (_, account) in self.accounts.iter() {
try!(account.encode(s));
}
Ok(())
}))
})
impl serde::Serialize for Wallet {
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
where S: serde::Serializer {
let len = self.accounts.len();
try!(self.master.serialize(s));
self.accounts.serialize(s)
}
}
impl<D: Decoder<E>, E> Decodable<D, E> for Wallet {
fn decode(d: &mut D) -> Result<Wallet, E> {
d.read_struct("wallet", 2, |d| {
Ok(Wallet {
master: try!(d.read_struct_field("master", 0, Decodable::decode)),
accounts: try!(d.read_struct_field("accounts", 1, |d| {
d.read_seq(|d, len| {
let mut ret = HashMap::new();
for i in range(0, len) {
let accnt: Account = try!(d.read_seq_elt(i, Decodable::decode));
ret.insert(accnt.name.clone(), accnt);
}
Ok(ret)
})
})),
impl serde::Deserialize for Wallet {
fn deserialize<D>(&self, d: &mut D) -> Result<Wallet, D::Error>
where D: serde::Deserializer {
Wallet {
master: try!(serde::Deserialize::deserialize(d)),
accounts: try!(serde::Deserialize::deserialize(d)),
index: None
})
})
}
}
}
@ -164,8 +146,7 @@ impl Wallet {
}
let idx = self.accounts.len() as u32;
self.accounts.insert(name.clone(), Account {
name: name,
self.accounts.insert(name, Account {
internal_path: vec![Hardened(idx), Normal(1)],
internal_used: vec![],
internal_next: 0,