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 = "*"
|
rand = "*"
|
||||||
rust-crypto = "*"
|
rust-crypto = "*"
|
||||||
rustc-serialize = "*"
|
rustc-serialize = "*"
|
||||||
|
serde = "*"
|
||||||
time = "*"
|
time = "*"
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,6 @@
|
||||||
|
|
||||||
use serialize::json;
|
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
|
// Heavy stick to translate between opcode types
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
|
|
||||||
|
@ -40,7 +35,7 @@ pub mod all {
|
||||||
/// A script Opcode
|
/// A script Opcode
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Opcode {
|
pub enum All {
|
||||||
/// Push an empty array onto the stack
|
/// Push an empty array onto the stack
|
||||||
OP_PUSHBYTES_0 = 0x0,
|
OP_PUSHBYTES_0 = 0x0,
|
||||||
/// Push the next byte as an array onto the stack
|
/// Push the next byte as an array onto the stack
|
||||||
|
@ -560,76 +555,77 @@ pub mod all {
|
||||||
OP_RETURN_255 = 0xff,
|
OP_RETURN_255 = 0xff,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Opcode {
|
impl All {
|
||||||
/// Translates a u8 to an Opcode
|
/// Translates a u8 to an opcode
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_u8(b: u8) -> Opcode {
|
pub fn from_u8(b: u8) -> All {
|
||||||
unsafe { transmute(b) }
|
unsafe { transmute(b) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Classifies an Opcode into a broad class
|
/// Classifies an Opcode into a broad class
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn classify(&self) -> super::OpcodeClass {
|
pub fn classify(&self) -> OpcodeClass {
|
||||||
// 17 opcodes
|
// 17 opcodes
|
||||||
if *self == OP_VERIF || *self == OP_VERNOTIF ||
|
if *self == All::OP_VERIF || *self == All::OP_VERNOTIF ||
|
||||||
*self == OP_CAT || *self == OP_SUBSTR ||
|
*self == All::OP_CAT || *self == All::OP_SUBSTR ||
|
||||||
*self == OP_LEFT || *self == OP_RIGHT ||
|
*self == All::OP_LEFT || *self == All::OP_RIGHT ||
|
||||||
*self == OP_INVERT || *self == OP_AND ||
|
*self == All::OP_INVERT || *self == All::OP_AND ||
|
||||||
*self == OP_OR || *self == OP_XOR ||
|
*self == All::OP_OR || *self == All::OP_XOR ||
|
||||||
*self == OP_2MUL || *self == OP_2DIV ||
|
*self == All::OP_2MUL || *self == All::OP_2DIV ||
|
||||||
*self == OP_MUL || *self == OP_DIV || *self == OP_MOD ||
|
*self == All::OP_MUL || *self == All::OP_DIV || *self == All::OP_MOD ||
|
||||||
*self == OP_LSHIFT || *self == OP_RSHIFT {
|
*self == All::OP_LSHIFT || *self == All::OP_RSHIFT {
|
||||||
super::IllegalOp
|
OpcodeClass::IllegalOp
|
||||||
// 11 opcodes
|
// 11 opcodes
|
||||||
} else if *self == OP_NOP ||
|
} else if *self == All::OP_NOP ||
|
||||||
(OP_NOP1 as u8 <= *self as u8 && *self as u8 <= OP_NOP10 as u8) {
|
(All::OP_NOP1 as u8 <= *self as u8 &&
|
||||||
super::NoOp
|
*self as u8 <= All::OP_NOP10 as u8) {
|
||||||
|
OpcodeClass::NoOp
|
||||||
// 75 opcodes
|
// 75 opcodes
|
||||||
} else if *self == OP_RESERVED || *self == OP_VER || *self == OP_RETURN ||
|
} else if *self == All::OP_RESERVED || *self == All::OP_VER || *self == All::OP_RETURN ||
|
||||||
*self == OP_RESERVED1 || *self == OP_RESERVED2 ||
|
*self == All::OP_RESERVED1 || *self == All::OP_RESERVED2 ||
|
||||||
*self as u8 >= OP_RETURN_186 as u8 {
|
*self as u8 >= All::OP_RETURN_186 as u8 {
|
||||||
super::ReturnOp
|
OpcodeClass::ReturnOp
|
||||||
// 1 opcode
|
// 1 opcode
|
||||||
} else if *self == OP_PUSHNUM_NEG1 {
|
} else if *self == All::OP_PUSHNUM_NEG1 {
|
||||||
super::PushNum(-1)
|
OpcodeClass::PushNum(-1)
|
||||||
// 16 opcodes
|
// 16 opcodes
|
||||||
} else if OP_PUSHNUM_1 as u8 <= *self as u8 && *self as u8 <= OP_PUSHNUM_16 as u8 {
|
} else if All::OP_PUSHNUM_1 as u8 <= *self as u8 &&
|
||||||
super::PushNum(1 + *self as isize - OP_PUSHNUM_1 as isize)
|
*self as u8 <= All::OP_PUSHNUM_16 as u8 {
|
||||||
|
OpcodeClass::PushNum(1 + *self as isize - OP_PUSHNUM_1 as isize)
|
||||||
// 76 opcodes
|
// 76 opcodes
|
||||||
} else if *self as u8 <= OP_PUSHBYTES_75 as u8 {
|
} else if *self as u8 <= All::OP_PUSHBYTES_75 as u8 {
|
||||||
super::PushBytes(*self as usize)
|
OpcodeClass::PushBytes(*self as usize)
|
||||||
// 60 opcodes
|
// 60 opcodes
|
||||||
} else {
|
} 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]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Opcode, E> {
|
fn consensus_decode(d: &mut D) -> Result<All, E> {
|
||||||
Ok(Opcode::from_u8(try!(d.read_u8())))
|
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]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
||||||
s.emit_u8(*self as u8)
|
s.emit_u8(*self as u8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl json::ToJson for Opcode {
|
impl json::ToJson for All {
|
||||||
fn to_json(&self) -> json::Json {
|
fn to_json(&self) -> json::Json {
|
||||||
json::String(self.to_string())
|
json::String(self.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Empty stack is also FALSE
|
/// Empty stack is also FALSE
|
||||||
pub static OP_FALSE: Opcode = OP_PUSHBYTES_0;
|
pub static OP_FALSE: All = OP_PUSHBYTES_0;
|
||||||
/// Number 1 is also TRUE
|
/// Number 1 is also TRUE
|
||||||
pub static OP_TRUE: Opcode = OP_PUSHNUM_1;
|
pub static OP_TRUE: All = OP_PUSHNUM_1;
|
||||||
}
|
|
||||||
|
|
||||||
/// Broad categories of opcodes with similar behavior
|
/// Broad categories of opcodes with similar behavior
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
@ -645,7 +641,7 @@ pub enum OpcodeClass {
|
||||||
/// Does nothing
|
/// Does nothing
|
||||||
NoOp,
|
NoOp,
|
||||||
/// Any opcode not covered above
|
/// Any opcode not covered above
|
||||||
Ordinary(Opcode)
|
Ordinary(Ordinary)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl json::ToJson for OpcodeClass {
|
impl json::ToJson for OpcodeClass {
|
||||||
|
@ -659,8 +655,8 @@ macro_rules! ordinary_opcode {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum Opcode {
|
pub enum Ordinary {
|
||||||
$( $op = all::$op as u8 ),*
|
$( $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::constants::Network;
|
||||||
use network::serialize::BitcoinHash;
|
use network::serialize::BitcoinHash;
|
||||||
use util::hash::{DumbHasher, Sha256dHash};
|
use util::hash::{DumbHasher, Sha256dHash};
|
||||||
use util::thinvec::ThinVec;
|
|
||||||
|
|
||||||
/// The amount of validation to do when updating the UTXO set
|
/// The amount of validation to do when updating the UTXO set
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
|
||||||
|
@ -63,7 +62,7 @@ struct UtxoNode {
|
||||||
/// Blockheight at which this UTXO appeared in the blockchain
|
/// Blockheight at which this UTXO appeared in the blockchain
|
||||||
height: u32,
|
height: u32,
|
||||||
/// Vector of outputs; None indicates a nonexistent or already spent output
|
/// 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);
|
impl_consensus_encoding!(UtxoNode, height, outputs);
|
||||||
|
|
||||||
|
@ -137,22 +136,22 @@ impl UtxoSet {
|
||||||
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 = unsafe {
|
||||||
let mut new_node = ThinVec::with_capacity(tx.output.len() as u32);
|
let mut new_node = Vec::with_capacity(tx.output.len());
|
||||||
for (vout, txo) in tx.output.iter().enumerate() {
|
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
|
||||||
if txo.script_pubkey.is_provably_unspendable() {
|
if txo.script_pubkey.is_provably_unspendable() {
|
||||||
new_node.init(vout as usize, None);
|
new_node.push(None);
|
||||||
self.n_utxos -= 1;
|
self.n_utxos -= 1;
|
||||||
self.n_pruned += 1;
|
self.n_pruned += 1;
|
||||||
} else {
|
} 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
|
// Get the old value, if any (this is suprisingly possible, c.f. BIP30
|
||||||
// and the other comments in this file referring to it)
|
// 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() {
|
if ret.is_none() {
|
||||||
self.n_utxos += tx.output.len() as u64;
|
self.n_utxos += tx.output.len() as u64;
|
||||||
}
|
}
|
||||||
|
@ -354,26 +353,17 @@ impl UtxoSet {
|
||||||
let new_node =
|
let new_node =
|
||||||
match self.table.pop(&txid) {
|
match self.table.pop(&txid) {
|
||||||
Some(mut node) => {
|
Some(mut node) => {
|
||||||
let old_len = node.outputs.len() as u32;
|
node.outputs[n as usize] = Some(txo);
|
||||||
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
|
node
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut thinvec = ThinVec::with_capacity(n + 1);
|
let mut thinvec = Vec::with_capacity(n + 1);
|
||||||
for i in range(0, n) {
|
for _ in 0..n {
|
||||||
thinvec.init(i as usize, None);
|
thinvec.push(None);
|
||||||
}
|
}
|
||||||
thinvec.init(n as usize, Some(txo));
|
thinvec.push(Some(txo));
|
||||||
UtxoNode { outputs: thinvec, height: height }
|
UtxoNode { outputs: thinvec.into_boxed_slice(), height: height }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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]
|
#[inline]
|
||||||
fn index<'a>(&'a self, idx: &usize) -> &'a $ty {
|
fn index(&self, index: usize) -> &$ty {
|
||||||
let &$thing(ref data) = self;
|
let &$thing(ref dat) = self;
|
||||||
&data[*idx]
|
&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 {
|
macro_rules! impl_array_newtype_encodable {
|
||||||
($thing:ident, $ty:ty, $len:expr) => {
|
($thing:ident, $ty:ty, $len:expr) => {
|
||||||
impl<D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for $thing {
|
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;
|
use serialize::Decodable;
|
||||||
|
|
||||||
::assert_type_is_copy::<$ty>();
|
::assert_type_is_copy::<$ty>();
|
||||||
|
@ -172,7 +214,7 @@ macro_rules! impl_array_newtype_encodable {
|
||||||
unsafe {
|
unsafe {
|
||||||
use std::mem;
|
use std::mem;
|
||||||
let mut ret: [$ty; $len] = mem::uninitialized();
|
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)));
|
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
|
||||||
}
|
}
|
||||||
Ok($thing(ret))
|
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 {
|
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)
|
self.as_slice().encode(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
|
|
||||||
// Experimental features we need
|
// Experimental features we need
|
||||||
|
#![feature(custom_derive, plugin)]
|
||||||
#![feature(overloaded_calls)]
|
#![feature(overloaded_calls)]
|
||||||
#![feature(unsafe_destructor)]
|
#![feature(unsafe_destructor)]
|
||||||
#![feature(unboxed_closure_sugar)]
|
#![feature(unboxed_closure_sugar)]
|
||||||
|
@ -49,6 +50,8 @@ extern crate core;
|
||||||
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;
|
||||||
|
extern crate serde;
|
||||||
|
#[plugin(serde_macros)]
|
||||||
extern crate test;
|
extern crate test;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ use std::default::Default;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
|
||||||
use util::thinvec::ThinVec;
|
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
use network::serialize::{SimpleDecoder, SimpleEncoder};
|
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]
|
#[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]
|
#[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));
|
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 {
|
unsafe {
|
||||||
let mut ret = ThinVec::with_capacity(len as u32);
|
let len = len as usize;
|
||||||
// Huge danger: if this fails, the remaining uninitialized part of the ThinVec
|
let mut ret = Vec::with_capacity(len);
|
||||||
// will be freed. This is ok, but only because the memory is u8, which has no
|
for i in 0..len { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
|
||||||
// destructor...and assuming there are no trap representations...very fragile.
|
Ok(ret.into_boxed_slice())
|
||||||
for i in range(0, len as usize) { ret.init(i, try!(ConsensusDecodable::consensus_decode(d))); }
|
|
||||||
Ok(ret)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||||
|
|
||||||
use std::string;
|
use std::string;
|
||||||
|
|
||||||
use util::thinvec::ThinVec;
|
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
|
|
||||||
/// An error that might occur during base58 decoding
|
/// 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()) }
|
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> {
|
impl FromBase58 for Vec<u8> {
|
||||||
fn from_base58_layout(data: Vec<u8>) -> Result<Vec<u8>, Base58Error> {
|
fn from_base58_layout(data: Vec<u8>) -> Result<Vec<u8>, Base58Error> {
|
||||||
Ok(data)
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serialize::hex::FromHex;
|
use serialize::hex::FromHex;
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
use std::io::{Error, Result, ErrorKind};
|
use std::io::{Error, Result, ErrorKind};
|
||||||
|
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use blockdata::opcodes::all::Opcode;
|
|
||||||
use util::iter::Pairable;
|
use util::iter::Pairable;
|
||||||
|
|
||||||
/// Convert a hexadecimal-encoded string to its corresponding bytes
|
/// Convert a hexadecimal-encoded string to its corresponding bytes
|
||||||
|
|
|
@ -22,7 +22,6 @@ pub mod hash;
|
||||||
pub mod iter;
|
pub mod iter;
|
||||||
pub mod misc;
|
pub mod misc;
|
||||||
pub mod patricia_tree;
|
pub mod patricia_tree;
|
||||||
pub mod thinvec;
|
|
||||||
pub mod uint;
|
pub mod uint;
|
||||||
|
|
||||||
/// A trait which allows numbers to act as fixed-size bit arrays
|
/// 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
|
/// Return the least number of bits needed to represent the number
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn bits(&self) -> uzise {
|
pub fn bits(&self) -> usize {
|
||||||
let &$name(ref arr) = self;
|
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; }
|
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()
|
0x40 - arr[0].leading_zeros()
|
||||||
|
@ -54,7 +54,7 @@ macro_rules! construct_uint {
|
||||||
let &$name(ref arr) = self;
|
let &$name(ref arr) = self;
|
||||||
let mut carry = [0u64; $n_words];
|
let mut carry = [0u64; $n_words];
|
||||||
let mut ret = [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 upper = other as u64 * (arr[i] >> 32);
|
||||||
let lower = other as u64 * (arr[i] & 0xFFFFFFFF);
|
let lower = other as u64 * (arr[i] & 0xFFFFFFFF);
|
||||||
if i < 3 {
|
if i < 3 {
|
||||||
|
@ -66,7 +66,7 @@ macro_rules! construct_uint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromPrimitive for $name {
|
impl ::std::num::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,29 +76,28 @@ macro_rules! construct_uint {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_i64(init: i64) -> Option<$name> {
|
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 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 {
|
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 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add<$name,$name> for $name {
|
impl ::std::ops::Add<$name,$name> for $name {
|
||||||
fn add(&self, other: &$name) -> $name {
|
fn add(&self, other: &$name) -> $name {
|
||||||
let &$name(ref me) = self;
|
let &$name(ref me) = self;
|
||||||
let &$name(ref you) = other;
|
let &$name(ref you) = other;
|
||||||
let mut ret = [0u64; $n_words];
|
let mut ret = [0u64; $n_words];
|
||||||
let mut carry = [0u64; $n_words];
|
let mut carry = [0u64; $n_words];
|
||||||
let mut b_carry = false;
|
let mut b_carry = false;
|
||||||
for i in range(0, $n_words) {
|
for i in 0..$n_words {
|
||||||
ret[i] = me[i] + you[i];
|
ret[i] = me[i] + you[i];
|
||||||
if i < $n_words - 1 && ret[i] < me[i] {
|
if i < $n_words - 1 && ret[i] < me[i] {
|
||||||
carry[i + 1] = 1;
|
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]
|
#[inline]
|
||||||
fn sub(&self, other: &$name) -> $name {
|
fn sub(&self, other: &$name) -> $name {
|
||||||
*self + !*other + One::one()
|
*self + !*other + One::one()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mul<$name,$name> for $name {
|
impl ::std::ops::Mul<$name,$name> for $name {
|
||||||
fn mul(&self, other: &$name) -> $name {
|
fn mul(&self, other: &$name) -> $name {
|
||||||
let mut me = *self;
|
let mut me = *self;
|
||||||
// TODO: be more efficient about this
|
// 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 = me + me.mul_u32((other >> (32 * i)).low_u32()) << (32 * i);
|
||||||
}
|
}
|
||||||
me
|
me
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<$name,$name> for $name {
|
impl ::std::ops::Div<$name,$name> for $name {
|
||||||
fn div(&self, other: &$name) -> $name {
|
fn div(&self, other: &$name) -> $name {
|
||||||
let mut sub_copy = *self;
|
let mut sub_copy = *self;
|
||||||
let mut shift_copy = *other;
|
let mut shift_copy = *other;
|
||||||
|
@ -177,7 +176,7 @@ macro_rules! construct_uint {
|
||||||
fn mask(&self, n: usize) -> $name {
|
fn mask(&self, n: usize) -> $name {
|
||||||
let &$name(ref arr) = self;
|
let &$name(ref arr) = self;
|
||||||
let mut ret = [0; $n_words];
|
let mut ret = [0; $n_words];
|
||||||
for i in range(0, $n_words) {
|
for i in 0..$n_words {
|
||||||
if n >= 0x40 * (i + 1) {
|
if n >= 0x40 * (i + 1) {
|
||||||
ret[i] = arr[i];
|
ret[i] = arr[i];
|
||||||
} else {
|
} else {
|
||||||
|
@ -191,71 +190,71 @@ macro_rules! construct_uint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn trailing_zeros(&self) -> usize {
|
fn trailing_zeros(&self) -> usize {
|
||||||
let &$name(ref arr) = self;
|
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(); }
|
if arr[i] > 0 { return (0x40 * i) + arr[i].trailing_zeros(); }
|
||||||
}
|
}
|
||||||
(0x40 * ($n_words - 1)) + arr[3].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]
|
#[inline]
|
||||||
fn bitand(&self, other: &$name) -> $name {
|
fn bitand(&self, other: &$name) -> $name {
|
||||||
let &$name(ref arr1) = self;
|
let &$name(ref arr1) = self;
|
||||||
let &$name(ref arr2) = other;
|
let &$name(ref arr2) = other;
|
||||||
let mut ret = [0u64; $n_words];
|
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];
|
ret[i] = arr1[i] & arr2[i];
|
||||||
}
|
}
|
||||||
$name(ret)
|
$name(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitXor<$name,$name> for $name {
|
impl ::std::ops::BitXor<$name,$name> for $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitxor(&self, other: &$name) -> $name {
|
fn bitxor(&self, other: &$name) -> $name {
|
||||||
let &$name(ref arr1) = self;
|
let &$name(ref arr1) = self;
|
||||||
let &$name(ref arr2) = other;
|
let &$name(ref arr2) = other;
|
||||||
let mut ret = [0u64; $n_words];
|
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];
|
ret[i] = arr1[i] ^ arr2[i];
|
||||||
}
|
}
|
||||||
$name(ret)
|
$name(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitOr<$name,$name> for $name {
|
impl ::std::ops::BitOr<$name,$name> for $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitor(&self, other: &$name) -> $name {
|
fn bitor(&self, other: &$name) -> $name {
|
||||||
let &$name(ref arr1) = self;
|
let &$name(ref arr1) = self;
|
||||||
let &$name(ref arr2) = other;
|
let &$name(ref arr2) = other;
|
||||||
let mut ret = [0u64; $n_words];
|
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];
|
ret[i] = arr1[i] | arr2[i];
|
||||||
}
|
}
|
||||||
$name(ret)
|
$name(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Not<$name> for $name {
|
impl ::std::ops::Not<$name> for $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn not(&self) -> $name {
|
fn not(&self) -> $name {
|
||||||
let &$name(ref arr) = self;
|
let &$name(ref arr) = self;
|
||||||
let mut ret = [0u64; $n_words];
|
let mut ret = [0u64; $n_words];
|
||||||
for i in range(0, $n_words) {
|
for i in 0..$n_words {
|
||||||
ret[i] = !arr[i];
|
ret[i] = !arr[i];
|
||||||
}
|
}
|
||||||
$name(ret)
|
$name(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Shl<usize, $name> for $name {
|
impl ::std::ops::Shl<usize, $name> for $name {
|
||||||
fn shl(&self, shift: &usize) -> $name {
|
fn shl(&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];
|
||||||
let word_shift = *shift / 64;
|
let word_shift = *shift / 64;
|
||||||
let bit_shift = *shift % 64;
|
let bit_shift = *shift % 64;
|
||||||
for i in range(0, $n_words) {
|
for i in 0..$n_words {
|
||||||
// Shift
|
// Shift
|
||||||
if bit_shift < 64 && i + word_shift < $n_words {
|
if bit_shift < 64 && i + word_shift < $n_words {
|
||||||
ret[i + word_shift] += original[i] << bit_shift;
|
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)]
|
#[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];
|
||||||
let word_shift = *shift / 64;
|
let word_shift = *shift / 64;
|
||||||
let bit_shift = *shift % 64;
|
let bit_shift = *shift % 64;
|
||||||
for i in range(0, $n_words) {
|
for i in 0..$n_words {
|
||||||
// Shift
|
// Shift
|
||||||
if bit_shift < 64 && i - word_shift < $n_words {
|
if bit_shift < 64 && i - word_shift < $n_words {
|
||||||
ret[i - word_shift] += original[i] >> bit_shift;
|
ret[i - word_shift] += original[i] >> bit_shift;
|
||||||
|
@ -290,20 +289,20 @@ macro_rules! construct_uint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for $name {
|
impl ::std::cmp::Ord for $name {
|
||||||
fn cmp(&self, other: &$name) -> Ordering {
|
fn cmp(&self, other: &$name) -> ::std::cmp::Ordering {
|
||||||
let &$name(ref me) = self;
|
let &$name(ref me) = self;
|
||||||
let &$name(ref you) = other;
|
let &$name(ref you) = other;
|
||||||
for i in range(0, $n_words) {
|
for i in 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 ::std::cmp::Ordering::Less; }
|
||||||
if me[$n_words - 1 - i] > you[$n_words - 1 - i] { return Greater; }
|
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 {
|
impl ::std::cmp::PartialOrd for $name {
|
||||||
fn partial_cmp(&self, other: &$name) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &$name) -> Option<::std::cmp::Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ use crypto::digest::Digest;
|
||||||
use crypto::sha2::Sha256;
|
use crypto::sha2::Sha256;
|
||||||
|
|
||||||
use blockdata::script::Script;
|
use blockdata::script::Script;
|
||||||
use blockdata::opcodes::all;
|
use blockdata::opcodes;
|
||||||
use network::constants::Network::{self, Bitcoin, BitcoinTestnet};
|
use network::constants::Network::{self, Bitcoin, BitcoinTestnet};
|
||||||
use util::hash::Ripemd160Hash;
|
use util::hash::Ripemd160Hash;
|
||||||
use util::base58::Base58Error::{self, InvalidLength, InvalidVersion};
|
use util::base58::Base58Error::{self, InvalidLength, InvalidVersion};
|
||||||
|
@ -61,11 +61,11 @@ impl Address {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn script_pubkey(&self) -> Script {
|
pub fn script_pubkey(&self) -> Script {
|
||||||
let mut script = Script::new();
|
let mut script = Script::new();
|
||||||
script.push_opcode(all::OP_DUP);
|
script.push_opcode(opcodes::All::OP_DUP);
|
||||||
script.push_opcode(all::OP_HASH160);
|
script.push_opcode(opcodes::All::OP_HASH160);
|
||||||
script.push_slice(self.hash.as_slice());
|
script.push_slice(self.hash.as_slice());
|
||||||
script.push_opcode(all::OP_EQUALVERIFY);
|
script.push_opcode(opcodes::All::OP_EQUALVERIFY);
|
||||||
script.push_opcode(all::OP_CHECKSIG);
|
script.push_opcode(opcodes::All::OP_CHECKSIG);
|
||||||
script
|
script
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ impl AddressIndex {
|
||||||
vout: idx,
|
vout: idx,
|
||||||
height: height,
|
height: height,
|
||||||
txo: txo.clone(),
|
txo: txo.clone(),
|
||||||
kind: Unknown
|
kind: WalletTxOutType::Unknown
|
||||||
};
|
};
|
||||||
ret.tentative_index.find_or_insert(txo.script_pubkey.clone(), vec![]).push(new);
|
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
|
//! at https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
|
||||||
|
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use serialize::{Decoder, Encoder};
|
use serde;
|
||||||
|
|
||||||
use byteorder::{ByteOrder, BigEndian};
|
use byteorder::{ByteOrder, BigEndian};
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
|
@ -51,7 +51,7 @@ impl Default for Fingerprint {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extended private key
|
/// Extended private key
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
pub struct ExtendedPrivKey {
|
pub struct ExtendedPrivKey {
|
||||||
/// The network this key is to be used on
|
/// The network this key is to be used on
|
||||||
pub network: Network,
|
pub network: Network,
|
||||||
|
@ -68,7 +68,7 @@ pub struct ExtendedPrivKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extended public key
|
/// Extended public key
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
pub struct ExtendedPubKey {
|
pub struct ExtendedPubKey {
|
||||||
/// The network this key is to be used on
|
/// The network this key is to be used on
|
||||||
pub network: Network,
|
pub network: Network,
|
||||||
|
@ -93,18 +93,20 @@ pub enum ChildNumber {
|
||||||
Normal(u32),
|
Normal(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Encoder<E>, E> Encodable<S, E> for ChildNumber {
|
impl serde::Serialize for ChildNumber {
|
||||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
|
||||||
|
where S: serde::Serializer {
|
||||||
match *self {
|
match *self {
|
||||||
ChildNumber::Hardened(n) => (n + (1 << 31)).encode(s),
|
ChildNumber::Hardened(n) => (n + (1 << 31)).serialize(s),
|
||||||
ChildNumber::Normal(n) => n.encode(s)
|
ChildNumber::Normal(n) => n.serialize(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Decoder<E>, E> RustcDecodable<D, E> for ChildNumber {
|
impl serde::Deserialize for ChildNumber {
|
||||||
fn decode(d: &mut D) -> Result<ChildNumber, E> {
|
fn deserialize<D>(&self, d: &mut D) -> Result<ChildNumber, D::Error>
|
||||||
let n: u32 = try!(RustcDecodable::decode(d));
|
where D: serde::Deserializer {
|
||||||
|
let n: u32 = try!(serde::Deserialize::decode(d));
|
||||||
if n < (1 << 31) {
|
if n < (1 << 31) {
|
||||||
Ok(ChildNumber::Normal(n))
|
Ok(ChildNumber::Normal(n))
|
||||||
} else {
|
} else {
|
||||||
|
@ -139,7 +141,7 @@ impl ExtendedPrivKey {
|
||||||
depth: 0,
|
depth: 0,
|
||||||
parent_fingerprint: Default::default(),
|
parent_fingerprint: Default::default(),
|
||||||
child_number: ChildNumber::Normal(0),
|
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))
|
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());
|
let mut hmac = Hmac::new(Sha512::new(), self.chain_code.as_slice());
|
||||||
match i {
|
match i {
|
||||||
ChildNumber::Normal(n) => {
|
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
|
// Non-hardened key: compute public data and use that
|
||||||
secp256k1::init();
|
secp256k1::init();
|
||||||
// Note the unwrap: this is fine, we checked the SK when we created it
|
// 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);
|
hmac.write_u32::<BigEndian>(n);
|
||||||
}
|
}
|
||||||
ChildNumber::Hardened(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
|
// Hardened key: use only secret data to prevent public derivation
|
||||||
hmac.input([0]);
|
hmac.input([0]);
|
||||||
hmac.input(self.secret_key.as_slice());
|
hmac.input(self.secret_key.as_slice());
|
||||||
|
@ -176,8 +178,8 @@ impl ExtendedPrivKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hmac.raw_result(result.as_mut_slice());
|
hmac.raw_result(result.as_mut_slice());
|
||||||
let mut sk = try!(SecretKey::from_slice(result.slice_to(32)).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(EcdsaError));
|
try!(sk.add_assign(&self.secret_key).map_err(Error::EcdsaError));
|
||||||
|
|
||||||
Ok(ExtendedPrivKey {
|
Ok(ExtendedPrivKey {
|
||||||
network: self.network,
|
network: self.network,
|
||||||
|
@ -232,9 +234,9 @@ impl ExtendedPubKey {
|
||||||
match i {
|
match i {
|
||||||
ChildNumber::Hardened(n) => {
|
ChildNumber::Hardened(n) => {
|
||||||
if n >= (1 << 31) {
|
if n >= (1 << 31) {
|
||||||
Err(InvalidChildNumber(i))
|
Err(Error::InvalidChildNumber(i))
|
||||||
} else {
|
} else {
|
||||||
Err(CannotDeriveFromHardenedKey)
|
Err(Error::CannotDeriveFromHardenedKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ChildNumber::Normal(n) => {
|
ChildNumber::Normal(n) => {
|
||||||
|
@ -245,9 +247,9 @@ impl ExtendedPubKey {
|
||||||
let mut result = [0; 64];
|
let mut result = [0; 64];
|
||||||
hmac.raw_result(result.as_mut_slice());
|
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();
|
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 {
|
Ok(ExtendedPubKey {
|
||||||
network: self.network,
|
network: self.network,
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use serialize::{Decoder, Encoder};
|
use serde;
|
||||||
|
|
||||||
use secp256k1::key::PublicKey;
|
use secp256k1::key::PublicKey;
|
||||||
|
|
||||||
|
@ -54,9 +54,8 @@ pub enum AccountChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An account
|
/// An account
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
name: String,
|
|
||||||
internal_path: Vec<ChildNumber>,
|
internal_path: Vec<ChildNumber>,
|
||||||
internal_used: Vec<ChildNumber>,
|
internal_used: Vec<ChildNumber>,
|
||||||
internal_next: u32,
|
internal_next: u32,
|
||||||
|
@ -68,7 +67,6 @@ pub struct Account {
|
||||||
impl Default for Account {
|
impl Default for Account {
|
||||||
fn default() -> Account {
|
fn default() -> Account {
|
||||||
Account {
|
Account {
|
||||||
name: String::new(),
|
|
||||||
internal_path: vec![Hardened(0), Normal(1)],
|
internal_path: vec![Hardened(0), Normal(1)],
|
||||||
internal_used: vec![],
|
internal_used: vec![],
|
||||||
internal_next: 0,
|
internal_next: 0,
|
||||||
|
@ -87,39 +85,23 @@ pub struct Wallet {
|
||||||
index: Option<AddressIndex>
|
index: Option<AddressIndex>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Encoder<E>, E> Encodable<S, E> for Wallet {
|
impl serde::Serialize for Wallet {
|
||||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
|
||||||
s.emit_struct("wallet", 2, |s| {
|
where S: serde::Serializer {
|
||||||
try!(s.emit_struct_field("master", 0, |s| self.master.encode(s)));
|
let len = self.accounts.len();
|
||||||
s.emit_struct_field("accounts", 1,
|
try!(self.master.serialize(s));
|
||||||
|s| s.emit_seq(self.accounts.len(), |s| {
|
self.accounts.serialize(s)
|
||||||
for (_, account) in self.accounts.iter() {
|
|
||||||
try!(account.encode(s));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Decoder<E>, E> Decodable<D, E> for Wallet {
|
impl serde::Deserialize for Wallet {
|
||||||
fn decode(d: &mut D) -> Result<Wallet, E> {
|
fn deserialize<D>(&self, d: &mut D) -> Result<Wallet, D::Error>
|
||||||
d.read_struct("wallet", 2, |d| {
|
where D: serde::Deserializer {
|
||||||
Ok(Wallet {
|
Wallet {
|
||||||
master: try!(d.read_struct_field("master", 0, Decodable::decode)),
|
master: try!(serde::Deserialize::deserialize(d)),
|
||||||
accounts: try!(d.read_struct_field("accounts", 1, |d| {
|
accounts: try!(serde::Deserialize::deserialize(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)
|
|
||||||
})
|
|
||||||
})),
|
|
||||||
index: None
|
index: None
|
||||||
})
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,8 +146,7 @@ impl Wallet {
|
||||||
}
|
}
|
||||||
|
|
||||||
let idx = self.accounts.len() as u32;
|
let idx = self.accounts.len() as u32;
|
||||||
self.accounts.insert(name.clone(), Account {
|
self.accounts.insert(name, Account {
|
||||||
name: name,
|
|
||||||
internal_path: vec![Hardened(idx), Normal(1)],
|
internal_path: vec![Hardened(idx), Normal(1)],
|
||||||
internal_used: vec![],
|
internal_used: vec![],
|
||||||
internal_next: 0,
|
internal_next: 0,
|
||||||
|
|
Loading…
Reference in New Issue