Drop ThinVec, many other changes toward updating for librustc
This commit is contained in:
parent
7a2cfe95e7
commit
160f2f9ea6
|
@ -17,5 +17,6 @@ num_cpus = "*"
|
|||
rand = "*"
|
||||
rust-crypto = "*"
|
||||
rustc-serialize = "*"
|
||||
serde = "*"
|
||||
time = "*"
|
||||
|
||||
|
|
|
@ -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
|
@ -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 }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -131,13 +131,55 @@ macro_rules! impl_array_newtype {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<usize, $ty> for $thing {
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, idx: &usize) -> &'a $ty {
|
||||
let &$thing(ref data) = self;
|
||||
&data[*idx]
|
||||
}
|
||||
}
|
||||
impl ::std::ops::Index<usize> for $thing {
|
||||
type Output = $ty;
|
||||
|
||||
#[inline]
|
||||
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[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for $thing {
|
||||
#[inline]
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue