Many syntax changes for rustc, incomplete
This commit is contained in:
parent
97bfbe790b
commit
c3377032f8
|
@ -79,7 +79,7 @@ impl BlockHeader {
|
||||||
let (mant, expt) = {
|
let (mant, expt) = {
|
||||||
let unshifted_expt = self.bits >> 24;
|
let unshifted_expt = self.bits >> 24;
|
||||||
if unshifted_expt <= 3 {
|
if unshifted_expt <= 3 {
|
||||||
((self.bits & 0xFFFFFF) >> 8 * (3 - unshifted_expt as uint), 0)
|
((self.bits & 0xFFFFFF) >> 8 * (3 - unshifted_expt as usize), 0)
|
||||||
} else {
|
} else {
|
||||||
(self.bits & 0xFFFFFF, 8 * ((self.bits >> 24) - 3))
|
(self.bits & 0xFFFFFF, 8 * ((self.bits >> 24) - 3))
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ impl BlockHeader {
|
||||||
if mant > 0x7FFFFF {
|
if mant > 0x7FFFFF {
|
||||||
Zero::zero()
|
Zero::zero()
|
||||||
} else {
|
} else {
|
||||||
from_u64::<Uint256>(mant as u64).unwrap() << (expt as uint)
|
from_u64::<Uint256>(mant as u64).unwrap() << (expt as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,10 +130,10 @@ impl BitcoinHash for Block {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce)
|
impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce);
|
||||||
impl_json!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce)
|
impl_json!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce);
|
||||||
impl_consensus_encoding!(Block, header, txdata)
|
impl_consensus_encoding!(Block, header, txdata);
|
||||||
impl_consensus_encoding!(LoneBlockHeader, header, tx_count)
|
impl_consensus_encoding!(LoneBlockHeader, header, tx_count);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -193,8 +193,8 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Blockchain {
|
||||||
// with a ContravariantLifetime marker tying it to the tree's lifetime.
|
// with a ContravariantLifetime marker tying it to the tree's lifetime.
|
||||||
struct LocatorHashIter {
|
struct LocatorHashIter {
|
||||||
index: NodePtr,
|
index: NodePtr,
|
||||||
count: uint,
|
count: usize,
|
||||||
skip: uint
|
skip: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocatorHashIter {
|
impl LocatorHashIter {
|
||||||
|
@ -341,7 +341,7 @@ impl Blockchain {
|
||||||
pub fn new(network: Network) -> Blockchain {
|
pub fn new(network: Network) -> Blockchain {
|
||||||
let genesis = genesis_block(network);
|
let genesis = genesis_block(network);
|
||||||
let genhash = genesis.header.bitcoin_hash();
|
let genhash = genesis.header.bitcoin_hash();
|
||||||
let new_node = box BlockchainNode {
|
let new_node = Box::new(BlockchainNode {
|
||||||
total_work: Zero::zero(),
|
total_work: Zero::zero(),
|
||||||
required_difficulty: genesis.header.target(),
|
required_difficulty: genesis.header.target(),
|
||||||
block: genesis,
|
block: genesis,
|
||||||
|
@ -349,7 +349,7 @@ impl Blockchain {
|
||||||
has_txdata: true,
|
has_txdata: true,
|
||||||
prev: RawPtr::null(),
|
prev: RawPtr::null(),
|
||||||
next: RawPtr::null()
|
next: RawPtr::null()
|
||||||
};
|
});
|
||||||
let raw_ptr = &*new_node as NodePtr;
|
let raw_ptr = &*new_node as NodePtr;
|
||||||
Blockchain {
|
Blockchain {
|
||||||
network: network,
|
network: network,
|
||||||
|
@ -490,7 +490,7 @@ impl Blockchain {
|
||||||
unsafe { (*prev).required_difficulty }
|
unsafe { (*prev).required_difficulty }
|
||||||
};
|
};
|
||||||
// Create node
|
// Create node
|
||||||
let ret = box BlockchainNode {
|
let ret = Box::new(BlockchainNode {
|
||||||
total_work: block.header.work().add(unsafe { &(*prev).total_work }),
|
total_work: block.header.work().add(unsafe { &(*prev).total_work }),
|
||||||
block: block,
|
block: block,
|
||||||
required_difficulty: difficulty,
|
required_difficulty: difficulty,
|
||||||
|
@ -498,7 +498,7 @@ impl Blockchain {
|
||||||
has_txdata: has_txdata,
|
has_txdata: has_txdata,
|
||||||
prev: prev,
|
prev: prev,
|
||||||
next: RawPtr::null()
|
next: RawPtr::null()
|
||||||
};
|
});
|
||||||
unsafe {
|
unsafe {
|
||||||
let prev = prev as *mut BlockchainNode;
|
let prev = prev as *mut BlockchainNode;
|
||||||
(*prev).next = &*ret as NodePtr;
|
(*prev).next = &*ret as NodePtr;
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub static DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600;
|
||||||
|
|
||||||
/// In Bitcoind this is insanely described as ~((u256)0 >> 32)
|
/// In Bitcoind this is insanely described as ~((u256)0 >> 32)
|
||||||
pub fn max_target(_: Network) -> Uint256 {
|
pub fn max_target(_: Network) -> Uint256 {
|
||||||
from_u64::<Uint256>(0xFFFF).unwrap() << 208u
|
from_u64::<Uint256>(0xFFFF).unwrap() << 208
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The maximum value allowed in an output (useful for sanity checking,
|
/// The maximum value allowed in an output (useful for sanity checking,
|
||||||
|
|
|
@ -594,10 +594,10 @@ pub mod all {
|
||||||
super::PushNum(-1)
|
super::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 OP_PUSHNUM_1 as u8 <= *self as u8 && *self as u8 <= OP_PUSHNUM_16 as u8 {
|
||||||
super::PushNum(1 + *self as int - OP_PUSHNUM_1 as int)
|
super::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 <= OP_PUSHBYTES_75 as u8 {
|
||||||
super::PushBytes(*self as uint)
|
super::PushBytes(*self as usize)
|
||||||
// 60 opcodes
|
// 60 opcodes
|
||||||
} else {
|
} else {
|
||||||
super::Ordinary(unsafe { transmute(*self) })
|
super::Ordinary(unsafe { transmute(*self) })
|
||||||
|
@ -635,9 +635,9 @@ pub mod all {
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
pub enum OpcodeClass {
|
pub enum OpcodeClass {
|
||||||
/// Pushes the given number onto the stack
|
/// Pushes the given number onto the stack
|
||||||
PushNum(int),
|
PushNum(isize),
|
||||||
/// Pushes the given number of bytes onto the stack
|
/// Pushes the given number of bytes onto the stack
|
||||||
PushBytes(uint),
|
PushBytes(usize),
|
||||||
/// Fails the script if executed
|
/// Fails the script if executed
|
||||||
ReturnOp,
|
ReturnOp,
|
||||||
/// Fails the script even if not executed
|
/// Fails the script even if not executed
|
||||||
|
@ -654,7 +654,7 @@ impl json::ToJson for OpcodeClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! ordinary_opcode(
|
macro_rules! ordinary_opcode {
|
||||||
($($op:ident),*) => (
|
($($op:ident),*) => (
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -663,10 +663,10 @@ macro_rules! ordinary_opcode(
|
||||||
$( $op = all::$op as u8 ),*
|
$( $op = all::$op as u8 ),*
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
)
|
}
|
||||||
|
|
||||||
/// "Ordinary" opcodes -- should be 60 of these
|
/// "Ordinary" opcodes -- should be 60 of these
|
||||||
ordinary_opcode!(
|
ordinary_opcode! {
|
||||||
// pushdata
|
// pushdata
|
||||||
OP_PUSHDATA1, OP_PUSHDATA2, OP_PUSHDATA4,
|
OP_PUSHDATA1, OP_PUSHDATA2, OP_PUSHDATA4,
|
||||||
// control flow
|
// control flow
|
||||||
|
@ -688,6 +688,6 @@ ordinary_opcode!(
|
||||||
OP_RIPEMD160, OP_SHA1, OP_SHA256, OP_HASH160, OP_HASH256,
|
OP_RIPEMD160, OP_SHA1, OP_SHA256, OP_HASH160, OP_HASH256,
|
||||||
OP_CODESEPARATOR, OP_CHECKSIG, OP_CHECKSIGVERIFY,
|
OP_CODESEPARATOR, OP_CHECKSIG, OP_CHECKSIGVERIFY,
|
||||||
OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
|
OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
|
||||||
)
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -98,9 +98,9 @@ pub enum ScriptError {
|
||||||
/// An OP_RETURN or synonym was executed
|
/// An OP_RETURN or synonym was executed
|
||||||
ExecutedReturn,
|
ExecutedReturn,
|
||||||
/// A multisig tx with negative or too many keys
|
/// A multisig tx with negative or too many keys
|
||||||
MultisigBadKeyCount(int),
|
MultisigBadKeyCount(isize),
|
||||||
/// A multisig tx with negative or too many signatures
|
/// A multisig tx with negative or too many signatures
|
||||||
MultisigBadSigCount(int),
|
MultisigBadSigCount(isize),
|
||||||
/// Used OP_PICK with a negative index
|
/// Used OP_PICK with a negative index
|
||||||
NegativePick,
|
NegativePick,
|
||||||
/// Used OP_ROLL with a negative index
|
/// Used OP_ROLL with a negative index
|
||||||
|
@ -126,15 +126,15 @@ pub enum ScriptError {
|
||||||
/// A rule for validating an abstract stack element
|
/// A rule for validating an abstract stack element
|
||||||
pub struct Validator {
|
pub struct Validator {
|
||||||
/// List of other elements to pass to both `check` and `update`
|
/// List of other elements to pass to both `check` and `update`
|
||||||
args: Vec<uint>,
|
args: Vec<usize>,
|
||||||
/// Function which confirms that the current value is consistent with
|
/// Function which confirms that the current value is consistent with
|
||||||
/// the stack state, returning `false` if not.
|
/// the stack state, returning `false` if not.
|
||||||
check: fn(&AbstractStackElem, &[uint]) -> bool,
|
check: fn(&AbstractStackElem, &[usize]) -> bool,
|
||||||
/// Function which updates the current stack based on the element's
|
/// Function which updates the current stack based on the element's
|
||||||
/// value, if it has a value, otherwise updates the element's value
|
/// value, if it has a value, otherwise updates the element's value
|
||||||
/// based on the current stack, if possible. Returns `false` if it
|
/// based on the current stack, if possible. Returns `false` if it
|
||||||
/// is forced to do something inconsistent.
|
/// is forced to do something inconsistent.
|
||||||
update: fn(&mut AbstractStackElem, &[uint]) -> Result<(), ScriptError>
|
update: fn(&mut AbstractStackElem, &[usize]) -> Result<(), ScriptError>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Validator {
|
impl Clone for Validator {
|
||||||
|
@ -148,13 +148,13 @@ impl Clone for Validator {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validators
|
// Validators
|
||||||
fn check_op_size(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_size(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let other = unsafe { elem.lookup(others[0]) };
|
let other = unsafe { elem.lookup(others[0]) };
|
||||||
elem.num_hi() >= other.len_lo() as i64 &&
|
elem.num_hi() >= other.len_lo() as i64 &&
|
||||||
elem.num_lo() <= other.len_hi() as i64
|
elem.num_lo() <= other.len_hi() as i64
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_size(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_size(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
let (lo, hi) = {
|
let (lo, hi) = {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
|
@ -165,7 +165,7 @@ fn update_op_size(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
elem.set_num_hi(hi)
|
elem.set_num_hi(hi)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_equal(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_equal(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
let two = unsafe { elem.lookup(others[1]) };
|
let two = unsafe { elem.lookup(others[1]) };
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
|
@ -207,7 +207,7 @@ fn update_boolean(elem: &mut AbstractStackElem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_equal(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_equal(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => update_boolean(elem),
|
None => update_boolean(elem),
|
||||||
|
@ -240,8 +240,8 @@ fn update_op_equal(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
(Some(_), Some(_)) => { return Err(Unsatisfiable); }
|
(Some(_), Some(_)) => { return Err(Unsatisfiable); }
|
||||||
}
|
}
|
||||||
// Equalize full values
|
// Equalize full values
|
||||||
match (one.raw_value().map(|r| Vec::from_slice(r)),
|
match (one.raw_value().map(|r| r.to_vec()),
|
||||||
two.raw_value().map(|r| Vec::from_slice(r))) {
|
two.raw_value().map(|r| r.to_vec())) {
|
||||||
(None, None) => {},
|
(None, None) => {},
|
||||||
(None, Some(x)) => try!(one.set_value(x.as_slice())),
|
(None, Some(x)) => try!(one.set_value(x.as_slice())),
|
||||||
(Some(x), None) => try!(two.set_value(x.as_slice())),
|
(Some(x), None) => try!(two.set_value(x.as_slice())),
|
||||||
|
@ -252,7 +252,7 @@ fn update_op_equal(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_not(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_not(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
if !one.may_be_numeric() {
|
if !one.may_be_numeric() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -265,7 +265,7 @@ fn check_op_not(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_not(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_not(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => update_boolean(elem),
|
None => update_boolean(elem),
|
||||||
|
@ -290,7 +290,7 @@ fn update_op_not(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_0notequal(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_0notequal(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
if !one.may_be_numeric() { return false; }
|
if !one.may_be_numeric() { return false; }
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
|
@ -300,7 +300,7 @@ fn check_op_0notequal(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_0notequal(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_0notequal(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => update_boolean(elem),
|
None => update_boolean(elem),
|
||||||
|
@ -325,7 +325,7 @@ fn update_op_0notequal(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_numequal(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_numequal(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
let two = unsafe { elem.lookup(others[1]) };
|
let two = unsafe { elem.lookup(others[1]) };
|
||||||
if !one.may_be_numeric() { return false; }
|
if !one.may_be_numeric() { return false; }
|
||||||
|
@ -349,7 +349,7 @@ fn check_op_numequal(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_numequal(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_numequal(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => update_boolean(elem),
|
None => update_boolean(elem),
|
||||||
|
@ -370,7 +370,7 @@ fn update_op_numequal(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_numnotequal(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_numnotequal(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
let two = unsafe { elem.lookup(others[1]) };
|
let two = unsafe { elem.lookup(others[1]) };
|
||||||
if !one.may_be_numeric() { return false; }
|
if !one.may_be_numeric() { return false; }
|
||||||
|
@ -382,7 +382,7 @@ fn check_op_numnotequal(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_numnotequal(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_numnotequal(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => update_boolean(elem),
|
None => update_boolean(elem),
|
||||||
|
@ -403,7 +403,7 @@ fn update_op_numnotequal(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_numlt(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_numlt(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
let two = unsafe { elem.lookup(others[1]) };
|
let two = unsafe { elem.lookup(others[1]) };
|
||||||
if !one.may_be_numeric() { return false; }
|
if !one.may_be_numeric() { return false; }
|
||||||
|
@ -415,7 +415,7 @@ fn check_op_numlt(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_numlt(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_numlt(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => update_boolean(elem),
|
None => update_boolean(elem),
|
||||||
|
@ -440,7 +440,7 @@ fn update_op_numlt(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_numgt(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_numgt(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
let two = unsafe { elem.lookup(others[1]) };
|
let two = unsafe { elem.lookup(others[1]) };
|
||||||
if !one.may_be_numeric() { return false; }
|
if !one.may_be_numeric() { return false; }
|
||||||
|
@ -452,7 +452,7 @@ fn check_op_numgt(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_numgt(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_numgt(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => try!(update_boolean(elem)),
|
None => try!(update_boolean(elem)),
|
||||||
|
@ -478,7 +478,7 @@ fn update_op_numgt(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_numlteq(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_numlteq(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
let two = unsafe { elem.lookup(others[1]) };
|
let two = unsafe { elem.lookup(others[1]) };
|
||||||
if !one.may_be_numeric() { return false; }
|
if !one.may_be_numeric() { return false; }
|
||||||
|
@ -490,7 +490,7 @@ fn check_op_numlteq(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_numlteq(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_numlteq(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => try!(update_boolean(elem)),
|
None => try!(update_boolean(elem)),
|
||||||
|
@ -516,7 +516,7 @@ fn update_op_numlteq(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_numgteq(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_numgteq(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
let two = unsafe { elem.lookup(others[1]) };
|
let two = unsafe { elem.lookup(others[1]) };
|
||||||
if !one.may_be_numeric() { return false; }
|
if !one.may_be_numeric() { return false; }
|
||||||
|
@ -528,7 +528,7 @@ fn check_op_numgteq(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_numgteq(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_numgteq(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => try!(update_boolean(elem)),
|
None => try!(update_boolean(elem)),
|
||||||
|
@ -554,11 +554,11 @@ fn update_op_numgteq(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_ripemd160(elem: &AbstractStackElem, _: &[uint]) -> bool {
|
fn check_op_ripemd160(elem: &AbstractStackElem, _: &[usize]) -> bool {
|
||||||
elem.may_be_hash160()
|
elem.may_be_hash160()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_ripemd160(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_ripemd160(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
try!(elem.set_len_lo(20));
|
try!(elem.set_len_lo(20));
|
||||||
try!(elem.set_len_hi(20));
|
try!(elem.set_len_hi(20));
|
||||||
|
@ -580,11 +580,11 @@ fn update_op_ripemd160(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_sha1(elem: &AbstractStackElem, _: &[uint]) -> bool {
|
fn check_op_sha1(elem: &AbstractStackElem, _: &[usize]) -> bool {
|
||||||
elem.may_be_hash160()
|
elem.may_be_hash160()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_sha1(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_sha1(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
try!(elem.set_len_lo(20));
|
try!(elem.set_len_lo(20));
|
||||||
try!(elem.set_len_hi(20));
|
try!(elem.set_len_hi(20));
|
||||||
|
@ -606,11 +606,11 @@ fn update_op_sha1(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_hash160(elem: &AbstractStackElem, _: &[uint]) -> bool {
|
fn check_op_hash160(elem: &AbstractStackElem, _: &[usize]) -> bool {
|
||||||
elem.may_be_hash160()
|
elem.may_be_hash160()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_hash160(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_hash160(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
try!(elem.set_len_lo(20));
|
try!(elem.set_len_lo(20));
|
||||||
try!(elem.set_len_hi(20));
|
try!(elem.set_len_hi(20));
|
||||||
|
@ -636,11 +636,11 @@ fn update_op_hash160(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_sha256(elem: &AbstractStackElem, _: &[uint]) -> bool {
|
fn check_op_sha256(elem: &AbstractStackElem, _: &[usize]) -> bool {
|
||||||
elem.may_be_hash256()
|
elem.may_be_hash256()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_sha256(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_sha256(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
try!(elem.set_len_lo(32));
|
try!(elem.set_len_lo(32));
|
||||||
try!(elem.set_len_hi(32));
|
try!(elem.set_len_hi(32));
|
||||||
|
@ -662,11 +662,11 @@ fn update_op_sha256(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_hash256(elem: &AbstractStackElem, _: &[uint]) -> bool {
|
fn check_op_hash256(elem: &AbstractStackElem, _: &[usize]) -> bool {
|
||||||
elem.may_be_hash256()
|
elem.may_be_hash256()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_hash256(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_hash256(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
try!(elem.set_len_lo(32));
|
try!(elem.set_len_lo(32));
|
||||||
try!(elem.set_len_hi(32));
|
try!(elem.set_len_hi(32));
|
||||||
|
@ -691,7 +691,7 @@ fn update_op_hash256(elem: &mut AbstractStackElem, others: &[uint])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_op_checksig(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
fn check_op_checksig(elem: &AbstractStackElem, others: &[usize]) -> bool {
|
||||||
let one = unsafe { elem.lookup(others[0]) };
|
let one = unsafe { elem.lookup(others[0]) };
|
||||||
let two = unsafe { elem.lookup(others[1]) };
|
let two = unsafe { elem.lookup(others[1]) };
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
|
@ -701,7 +701,7 @@ fn check_op_checksig(elem: &AbstractStackElem, others: &[uint]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_op_checksig(elem: &mut AbstractStackElem, others: &[uint])
|
fn update_op_checksig(elem: &mut AbstractStackElem, others: &[usize])
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
match elem.bool_value() {
|
match elem.bool_value() {
|
||||||
None => update_boolean(elem),
|
None => update_boolean(elem),
|
||||||
|
@ -732,13 +732,13 @@ pub struct AbstractStackElem {
|
||||||
/// Upper bound when read as number
|
/// Upper bound when read as number
|
||||||
num_hi: i64,
|
num_hi: i64,
|
||||||
/// Length lower bound
|
/// Length lower bound
|
||||||
len_lo: uint,
|
len_lo: usize,
|
||||||
/// Length upper bound
|
/// Length upper bound
|
||||||
len_hi: uint,
|
len_hi: usize,
|
||||||
/// Relations this must satisfy
|
/// Relations this must satisfy
|
||||||
validators: Vec<Validator>,
|
validators: Vec<Validator>,
|
||||||
/// Index of the element in its stack allocator
|
/// Index of the element in its stack allocator
|
||||||
alloc_index: Option<uint>
|
alloc_index: Option<usize>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractStackElem {
|
impl AbstractStackElem {
|
||||||
|
@ -771,7 +771,7 @@ impl AbstractStackElem {
|
||||||
len_lo: data.len(),
|
len_lo: data.len(),
|
||||||
len_hi: data.len(),
|
len_hi: data.len(),
|
||||||
bool_val: Some(read_scriptbool(data)),
|
bool_val: Some(read_scriptbool(data)),
|
||||||
raw: Some(Vec::from_slice(data)),
|
raw: Some(data.to_vec()),
|
||||||
validators: vec![],
|
validators: vec![],
|
||||||
alloc_index: None
|
alloc_index: None
|
||||||
}
|
}
|
||||||
|
@ -792,17 +792,17 @@ impl AbstractStackElem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Looks up another stack item by index
|
/// Looks up another stack item by index
|
||||||
unsafe fn lookup<'a>(&'a self, idx: uint) -> &'a AbstractStackElem {
|
unsafe fn lookup<'a>(&'a self, idx: usize) -> &'a AbstractStackElem {
|
||||||
let mypos = self as *const _;
|
let mypos = self as *const _;
|
||||||
let myidx = self.alloc_index.unwrap() as int;
|
let myidx = self.alloc_index.unwrap() as isize;
|
||||||
&*mypos.offset(idx as int - myidx)
|
&*mypos.offset(idx as isize - myidx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Looks up another stack item by index
|
/// Looks up another stack item by index
|
||||||
unsafe fn lookup_mut<'a>(&'a self, idx: uint) -> &'a mut AbstractStackElem {
|
unsafe fn lookup_mut<'a>(&'a self, idx: usize) -> &'a mut AbstractStackElem {
|
||||||
let mypos = self as *const _ as *mut _;
|
let mypos = self as *const _ as *mut _;
|
||||||
let myidx = self.alloc_index.unwrap() as int;
|
let myidx = self.alloc_index.unwrap() as isize;
|
||||||
&mut *mypos.offset(idx as int - myidx)
|
&mut *mypos.offset(idx as isize - myidx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the boolean value of the stack element, if it can be determined
|
/// Retrieve the boolean value of the stack element, if it can be determined
|
||||||
|
@ -832,13 +832,13 @@ impl AbstractStackElem {
|
||||||
/// Retrieve the upper bound for this element's length. This always
|
/// Retrieve the upper bound for this element's length. This always
|
||||||
/// exists as a finite value, though the default upper limit is some
|
/// exists as a finite value, though the default upper limit is some
|
||||||
/// impractically large number
|
/// impractically large number
|
||||||
pub fn len_hi(&self) -> uint {
|
pub fn len_hi(&self) -> usize {
|
||||||
self.len_hi
|
self.len_hi
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the lower bound for this element's length. This always
|
/// Retrieve the lower bound for this element's length. This always
|
||||||
/// exists since it is at least zero :)
|
/// exists since it is at least zero :)
|
||||||
pub fn len_lo(&self) -> uint {
|
pub fn len_lo(&self) -> usize {
|
||||||
self.len_lo
|
self.len_lo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,7 +901,7 @@ impl AbstractStackElem {
|
||||||
|
|
||||||
/// Sets the entire value of the
|
/// Sets the entire value of the
|
||||||
pub fn set_value(&mut self, val: &[u8]) -> Result<(), ScriptError> {
|
pub fn set_value(&mut self, val: &[u8]) -> Result<(), ScriptError> {
|
||||||
match self.raw_value().map(|x| Vec::from_slice(x)) {
|
match self.raw_value().map(|x| x.to_vec()) {
|
||||||
Some(x) => { if x.as_slice() == val { Ok(()) } else { Err(Unsatisfiable) } }
|
Some(x) => { if x.as_slice() == val { Ok(()) } else { Err(Unsatisfiable) } }
|
||||||
None => {
|
None => {
|
||||||
try!(self.set_len_lo(val.len()));
|
try!(self.set_len_lo(val.len()));
|
||||||
|
@ -915,7 +915,7 @@ impl AbstractStackElem {
|
||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
}
|
}
|
||||||
try!(self.set_bool_value(read_scriptbool(val)));
|
try!(self.set_bool_value(read_scriptbool(val)));
|
||||||
self.raw = Some(Vec::from_slice(val));
|
self.raw = Some(val.to_vec());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1012,7 +1012,7 @@ impl AbstractStackElem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a lower length bound on a value
|
/// Sets a lower length bound on a value
|
||||||
pub fn set_len_lo(&mut self, value: uint) -> Result<(), ScriptError> {
|
pub fn set_len_lo(&mut self, value: usize) -> Result<(), ScriptError> {
|
||||||
if self.len_lo < value {
|
if self.len_lo < value {
|
||||||
self.len_lo = value;
|
self.len_lo = value;
|
||||||
if value > 0 { try!(self.set_bool_value(true)); }
|
if value > 0 { try!(self.set_bool_value(true)); }
|
||||||
|
@ -1023,7 +1023,7 @@ impl AbstractStackElem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a upper length bound on a value
|
/// Sets a upper length bound on a value
|
||||||
pub fn set_len_hi(&mut self, value: uint) -> Result<(), ScriptError> {
|
pub fn set_len_hi(&mut self, value: usize) -> Result<(), ScriptError> {
|
||||||
if self.len_hi > value {
|
if self.len_hi > value {
|
||||||
self.len_hi = value;
|
self.len_hi = value;
|
||||||
try!(self.update());
|
try!(self.update());
|
||||||
|
@ -1043,11 +1043,11 @@ impl AbstractStackElem {
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct AbstractStack {
|
pub struct AbstractStack {
|
||||||
/// Actual elements on the stack
|
/// Actual elements on the stack
|
||||||
stack: Vec<uint>,
|
stack: Vec<usize>,
|
||||||
/// Actual elements on the altstack
|
/// Actual elements on the altstack
|
||||||
alt_stack: Vec<uint>,
|
alt_stack: Vec<usize>,
|
||||||
/// Stack needed to satisfy the script before execution
|
/// Stack needed to satisfy the script before execution
|
||||||
initial_stack: Vec<uint>,
|
initial_stack: Vec<usize>,
|
||||||
/// Local allocator to allow cloning; refs are indices into here
|
/// Local allocator to allow cloning; refs are indices into here
|
||||||
alloc: Vec<AbstractStackElem>
|
alloc: Vec<AbstractStackElem>
|
||||||
}
|
}
|
||||||
|
@ -1063,7 +1063,7 @@ impl AbstractStack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate(&mut self, mut elem: AbstractStackElem) -> uint {
|
fn allocate(&mut self, mut elem: AbstractStackElem) -> usize {
|
||||||
elem.alloc_index = Some(self.alloc.len());
|
elem.alloc_index = Some(self.alloc.len());
|
||||||
self.alloc.push(elem);
|
self.alloc.push(elem);
|
||||||
self.alloc.len() - 1
|
self.alloc.len() - 1
|
||||||
|
@ -1084,24 +1084,24 @@ impl AbstractStack {
|
||||||
|
|
||||||
/// Increase the stack size to `n`, adding elements to the initial
|
/// Increase the stack size to `n`, adding elements to the initial
|
||||||
/// stack as necessary
|
/// stack as necessary
|
||||||
pub fn require_n_elems(&mut self, n: uint) {
|
pub fn require_n_elems(&mut self, n: usize) {
|
||||||
while self.stack.len() < n {
|
while self.stack.len() < n {
|
||||||
self.push_initial(AbstractStackElem::new_unknown());
|
self.push_initial(AbstractStackElem::new_unknown());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup an element by index
|
/// Lookup an element by index
|
||||||
pub fn get_elem(&self, alloc_index: uint) -> &AbstractStackElem {
|
pub fn get_elem(&self, alloc_index: usize) -> &AbstractStackElem {
|
||||||
&self.alloc[alloc_index]
|
&self.alloc[alloc_index]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup an element by index
|
/// Lookup an element by index
|
||||||
pub fn get_elem_mut(&mut self, alloc_index: uint) -> &mut AbstractStackElem {
|
pub fn get_elem_mut(&mut self, alloc_index: usize) -> &mut AbstractStackElem {
|
||||||
self.alloc.get_mut(alloc_index)
|
self.alloc.get_mut(alloc_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push a copy of an existing element by index
|
/// Push a copy of an existing element by index
|
||||||
pub fn push(&mut self, elem: uint) {
|
pub fn push(&mut self, elem: usize) {
|
||||||
self.stack.push(elem);
|
self.stack.push(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1123,7 +1123,7 @@ impl AbstractStack {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain a stackref to the current top element
|
/// Obtain a stackref to the current top element
|
||||||
pub fn peek_index(&mut self) -> uint {
|
pub fn peek_index(&mut self) -> usize {
|
||||||
if self.stack.len() == 0 {
|
if self.stack.len() == 0 {
|
||||||
self.push_initial(AbstractStackElem::new_unknown());
|
self.push_initial(AbstractStackElem::new_unknown());
|
||||||
}
|
}
|
||||||
|
@ -1131,7 +1131,7 @@ impl AbstractStack {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Drop the top stack item
|
/// Drop the top stack item
|
||||||
fn pop(&mut self) -> uint {
|
fn pop(&mut self) -> usize {
|
||||||
if self.stack.len() == 0 {
|
if self.stack.len() == 0 {
|
||||||
self.push_initial(AbstractStackElem::new_unknown());
|
self.push_initial(AbstractStackElem::new_unknown());
|
||||||
}
|
}
|
||||||
|
@ -1171,28 +1171,28 @@ impl AbstractStack {
|
||||||
|
|
||||||
/// Immutable view of the current stack as a slice (to be compatible
|
/// Immutable view of the current stack as a slice (to be compatible
|
||||||
/// with the `stack_opcode!` macro
|
/// with the `stack_opcode!` macro
|
||||||
pub fn as_slice<'a>(&'a self) -> &'a [uint] {
|
pub fn as_slice<'a>(&'a self) -> &'a [usize] {
|
||||||
self.stack.as_slice()
|
self.stack.as_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Immutable view of the current stack as a slice of bytes
|
/// Immutable view of the current stack as a slice of bytes
|
||||||
pub fn slice_to<'a>(&'a self, n: uint) -> &'a [uint] {
|
pub fn slice_to<'a>(&'a self, n: usize) -> &'a [usize] {
|
||||||
self.stack.slice_to(n)
|
self.stack.slice_to(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutable view of the current stack as a slice (to be compatible
|
/// Mutable view of the current stack as a slice (to be compatible
|
||||||
/// with the `stack_opcode!` macro
|
/// with the `stack_opcode!` macro
|
||||||
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [uint] {
|
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [usize] {
|
||||||
self.stack.as_mut_slice()
|
self.stack.as_mut_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Length of the current stack
|
/// Length of the current stack
|
||||||
fn len(&self) -> uint {
|
fn len(&self) -> usize {
|
||||||
self.stack.len()
|
self.stack.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete an element from the middle of the current stack
|
/// Delete an element from the middle of the current stack
|
||||||
fn remove(&mut self, idx: uint) {
|
fn remove(&mut self, idx: usize) {
|
||||||
self.stack.remove(idx);
|
self.stack.remove(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1206,8 +1206,8 @@ impl json::ToJson for ScriptError {
|
||||||
/// A single iteration of a script execution
|
/// A single iteration of a script execution
|
||||||
#[deriving(PartialEq, Eq, Show, Clone)]
|
#[deriving(PartialEq, Eq, Show, Clone)]
|
||||||
pub struct TraceIteration {
|
pub struct TraceIteration {
|
||||||
index: uint,
|
index: usize,
|
||||||
op_count: uint,
|
op_count: usize,
|
||||||
opcode: allops::Opcode,
|
opcode: allops::Opcode,
|
||||||
executed: bool,
|
executed: bool,
|
||||||
errored: bool,
|
errored: bool,
|
||||||
|
@ -1228,7 +1228,7 @@ pub struct ScriptTrace {
|
||||||
pub error: Option<ScriptError>
|
pub error: Option<ScriptError>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_json!(TraceIteration, index, opcode, op_count, executed, errored, effect, stack)
|
impl_json!(TraceIteration, index, opcode, op_count, executed, errored, effect, stack);
|
||||||
|
|
||||||
/// Hashtype of a transaction, encoded in the last byte of a signature,
|
/// Hashtype of a transaction, encoded in the last byte of a signature,
|
||||||
/// specifically in the last 5 bits `byte & 31`
|
/// specifically in the last 5 bits `byte & 31`
|
||||||
|
@ -1269,7 +1269,7 @@ pub enum MaybeOwned<'a> {
|
||||||
/// Freshly allocated memory
|
/// Freshly allocated memory
|
||||||
Owned(Vec<u8>),
|
Owned(Vec<u8>),
|
||||||
/// Pointer into the original script
|
/// Pointer into the original script
|
||||||
Slice(&'a [u8])
|
Borrowed(&'a [u8])
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PartialEq for MaybeOwned<'a> {
|
impl<'a> PartialEq for MaybeOwned<'a> {
|
||||||
|
@ -1284,17 +1284,17 @@ impl<'a> Slice<u8> for MaybeOwned<'a> {
|
||||||
fn as_slice<'a>(&'a self) -> &'a [u8] {
|
fn as_slice<'a>(&'a self) -> &'a [u8] {
|
||||||
match *self {
|
match *self {
|
||||||
Owned(ref v) => v.as_slice(),
|
Owned(ref v) => v.as_slice(),
|
||||||
Slice(ref s) => s.as_slice()
|
Borrowed(ref s) => s.as_slice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Collection for MaybeOwned<'a> {
|
impl<'a> Collection for MaybeOwned<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn len(&self) -> uint {
|
fn len(&self) -> usize {
|
||||||
match *self {
|
match *self {
|
||||||
Owned(ref v) => v.len(),
|
Owned(ref v) => v.len(),
|
||||||
Slice(ref s) => s.len()
|
Borrowed(ref s) => s.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1308,7 +1308,7 @@ fn build_scriptint(n: i64) -> Vec<u8> {
|
||||||
|
|
||||||
let neg = n < 0;
|
let neg = n < 0;
|
||||||
|
|
||||||
let mut abs = if neg { -n } else { n } as uint;
|
let mut abs = if neg { -n } else { n } as usize;
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
while abs > 0xFF {
|
while abs > 0xFF {
|
||||||
v.push((abs & 0xFF) as u8);
|
v.push((abs & 0xFF) as u8);
|
||||||
|
@ -1348,7 +1348,7 @@ pub fn read_scriptint(v: &[u8]) -> Result<i64, ScriptError> {
|
||||||
if len > 4 { return Err(NumericOverflow); }
|
if len > 4 { return Err(NumericOverflow); }
|
||||||
|
|
||||||
let (mut ret, sh) = v.iter()
|
let (mut ret, sh) = v.iter()
|
||||||
.fold((0, 0), |(acc, sh), n| (acc + (*n as i64 << sh), sh + 8));
|
.fold((0, 0), |(acc, sh), n| (acc + ((*n as i64) << sh), sh + 8));
|
||||||
if v[len - 1] & 0x80 != 0 {
|
if v[len - 1] & 0x80 != 0 {
|
||||||
ret &= (1 << sh - 1) - 1;
|
ret &= (1 << sh - 1) - 1;
|
||||||
ret = -ret;
|
ret = -ret;
|
||||||
|
@ -1366,12 +1366,12 @@ pub fn read_scriptbool(v: &[u8]) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a script-encoded unsigned integer
|
/// Read a script-encoded unsigned integer
|
||||||
pub fn read_uint<'a, I:Iterator<&'a u8>>(mut iter: I, size: uint)
|
pub fn read_uint<'a, I:Iterator<&'a u8>>(mut iter: I, size: usize)
|
||||||
-> Result<uint, ScriptError> {
|
-> Result<usize, ScriptError> {
|
||||||
let mut ret = 0;
|
let mut ret = 0;
|
||||||
for i in range(0, size) {
|
for i in range(0, size) {
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
Some(&n) => ret += n as uint << (i * 8),
|
Some(&n) => ret += (n as usize) << (i * 8),
|
||||||
None => { return Err(EarlyEndOfScript); }
|
None => { return Err(EarlyEndOfScript); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1381,7 +1381,7 @@ pub fn read_uint<'a, I:Iterator<&'a u8>>(mut iter: I, size: uint)
|
||||||
/// Check a signature -- returns an error that is currently just translated
|
/// Check a signature -- returns an error that is currently just translated
|
||||||
/// into a 0/1 to push onto the script stack
|
/// into a 0/1 to push onto the script stack
|
||||||
fn check_signature(sig_slice: &[u8], pk_slice: &[u8], script: Vec<u8>,
|
fn check_signature(sig_slice: &[u8], pk_slice: &[u8], script: Vec<u8>,
|
||||||
tx: &Transaction, input_index: uint) -> Result<(), ScriptError> {
|
tx: &Transaction, input_index: usize) -> Result<(), ScriptError> {
|
||||||
|
|
||||||
// Check public key
|
// Check public key
|
||||||
let pubkey = PublicKey::from_slice(pk_slice);
|
let pubkey = PublicKey::from_slice(pk_slice);
|
||||||
|
@ -1478,13 +1478,13 @@ fn check_signature(sig_slice: &[u8], pk_slice: &[u8], script: Vec<u8>,
|
||||||
// were really hard to read and verify -- see OP_PICK and OP_ROLL
|
// were really hard to read and verify -- see OP_PICK and OP_ROLL
|
||||||
// for an example of what Rust vector-stack manipulation looks
|
// for an example of what Rust vector-stack manipulation looks
|
||||||
// like.
|
// like.
|
||||||
macro_rules! stack_opcode(
|
macro_rules! stack_opcode {
|
||||||
($stack:ident($min:expr):
|
($stack:ident($min:expr):
|
||||||
$(require $r:expr)*
|
$(require $r:expr);*
|
||||||
$(copy $c:expr)*
|
$(copy $c:expr);*
|
||||||
$(swap ($a:expr, $b:expr))*
|
$(swap ($a:expr, $b:expr));*
|
||||||
$(perm ($first:expr $(->$i:expr)*) )*
|
$(perm ($first:expr, $($i:expr),*) );*
|
||||||
$(drop $d:expr)*
|
$(drop $d:expr);*
|
||||||
) => ({
|
) => ({
|
||||||
$( $stack.require_n_elems($r); )*
|
$( $stack.require_n_elems($r); )*
|
||||||
// Record top
|
// Record top
|
||||||
|
@ -1502,10 +1502,10 @@ macro_rules! stack_opcode(
|
||||||
// Do drops last so that dropped values will be available above
|
// Do drops last so that dropped values will be available above
|
||||||
$( $stack.remove(top - $d); )*
|
$( $stack.remove(top - $d); )*
|
||||||
});
|
});
|
||||||
)
|
}
|
||||||
|
|
||||||
/// Macro to translate numerical operations into stack ones
|
/// Macro to translate numerical operations into stack ones
|
||||||
macro_rules! num_opcode(
|
macro_rules! num_opcode {
|
||||||
($stack:ident($($var:ident),*): $op:expr) => ({
|
($stack:ident($($var:ident),*): $op:expr) => ({
|
||||||
$(
|
$(
|
||||||
let $var = try!(read_scriptint(match $stack.pop() {
|
let $var = try!(read_scriptint(match $stack.pop() {
|
||||||
|
@ -1517,9 +1517,9 @@ macro_rules! num_opcode(
|
||||||
// Return a tuple of all the variables
|
// Return a tuple of all the variables
|
||||||
($( $var ),*)
|
($( $var ),*)
|
||||||
});
|
});
|
||||||
)
|
}
|
||||||
|
|
||||||
macro_rules! unary_opcode_satisfy(
|
macro_rules! unary_opcode_satisfy {
|
||||||
($stack:ident, $op:ident) => ({
|
($stack:ident, $op:ident) => ({
|
||||||
let one = $stack.pop();
|
let one = $stack.pop();
|
||||||
let cond = $stack.push_alloc(AbstractStackElem::new_unknown());
|
let cond = $stack.push_alloc(AbstractStackElem::new_unknown());
|
||||||
|
@ -1527,9 +1527,9 @@ macro_rules! unary_opcode_satisfy(
|
||||||
check: concat_idents!(check_, $op),
|
check: concat_idents!(check_, $op),
|
||||||
update: concat_idents!(update_, $op) }));
|
update: concat_idents!(update_, $op) }));
|
||||||
})
|
})
|
||||||
)
|
}
|
||||||
|
|
||||||
macro_rules! boolean_opcode_satisfy(
|
macro_rules! boolean_opcode_satisfy {
|
||||||
($stack:ident, unary $op:ident) => ({
|
($stack:ident, unary $op:ident) => ({
|
||||||
let one = $stack.pop();
|
let one = $stack.pop();
|
||||||
let cond = $stack.push_alloc(AbstractStackElem::new_unknown());
|
let cond = $stack.push_alloc(AbstractStackElem::new_unknown());
|
||||||
|
@ -1557,10 +1557,10 @@ macro_rules! boolean_opcode_satisfy(
|
||||||
check: concat_idents!(check_, $op),
|
check: concat_idents!(check_, $op),
|
||||||
update: concat_idents!(update_, $op) }));
|
update: concat_idents!(update_, $op) }));
|
||||||
});
|
});
|
||||||
)
|
}
|
||||||
|
|
||||||
/// Macro to translate hashing operations into stack ones
|
/// Macro to translate hashing operations into stack ones
|
||||||
macro_rules! hash_opcode(
|
macro_rules! hash_opcode {
|
||||||
($stack:ident, $hash:ident) => ({
|
($stack:ident, $hash:ident) => ({
|
||||||
match $stack.pop() {
|
match $stack.pop() {
|
||||||
None => { return Err(PopEmptyStack); }
|
None => { return Err(PopEmptyStack); }
|
||||||
|
@ -1576,10 +1576,10 @@ macro_rules! hash_opcode(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
)
|
}
|
||||||
|
|
||||||
// OP_VERIFY macro
|
// OP_VERIFY macro
|
||||||
macro_rules! op_verify (
|
macro_rules! op_verify {
|
||||||
($stack:expr, $err:expr) => (
|
($stack:expr, $err:expr) => (
|
||||||
match $stack.last().map(|v| read_scriptbool(v.as_slice())) {
|
match $stack.last().map(|v| read_scriptbool(v.as_slice())) {
|
||||||
None => { return Err(VerifyEmptyStack); }
|
None => { return Err(VerifyEmptyStack); }
|
||||||
|
@ -1587,14 +1587,14 @@ macro_rules! op_verify (
|
||||||
Some(true) => { $stack.pop(); }
|
Some(true) => { $stack.pop(); }
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
|
|
||||||
macro_rules! op_verify_satisfy (
|
macro_rules! op_verify_satisfy {
|
||||||
($stack:expr) => ({
|
($stack:expr) => ({
|
||||||
try!($stack.peek_mut().set_bool_value(true));
|
try!($stack.peek_mut().set_bool_value(true));
|
||||||
$stack.pop();
|
$stack.pop();
|
||||||
})
|
})
|
||||||
)
|
}
|
||||||
|
|
||||||
impl Script {
|
impl Script {
|
||||||
/// Creates a new empty script
|
/// Creates a new empty script
|
||||||
|
@ -1604,7 +1604,7 @@ impl Script {
|
||||||
pub fn from_vec(v: Vec<u8>) -> Script { Script(ThinVec::from_vec(v)) }
|
pub fn from_vec(v: Vec<u8>) -> Script { Script(ThinVec::from_vec(v)) }
|
||||||
|
|
||||||
/// The length in bytes of the script
|
/// The length in bytes of the script
|
||||||
pub fn len(&self) -> uint {
|
pub fn len(&self) -> usize {
|
||||||
let &Script(ref raw) = self;
|
let &Script(ref raw) = self;
|
||||||
raw.len()
|
raw.len()
|
||||||
}
|
}
|
||||||
|
@ -1640,7 +1640,7 @@ impl Script {
|
||||||
let &Script(ref mut raw) = self;
|
let &Script(ref mut raw) = self;
|
||||||
// Start with a PUSH opcode
|
// Start with a PUSH opcode
|
||||||
match data.len() {
|
match data.len() {
|
||||||
n if n < opcodes::OP_PUSHDATA1 as uint => { raw.push(n as u8); },
|
n if n < opcodes::OP_PUSHDATA1 as usize => { raw.push(n as u8); },
|
||||||
n if n < 0x100 => {
|
n if n < 0x100 => {
|
||||||
raw.push(opcodes::OP_PUSHDATA1 as u8);
|
raw.push(opcodes::OP_PUSHDATA1 as u8);
|
||||||
raw.push(n as u8);
|
raw.push(n as u8);
|
||||||
|
@ -1657,7 +1657,7 @@ impl Script {
|
||||||
raw.push(((n / 0x10000) % 0x100) as u8);
|
raw.push(((n / 0x10000) % 0x100) as u8);
|
||||||
raw.push((n / 0x1000000) as u8);
|
raw.push((n / 0x1000000) as u8);
|
||||||
}
|
}
|
||||||
_ => fail!("tried to put a 4bn+ sized object into a script!")
|
_ => panic!("tried to put a 4bn+ sized object into a script!")
|
||||||
}
|
}
|
||||||
// Then push the acraw
|
// Then push the acraw
|
||||||
raw.extend(data.iter().map(|n| *n));
|
raw.extend(data.iter().map(|n| *n));
|
||||||
|
@ -1676,26 +1676,26 @@ impl Script {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a view into the script as a slice
|
/// Returns a view into the script as a slice
|
||||||
pub fn slice_to(&self, n: uint) -> &[u8] {
|
pub fn slice_to(&self, n: usize) -> &[u8] {
|
||||||
let &Script(ref raw) = self;
|
let &Script(ref raw) = self;
|
||||||
raw.slice_to(n)
|
raw.slice_to(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a view into the script as a slice
|
/// Returns a view into the script as a slice
|
||||||
pub fn slice_from(&self, n: uint) -> &[u8] {
|
pub fn slice_from(&self, n: usize) -> &[u8] {
|
||||||
let &Script(ref raw) = self;
|
let &Script(ref raw) = self;
|
||||||
raw.slice_from(n)
|
raw.slice_from(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a view into the script as a slice
|
/// Returns a view into the script as a slice
|
||||||
pub fn slice(&self, s: uint, e: uint) -> &[u8] {
|
pub fn slice(&self, s: usize, e: usize) -> &[u8] {
|
||||||
let &Script(ref raw) = self;
|
let &Script(ref raw) = self;
|
||||||
raw.slice(s, e)
|
raw.slice(s, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trace a script
|
/// Trace a script
|
||||||
pub fn trace<'a>(&'a self, stack: &mut Vec<MaybeOwned<'a>>,
|
pub fn trace<'a>(&'a self, stack: &mut Vec<MaybeOwned<'a>>,
|
||||||
input_context: Option<(&Transaction, uint)>)
|
input_context: Option<(&Transaction, usize)>)
|
||||||
-> ScriptTrace {
|
-> ScriptTrace {
|
||||||
let mut trace = ScriptTrace {
|
let mut trace = ScriptTrace {
|
||||||
script: self.clone(),
|
script: self.clone(),
|
||||||
|
@ -1713,12 +1713,12 @@ impl Script {
|
||||||
|
|
||||||
/// Evaluate the script, modifying the stack in place
|
/// Evaluate the script, modifying the stack in place
|
||||||
pub fn evaluate<'a>(&'a self, stack: &mut Vec<MaybeOwned<'a>>,
|
pub fn evaluate<'a>(&'a self, stack: &mut Vec<MaybeOwned<'a>>,
|
||||||
input_context: Option<(&Transaction, uint)>,
|
input_context: Option<(&Transaction, usize)>,
|
||||||
mut trace: Option<&mut Vec<TraceIteration>>)
|
mut trace: Option<&mut Vec<TraceIteration>>)
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
let &Script(ref raw) = self;
|
let &Script(ref raw) = self;
|
||||||
|
|
||||||
let mut codeseparator_index = 0u;
|
let mut codeseparator_index = 0;
|
||||||
let mut exec_stack = vec![];
|
let mut exec_stack = vec![];
|
||||||
let mut alt_stack = vec![];
|
let mut alt_stack = vec![];
|
||||||
|
|
||||||
|
@ -1757,35 +1757,35 @@ impl Script {
|
||||||
// Data-reading statements still need to read, even when not executing
|
// Data-reading statements still need to read, even when not executing
|
||||||
(_, opcodes::PushBytes(n)) => {
|
(_, opcodes::PushBytes(n)) => {
|
||||||
if raw.len() < index + n { return Err(EarlyEndOfScript); }
|
if raw.len() < index + n { return Err(EarlyEndOfScript); }
|
||||||
if executing { stack.push(Slice(raw.slice(index, index + n))); }
|
if executing { stack.push(Borrowed(raw.slice(index, index + n))); }
|
||||||
index += n;
|
index += n;
|
||||||
}
|
}
|
||||||
(_, opcodes::Ordinary(opcodes::OP_PUSHDATA1)) => {
|
(_, opcodes::Ordinary(opcodes::OP_PUSHDATA1)) => {
|
||||||
if raw.len() < index + 1 { return Err(EarlyEndOfScript); }
|
if raw.len() < index + 1 { return Err(EarlyEndOfScript); }
|
||||||
let n = try!(read_uint(raw.slice_from(index).iter(), 1));
|
let n = try!(read_uint(raw.slice_from(index).iter(), 1));
|
||||||
if raw.len() < index + 1 + n { return Err(EarlyEndOfScript); }
|
if raw.len() < index + 1 + n { return Err(EarlyEndOfScript); }
|
||||||
if executing { stack.push(Slice(raw.slice(index + 1, index + n + 1))); }
|
if executing { stack.push(Borrowed(raw.slice(index + 1, index + n + 1))); }
|
||||||
index += 1 + n;
|
index += 1 + n;
|
||||||
}
|
}
|
||||||
(_, opcodes::Ordinary(opcodes::OP_PUSHDATA2)) => {
|
(_, opcodes::Ordinary(opcodes::OP_PUSHDATA2)) => {
|
||||||
if raw.len() < index + 2 { return Err(EarlyEndOfScript); }
|
if raw.len() < index + 2 { return Err(EarlyEndOfScript); }
|
||||||
let n = try!(read_uint(raw.slice_from(index).iter(), 2));
|
let n = try!(read_uint(raw.slice_from(index).iter(), 2));
|
||||||
if raw.len() < index + 2 + n { return Err(EarlyEndOfScript); }
|
if raw.len() < index + 2 + n { return Err(EarlyEndOfScript); }
|
||||||
if executing { stack.push(Slice(raw.slice(index + 2, index + n + 2))); }
|
if executing { stack.push(Borrowed(raw.slice(index + 2, index + n + 2))); }
|
||||||
index += 2 + n;
|
index += 2 + n;
|
||||||
}
|
}
|
||||||
(_, opcodes::Ordinary(opcodes::OP_PUSHDATA4)) => {
|
(_, opcodes::Ordinary(opcodes::OP_PUSHDATA4)) => {
|
||||||
if raw.len() < index + 4 { return Err(EarlyEndOfScript); }
|
if raw.len() < index + 4 { return Err(EarlyEndOfScript); }
|
||||||
let n = try!(read_uint(raw.slice_from(index).iter(), 4));
|
let n = try!(read_uint(raw.slice_from(index).iter(), 4));
|
||||||
if raw.len() < index + 4 + n { return Err(EarlyEndOfScript); }
|
if raw.len() < index + 4 + n { return Err(EarlyEndOfScript); }
|
||||||
if executing { stack.push(Slice(raw.slice(index + 4, index + n + 4))); }
|
if executing { stack.push(Borrowed(raw.slice(index + 4, index + n + 4))); }
|
||||||
index += 4 + n;
|
index += 4 + n;
|
||||||
}
|
}
|
||||||
// If-statements take effect when not executing
|
// If-statements take effect when not executing
|
||||||
(false, opcodes::Ordinary(opcodes::OP_IF)) => exec_stack.push(false),
|
(false, opcodes::Ordinary(opcodes::OP_IF)) => exec_stack.push(false),
|
||||||
(false, opcodes::Ordinary(opcodes::OP_NOTIF)) => exec_stack.push(false),
|
(false, opcodes::Ordinary(opcodes::OP_NOTIF)) => exec_stack.push(false),
|
||||||
(false, opcodes::Ordinary(opcodes::OP_ELSE)) => {
|
(false, opcodes::Ordinary(opcodes::OP_ELSE)) => {
|
||||||
match exec_stack.mut_last() {
|
match exec_stack.last_mut() {
|
||||||
Some(ref_e) => { *ref_e = !*ref_e }
|
Some(ref_e) => { *ref_e = !*ref_e }
|
||||||
None => { return Err(ElseWithoutIf); }
|
None => { return Err(ElseWithoutIf); }
|
||||||
}
|
}
|
||||||
|
@ -1816,7 +1816,7 @@ impl Script {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opcodes::OP_ELSE => {
|
opcodes::OP_ELSE => {
|
||||||
match exec_stack.mut_last() {
|
match exec_stack.last_mut() {
|
||||||
Some(ref_e) => { *ref_e = !*ref_e }
|
Some(ref_e) => { *ref_e = !*ref_e }
|
||||||
None => { return Err(ElseWithoutIf); }
|
None => { return Err(ElseWithoutIf); }
|
||||||
}
|
}
|
||||||
|
@ -1839,13 +1839,13 @@ impl Script {
|
||||||
Some(elem) => { stack.push(elem); }
|
Some(elem) => { stack.push(elem); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opcodes::OP_2DROP => stack_opcode!(stack(2): drop 1 drop 2),
|
opcodes::OP_2DROP => stack_opcode!(stack(2): drop 1; drop 2),
|
||||||
opcodes::OP_2DUP => stack_opcode!(stack(2): copy 2 copy 1),
|
opcodes::OP_2DUP => stack_opcode!(stack(2): copy 2; copy 1),
|
||||||
opcodes::OP_3DUP => stack_opcode!(stack(3): copy 3 copy 2 copy 1),
|
opcodes::OP_3DUP => stack_opcode!(stack(3): copy 3; copy 2; copy 1),
|
||||||
opcodes::OP_2OVER => stack_opcode!(stack(4): copy 4 copy 3),
|
opcodes::OP_2OVER => stack_opcode!(stack(4): copy 4; copy 3),
|
||||||
opcodes::OP_2ROT => stack_opcode!(stack(6): perm (1 -> 3 -> 5)
|
opcodes::OP_2ROT => stack_opcode!(stack(6): perm (1, 3, 5);
|
||||||
perm (2 -> 4 -> 6)),
|
perm (2, 4, 6)),
|
||||||
opcodes::OP_2SWAP => stack_opcode!(stack(4): swap (2, 4) swap (1, 3)),
|
opcodes::OP_2SWAP => stack_opcode!(stack(4): swap (2, 4); swap (1, 3)),
|
||||||
opcodes::OP_DROP => stack_opcode!(stack(1): drop 1),
|
opcodes::OP_DROP => stack_opcode!(stack(1): drop 1),
|
||||||
opcodes::OP_DUP => stack_opcode!(stack(1): copy 1),
|
opcodes::OP_DUP => stack_opcode!(stack(1): copy 1),
|
||||||
opcodes::OP_NIP => stack_opcode!(stack(2): drop 2),
|
opcodes::OP_NIP => stack_opcode!(stack(2): drop 2),
|
||||||
|
@ -1856,7 +1856,7 @@ impl Script {
|
||||||
None => { return Err(PopEmptyStack); }
|
None => { return Err(PopEmptyStack); }
|
||||||
};
|
};
|
||||||
if n < 0 { return Err(NegativePick); }
|
if n < 0 { return Err(NegativePick); }
|
||||||
let n = n as uint;
|
let n = n as usize;
|
||||||
stack_opcode!(stack(n + 1): copy n + 1)
|
stack_opcode!(stack(n + 1): copy n + 1)
|
||||||
}
|
}
|
||||||
opcodes::OP_ROLL => {
|
opcodes::OP_ROLL => {
|
||||||
|
@ -1865,12 +1865,12 @@ impl Script {
|
||||||
None => { return Err(PopEmptyStack); }
|
None => { return Err(PopEmptyStack); }
|
||||||
};
|
};
|
||||||
if n < 0 { return Err(NegativeRoll); }
|
if n < 0 { return Err(NegativeRoll); }
|
||||||
let n = n as uint;
|
let n = n as usize;
|
||||||
stack_opcode!(stack(n + 1): copy n + 1 drop n + 1)
|
stack_opcode!(stack(n + 1): copy n + 1 drop n + 1)
|
||||||
}
|
}
|
||||||
opcodes::OP_ROT => stack_opcode!(stack(3): perm (1 -> 2 -> 3)),
|
opcodes::OP_ROT => stack_opcode!(stack(3): perm (1, 2, 3)),
|
||||||
opcodes::OP_SWAP => stack_opcode!(stack(2): swap (1, 2)),
|
opcodes::OP_SWAP => stack_opcode!(stack(2): swap (1, 2)),
|
||||||
opcodes::OP_TUCK => stack_opcode!(stack(2): copy 2 copy 1 drop 2),
|
opcodes::OP_TUCK => stack_opcode!(stack(2): copy 2; copy 1 drop 2),
|
||||||
opcodes::OP_IFDUP => {
|
opcodes::OP_IFDUP => {
|
||||||
match stack.last().map(|v| read_scriptbool(v.as_slice())) {
|
match stack.last().map(|v| read_scriptbool(v.as_slice())) {
|
||||||
None => { return Err(IfEmptyStack); }
|
None => { return Err(IfEmptyStack); }
|
||||||
|
@ -1892,7 +1892,7 @@ impl Script {
|
||||||
if stack.len() < 2 { return Err(PopEmptyStack); }
|
if stack.len() < 2 { return Err(PopEmptyStack); }
|
||||||
let a = stack.pop().unwrap();
|
let a = stack.pop().unwrap();
|
||||||
let b = stack.pop().unwrap();
|
let b = stack.pop().unwrap();
|
||||||
stack.push(Slice(if a == b { SCRIPT_TRUE } else { SCRIPT_FALSE }));
|
stack.push(Borrowed(if a == b { SCRIPT_TRUE } else { SCRIPT_FALSE }));
|
||||||
if op == opcodes::OP_EQUALVERIFY {
|
if op == opcodes::OP_EQUALVERIFY {
|
||||||
op_verify!(stack, EqualVerifyFailed(a.as_slice().to_hex(),
|
op_verify!(stack, EqualVerifyFailed(a.as_slice().to_hex(),
|
||||||
b.as_slice().to_hex()));
|
b.as_slice().to_hex()));
|
||||||
|
@ -1943,7 +1943,7 @@ impl Script {
|
||||||
|
|
||||||
// Compute the section of script that needs to be hashed: everything
|
// Compute the section of script that needs to be hashed: everything
|
||||||
// from the last CODESEPARATOR, except the signature itself.
|
// from the last CODESEPARATOR, except the signature itself.
|
||||||
let mut script = Vec::from_slice(raw.slice_from(codeseparator_index));
|
let mut script = raw.slice_from(codeseparator_index).to_vec();
|
||||||
let mut remove = Script::new();
|
let mut remove = Script::new();
|
||||||
remove.push_slice(sig_slice);
|
remove.push_slice(sig_slice);
|
||||||
script_find_and_remove(&mut script, remove.as_slice());
|
script_find_and_remove(&mut script, remove.as_slice());
|
||||||
|
@ -1955,8 +1955,8 @@ impl Script {
|
||||||
let (tx, input_index) = input_context.unwrap();
|
let (tx, input_index) = input_context.unwrap();
|
||||||
|
|
||||||
match check_signature( sig_slice, pk_slice, script, tx, input_index) {
|
match check_signature( sig_slice, pk_slice, script, tx, input_index) {
|
||||||
Ok(()) => stack.push(Slice(SCRIPT_TRUE)),
|
Ok(()) => stack.push(Borrowed(SCRIPT_TRUE)),
|
||||||
_ => stack.push(Slice(SCRIPT_FALSE)),
|
_ => stack.push(Borrowed(SCRIPT_FALSE)),
|
||||||
}
|
}
|
||||||
if op == opcodes::OP_CHECKSIGVERIFY { op_verify!(stack, VerifyFailed); }
|
if op == opcodes::OP_CHECKSIGVERIFY { op_verify!(stack, VerifyFailed); }
|
||||||
}
|
}
|
||||||
|
@ -1965,11 +1965,11 @@ impl Script {
|
||||||
if stack.len() < 1 { return Err(PopEmptyStack); }
|
if stack.len() < 1 { return Err(PopEmptyStack); }
|
||||||
let n_keys = try!(read_scriptint(stack.pop().unwrap().as_slice()));
|
let n_keys = try!(read_scriptint(stack.pop().unwrap().as_slice()));
|
||||||
if n_keys < 0 || n_keys > 20 {
|
if n_keys < 0 || n_keys > 20 {
|
||||||
return Err(MultisigBadKeyCount(n_keys as int));
|
return Err(MultisigBadKeyCount(n_keys as isize));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack.len() as i64) < n_keys { return Err(PopEmptyStack); }
|
if (stack.len() as i64) < n_keys { return Err(PopEmptyStack); }
|
||||||
let mut keys = Vec::with_capacity(n_keys as uint);
|
let mut keys = Vec::with_capacity(n_keys as usize);
|
||||||
for _ in range(0, n_keys) {
|
for _ in range(0, n_keys) {
|
||||||
keys.push(stack.pop().unwrap());
|
keys.push(stack.pop().unwrap());
|
||||||
}
|
}
|
||||||
|
@ -1978,11 +1978,11 @@ impl Script {
|
||||||
if stack.len() < 1 { return Err(PopEmptyStack); }
|
if stack.len() < 1 { return Err(PopEmptyStack); }
|
||||||
let n_sigs = try!(read_scriptint(stack.pop().unwrap().as_slice()));
|
let n_sigs = try!(read_scriptint(stack.pop().unwrap().as_slice()));
|
||||||
if n_sigs < 0 || n_sigs > n_keys {
|
if n_sigs < 0 || n_sigs > n_keys {
|
||||||
return Err(MultisigBadSigCount(n_sigs as int));
|
return Err(MultisigBadSigCount(n_sigs as isize));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack.len() as i64) < n_sigs { return Err(PopEmptyStack); }
|
if (stack.len() as i64) < n_sigs { return Err(PopEmptyStack); }
|
||||||
let mut sigs = Vec::with_capacity(n_sigs as uint);
|
let mut sigs = Vec::with_capacity(n_sigs as usize);
|
||||||
for _ in range(0, n_sigs) {
|
for _ in range(0, n_sigs) {
|
||||||
sigs.push(stack.pop().unwrap());
|
sigs.push(stack.pop().unwrap());
|
||||||
}
|
}
|
||||||
|
@ -1992,7 +1992,7 @@ impl Script {
|
||||||
|
|
||||||
// Compute the section of script that needs to be hashed: everything
|
// Compute the section of script that needs to be hashed: everything
|
||||||
// from the last CODESEPARATOR, except the signatures themselves.
|
// from the last CODESEPARATOR, except the signatures themselves.
|
||||||
let mut script = Vec::from_slice(raw.slice_from(codeseparator_index));
|
let mut script = raw.slice_from(codeseparator_index).to_vec();
|
||||||
for sig in sigs.iter() {
|
for sig in sigs.iter() {
|
||||||
let mut remove = Script::new();
|
let mut remove = Script::new();
|
||||||
remove.push_slice(sig.as_slice());
|
remove.push_slice(sig.as_slice());
|
||||||
|
@ -2024,12 +2024,12 @@ impl Script {
|
||||||
}
|
}
|
||||||
// Run out of signatures, success
|
// Run out of signatures, success
|
||||||
(_, None) => {
|
(_, None) => {
|
||||||
stack.push(Slice(SCRIPT_TRUE));
|
stack.push(Borrowed(SCRIPT_TRUE));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Run out of keys to match to signatures, fail
|
// Run out of keys to match to signatures, fail
|
||||||
(None, Some(_)) => {
|
(None, Some(_)) => {
|
||||||
stack.push(Slice(SCRIPT_FALSE));
|
stack.push(Borrowed(SCRIPT_FALSE));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2041,7 +2041,7 @@ impl Script {
|
||||||
} // end loop
|
} // end loop
|
||||||
// Store the stack in the trace
|
// Store the stack in the trace
|
||||||
trace.as_mut().map(|t|
|
trace.as_mut().map(|t|
|
||||||
t.mut_last().map(|t| {
|
t.last_mut().map(|t| {
|
||||||
t.errored = false;
|
t.errored = false;
|
||||||
t.stack = stack.iter().map(|elem| elem.as_slice().to_hex()).collect();
|
t.stack = stack.iter().map(|elem| elem.as_slice().to_hex()).collect();
|
||||||
})
|
})
|
||||||
|
@ -2077,7 +2077,7 @@ impl Script {
|
||||||
fn recurse<'a>(script: &'a [u8],
|
fn recurse<'a>(script: &'a [u8],
|
||||||
mut stack: AbstractStack,
|
mut stack: AbstractStack,
|
||||||
mut exec_stack: Vec<bool>,
|
mut exec_stack: Vec<bool>,
|
||||||
depth: uint) -> Result<Vec<AbstractStackElem>, ScriptError> {
|
depth: usize) -> Result<Vec<AbstractStackElem>, ScriptError> {
|
||||||
|
|
||||||
// Avoid doing more than 64k forks
|
// Avoid doing more than 64k forks
|
||||||
if depth > 16 { return Err(InterpreterStackOverflow); }
|
if depth > 16 { return Err(InterpreterStackOverflow); }
|
||||||
|
@ -2143,7 +2143,7 @@ impl Script {
|
||||||
(false, opcodes::Ordinary(opcodes::OP_IF)) => exec_stack.push(false),
|
(false, opcodes::Ordinary(opcodes::OP_IF)) => exec_stack.push(false),
|
||||||
(false, opcodes::Ordinary(opcodes::OP_NOTIF)) => exec_stack.push(false),
|
(false, opcodes::Ordinary(opcodes::OP_NOTIF)) => exec_stack.push(false),
|
||||||
(false, opcodes::Ordinary(opcodes::OP_ELSE)) => {
|
(false, opcodes::Ordinary(opcodes::OP_ELSE)) => {
|
||||||
match exec_stack.mut_last() {
|
match exec_stack.last_mut() {
|
||||||
Some(ref_e) => { *ref_e = !*ref_e }
|
Some(ref_e) => { *ref_e = !*ref_e }
|
||||||
None => { return Err(ElseWithoutIf); }
|
None => { return Err(ElseWithoutIf); }
|
||||||
}
|
}
|
||||||
|
@ -2212,7 +2212,7 @@ impl Script {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opcodes::OP_ELSE => {
|
opcodes::OP_ELSE => {
|
||||||
match exec_stack.mut_last() {
|
match exec_stack.last_mut() {
|
||||||
Some(ref_e) => { *ref_e = !*ref_e }
|
Some(ref_e) => { *ref_e = !*ref_e }
|
||||||
None => { return Err(ElseWithoutIf); }
|
None => { return Err(ElseWithoutIf); }
|
||||||
}
|
}
|
||||||
|
@ -2225,15 +2225,15 @@ impl Script {
|
||||||
opcodes::OP_VERIFY => op_verify_satisfy!(stack),
|
opcodes::OP_VERIFY => op_verify_satisfy!(stack),
|
||||||
opcodes::OP_TOALTSTACK => { stack.to_altstack(); }
|
opcodes::OP_TOALTSTACK => { stack.to_altstack(); }
|
||||||
opcodes::OP_FROMALTSTACK => { try!(stack.from_altstack()); }
|
opcodes::OP_FROMALTSTACK => { try!(stack.from_altstack()); }
|
||||||
opcodes::OP_2DROP => stack_opcode!(stack(2): require 2 drop 1 drop 2),
|
opcodes::OP_2DROP => stack_opcode!(stack(2): require 2 drop 1; drop 2),
|
||||||
opcodes::OP_2DUP => stack_opcode!(stack(2): require 2 copy 2 copy 1),
|
opcodes::OP_2DUP => stack_opcode!(stack(2): require 2 copy 2; copy 1),
|
||||||
opcodes::OP_3DUP => stack_opcode!(stack(3): require 3 copy 3 copy 2 copy 1),
|
opcodes::OP_3DUP => stack_opcode!(stack(3): require 3 copy 3; copy 2; copy 1),
|
||||||
opcodes::OP_2OVER => stack_opcode!(stack(4): require 4 copy 4 copy 3),
|
opcodes::OP_2OVER => stack_opcode!(stack(4): require 4 copy 4; copy 3),
|
||||||
opcodes::OP_2ROT => stack_opcode!(stack(6): require 6
|
opcodes::OP_2ROT => stack_opcode!(stack(6): require 6
|
||||||
perm (1 -> 3 -> 5)
|
perm (1, 3, 5);
|
||||||
perm (2 -> 4 -> 6)),
|
perm (2, 4, 6)),
|
||||||
opcodes::OP_2SWAP => stack_opcode!(stack(4): require 4
|
opcodes::OP_2SWAP => stack_opcode!(stack(4): require 4
|
||||||
swap (2, 4)
|
swap (2, 4);
|
||||||
swap (1, 3)),
|
swap (1, 3)),
|
||||||
opcodes::OP_DROP => stack_opcode!(stack(1): require 1 drop 1),
|
opcodes::OP_DROP => stack_opcode!(stack(1): require 1 drop 1),
|
||||||
opcodes::OP_DUP => stack_opcode!(stack(1): require 1 copy 1),
|
opcodes::OP_DUP => stack_opcode!(stack(1): require 1 copy 1),
|
||||||
|
@ -2244,7 +2244,7 @@ impl Script {
|
||||||
let top = stack.peek_mut();
|
let top = stack.peek_mut();
|
||||||
try!(top.set_numeric());
|
try!(top.set_numeric());
|
||||||
try!(top.set_num_lo(0));
|
try!(top.set_num_lo(0));
|
||||||
top.num_value().map(|n| n as uint)
|
top.num_value().map(|n| n as usize)
|
||||||
};
|
};
|
||||||
stack.pop();
|
stack.pop();
|
||||||
match top_n {
|
match top_n {
|
||||||
|
@ -2262,7 +2262,7 @@ impl Script {
|
||||||
let top = stack.peek_mut();
|
let top = stack.peek_mut();
|
||||||
try!(top.set_numeric());
|
try!(top.set_numeric());
|
||||||
try!(top.set_num_lo(0));
|
try!(top.set_num_lo(0));
|
||||||
top.num_value().map(|n| n as uint)
|
top.num_value().map(|n| n as usize)
|
||||||
};
|
};
|
||||||
stack.pop();
|
stack.pop();
|
||||||
match top_n {
|
match top_n {
|
||||||
|
@ -2274,9 +2274,9 @@ impl Script {
|
||||||
None => { return Err(Unanalyzable); }
|
None => { return Err(Unanalyzable); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opcodes::OP_ROT => stack_opcode!(stack(3): require 3 perm (1 -> 2 -> 3)),
|
opcodes::OP_ROT => stack_opcode!(stack(3): require 3 perm (1, 2, 3)),
|
||||||
opcodes::OP_SWAP => stack_opcode!(stack(2): require 3 swap (1, 2)),
|
opcodes::OP_SWAP => stack_opcode!(stack(2): require 3 swap (1, 2)),
|
||||||
opcodes::OP_TUCK => stack_opcode!(stack(2): require 2 copy 2 copy 1 drop 2),
|
opcodes::OP_TUCK => stack_opcode!(stack(2): require 2 copy 2; copy 1 drop 2),
|
||||||
opcodes::OP_IFDUP => {
|
opcodes::OP_IFDUP => {
|
||||||
let top_bool = {
|
let top_bool = {
|
||||||
let top = stack.peek_mut();
|
let top = stack.peek_mut();
|
||||||
|
@ -2423,8 +2423,8 @@ impl json::ToJson for Script {
|
||||||
let &Script(ref raw) = self;
|
let &Script(ref raw) = self;
|
||||||
let mut ret = String::new();
|
let mut ret = String::new();
|
||||||
for dat in raw.iter() {
|
for dat in raw.iter() {
|
||||||
ret.push_char(from_digit((dat / 0x10) as uint, 16).unwrap());
|
ret.push_char(from_digit((dat / 0x10) as usize, 16).unwrap());
|
||||||
ret.push_char(from_digit((dat & 0x0f) as uint, 16).unwrap());
|
ret.push_char(from_digit((dat & 0x0f) as usize, 16).unwrap());
|
||||||
}
|
}
|
||||||
json::String(ret)
|
json::String(ret)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ use std::default::Default;
|
||||||
use serialize::json;
|
use serialize::json;
|
||||||
|
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
use blockdata::script::{mod, Script, ScriptError, ScriptTrace, read_scriptbool};
|
use blockdata::script::{self, Script, ScriptError, ScriptTrace, read_scriptbool};
|
||||||
use blockdata::utxoset::UtxoSet;
|
use blockdata::utxoset::UtxoSet;
|
||||||
use network::encodable::ConsensusEncodable;
|
use network::encodable::ConsensusEncodable;
|
||||||
use network::serialize::BitcoinHash;
|
use network::serialize::BitcoinHash;
|
||||||
|
@ -81,7 +81,7 @@ impl TxOut {
|
||||||
if self.script_pubkey.len() == 25 &&
|
if self.script_pubkey.len() == 25 &&
|
||||||
self.script_pubkey.slice_to(3) == &[0x76, 0xa9, 0x14] &&
|
self.script_pubkey.slice_to(3) == &[0x76, 0xa9, 0x14] &&
|
||||||
self.script_pubkey.slice_from(23) == &[0x88, 0xac] {
|
self.script_pubkey.slice_from(23) == &[0x88, 0xac] {
|
||||||
PayToPubkeyHash(Address::from_slice(network, self.script_pubkey.slice(3, 23)))
|
PayToPubkeyHash(self.script_pubkey.slice(3, 23).to_address(network))
|
||||||
} else {
|
} else {
|
||||||
Unknown
|
Unknown
|
||||||
}
|
}
|
||||||
|
@ -133,16 +133,16 @@ impl json::ToJson for TransactionError {
|
||||||
#[deriving(PartialEq, Eq, Clone, Show)]
|
#[deriving(PartialEq, Eq, Clone, Show)]
|
||||||
pub struct InputTrace {
|
pub struct InputTrace {
|
||||||
input_txid: Sha256dHash,
|
input_txid: Sha256dHash,
|
||||||
input_vout: uint,
|
input_vout: usize,
|
||||||
sig_trace: ScriptTrace,
|
sig_trace: ScriptTrace,
|
||||||
pubkey_trace: Option<ScriptTrace>,
|
pubkey_trace: Option<ScriptTrace>,
|
||||||
p2sh_trace: Option<ScriptTrace>,
|
p2sh_trace: Option<ScriptTrace>,
|
||||||
error: Option<TransactionError>
|
error: Option<TransactionError>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_json!(ScriptTrace, script, initial_stack, iterations, error)
|
impl_json!(ScriptTrace, script, initial_stack, iterations, error);
|
||||||
impl_json!(InputTrace, input_txid, input_vout, sig_trace,
|
impl_json!(InputTrace, input_txid, input_vout, sig_trace,
|
||||||
pubkey_trace, p2sh_trace, error)
|
pubkey_trace, p2sh_trace, error);
|
||||||
|
|
||||||
/// A trace of a transaction's execution
|
/// A trace of a transaction's execution
|
||||||
#[deriving(PartialEq, Eq, Clone, Show)]
|
#[deriving(PartialEq, Eq, Clone, Show)]
|
||||||
|
@ -151,14 +151,14 @@ pub struct TransactionTrace {
|
||||||
inputs: Vec<InputTrace>
|
inputs: Vec<InputTrace>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_json!(TransactionTrace, txid, inputs)
|
impl_json!(TransactionTrace, txid, inputs);
|
||||||
|
|
||||||
impl TxIn {
|
impl TxIn {
|
||||||
/// Check an input's script for validity
|
/// Check an input's script for validity
|
||||||
pub fn validate(&self,
|
pub fn validate(&self,
|
||||||
utxoset: &UtxoSet,
|
utxoset: &UtxoSet,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
index: uint) -> Result<(), TransactionError> {
|
index: usize) -> Result<(), TransactionError> {
|
||||||
let txo = utxoset.get_utxo(self.prev_hash, self.prev_index);
|
let txo = utxoset.get_utxo(self.prev_hash, self.prev_index);
|
||||||
match txo {
|
match txo {
|
||||||
Some((_, txo)) => {
|
Some((_, txo)) => {
|
||||||
|
@ -174,7 +174,7 @@ impl TxIn {
|
||||||
p2sh_stack = stack.clone();
|
p2sh_stack = stack.clone();
|
||||||
p2sh_script = match p2sh_stack.pop() {
|
p2sh_script = match p2sh_stack.pop() {
|
||||||
Some(script::Owned(v)) => Script::from_vec(v),
|
Some(script::Owned(v)) => Script::from_vec(v),
|
||||||
Some(script::Slice(s)) => Script::from_vec(Vec::from_slice(s)),
|
Some(script::Borrowed(s)) => Script::from_vec(s.to_vec()),
|
||||||
None => unreachable!()
|
None => unreachable!()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -228,7 +228,7 @@ impl Transaction {
|
||||||
// Setup trace
|
// Setup trace
|
||||||
let mut trace = InputTrace {
|
let mut trace = InputTrace {
|
||||||
input_txid: input.prev_hash,
|
input_txid: input.prev_hash,
|
||||||
input_vout: input.prev_index as uint,
|
input_vout: input.prev_index as usize,
|
||||||
sig_trace: ScriptTrace {
|
sig_trace: ScriptTrace {
|
||||||
script: Script::new(),
|
script: Script::new(),
|
||||||
initial_stack: vec![],
|
initial_stack: vec![],
|
||||||
|
@ -255,7 +255,7 @@ impl Transaction {
|
||||||
p2sh_stack = stack.clone();
|
p2sh_stack = stack.clone();
|
||||||
p2sh_script = match p2sh_stack.pop() {
|
p2sh_script = match p2sh_stack.pop() {
|
||||||
Some(script::Owned(v)) => Script::from_vec(v),
|
Some(script::Owned(v)) => Script::from_vec(v),
|
||||||
Some(script::Slice(s)) => Script::from_vec(Vec::from_slice(s)),
|
Some(script::Borrowed(s)) => Script::from_vec(s.to_vec()),
|
||||||
None => unreachable!()
|
None => unreachable!()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -303,12 +303,12 @@ impl BitcoinHash for Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_consensus_encoding!(TxIn, prev_hash, prev_index, script_sig, sequence)
|
impl_consensus_encoding!(TxIn, prev_hash, prev_index, script_sig, sequence);
|
||||||
impl_json!(TxIn, prev_hash, prev_index, script_sig, sequence)
|
impl_json!(TxIn, prev_hash, prev_index, script_sig, sequence);
|
||||||
impl_consensus_encoding!(TxOut, value, script_pubkey)
|
impl_consensus_encoding!(TxOut, value, script_pubkey);
|
||||||
impl_json!(TxOut, value, script_pubkey)
|
impl_json!(TxOut, value, script_pubkey);
|
||||||
impl_consensus_encoding!(Transaction, version, input, output, lock_time)
|
impl_consensus_encoding!(Transaction, version, input, output, lock_time);
|
||||||
impl_json!(Transaction, version, input, output, lock_time)
|
impl_json!(Transaction, version, input, output, lock_time);
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -65,27 +65,27 @@ struct UtxoNode {
|
||||||
/// 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: ThinVec<Option<TxOut>>
|
||||||
}
|
}
|
||||||
impl_consensus_encoding!(UtxoNode, height, outputs)
|
impl_consensus_encoding!(UtxoNode, height, outputs);
|
||||||
|
|
||||||
/// An iterator over UTXOs
|
/// An iterator over UTXOs
|
||||||
pub struct UtxoIterator<'a> {
|
pub struct UtxoIterator<'a> {
|
||||||
tx_iter: Entries<'a, Sha256dHash, UtxoNode>,
|
tx_iter: Entries<'a, Sha256dHash, UtxoNode>,
|
||||||
current_key: Sha256dHash,
|
current_key: Sha256dHash,
|
||||||
current: Option<&'a UtxoNode>,
|
current: Option<&'a UtxoNode>,
|
||||||
tx_index: uint
|
tx_index: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator<(Sha256dHash, uint, &'a TxOut, uint)> for UtxoIterator<'a> {
|
impl<'a> Iterator<(Sha256dHash, u32, &'a TxOut, u32)> for UtxoIterator<'a> {
|
||||||
fn next(&mut self) -> Option<(Sha256dHash, uint, &'a TxOut, uint)> {
|
fn next(&mut self) -> Option<(Sha256dHash, u32, &'a TxOut, u32)> {
|
||||||
while self.current.is_some() {
|
while self.current.is_some() {
|
||||||
let current = &self.current.unwrap().outputs;
|
let current = &self.current.unwrap().outputs;
|
||||||
while self.tx_index < current.len() {
|
while self.tx_index < current.len() as u32 {
|
||||||
self.tx_index += 1;
|
self.tx_index += 1;
|
||||||
if unsafe { current.get(self.tx_index - 1) }.is_some() {
|
if unsafe { current.get(self.tx_index as usize - 1) }.is_some() {
|
||||||
return Some((self.current_key,
|
return Some((self.current_key,
|
||||||
self.tx_index,
|
self.tx_index,
|
||||||
unsafe { current.get(self.tx_index - 1) }.as_ref().unwrap(),
|
unsafe { current.get(self.tx_index as usize - 1) }.as_ref().unwrap(),
|
||||||
self.current.unwrap().height as uint));
|
self.current.unwrap().height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match self.tx_iter.next() {
|
match self.tx_iter.next() {
|
||||||
|
@ -113,11 +113,11 @@ pub struct UtxoSet {
|
||||||
n_pruned: u64
|
n_pruned: u64
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_consensus_encoding!(UtxoSet, last_hash, n_utxos, n_pruned, spent_txos, spent_idx, table)
|
impl_consensus_encoding!(UtxoSet, last_hash, n_utxos, n_pruned, spent_txos, spent_idx, table);
|
||||||
|
|
||||||
impl UtxoSet {
|
impl UtxoSet {
|
||||||
/// Constructs a new UTXO set
|
/// Constructs a new UTXO set
|
||||||
pub fn new(network: Network, rewind_limit: uint) -> UtxoSet {
|
pub fn new(network: Network, rewind_limit: usize) -> UtxoSet {
|
||||||
// There is in fact a transaction in the genesis block, but the Bitcoin
|
// There is in fact a transaction in the genesis block, but the Bitcoin
|
||||||
// reference client does not add its sole output to the UTXO set. We
|
// reference client does not add its sole output to the UTXO set. We
|
||||||
// must follow suit, otherwise we will accept a transaction spending it
|
// must follow suit, otherwise we will accept a transaction spending it
|
||||||
|
@ -141,11 +141,11 @@ impl UtxoSet {
|
||||||
for (vout, txo) in tx.output.iter().enumerate() {
|
for (vout, txo) in tx.output.iter().enumerate() {
|
||||||
// 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 uint, None);
|
new_node.init(vout as usize, None);
|
||||||
self.n_utxos -= 1;
|
self.n_utxos -= 1;
|
||||||
self.n_pruned += 1;
|
self.n_pruned += 1;
|
||||||
} else {
|
} else {
|
||||||
new_node.init(vout as uint, Some(txo.clone()));
|
new_node.init(vout as usize, Some(txo.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UtxoNode { outputs: new_node, height: height }
|
UtxoNode { outputs: new_node, height: height }
|
||||||
|
@ -171,8 +171,8 @@ impl UtxoSet {
|
||||||
|
|
||||||
let ret = {
|
let ret = {
|
||||||
// Check that this specific output is there
|
// Check that this specific output is there
|
||||||
if vout as uint >= node.outputs.len() { return None; }
|
if vout as usize >= node.outputs.len() { return None; }
|
||||||
let replace = unsafe { node.outputs.get_mut(vout as uint) };
|
let replace = unsafe { node.outputs.get_mut(vout as usize) };
|
||||||
replace.take()
|
replace.take()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -190,20 +190,20 @@ impl UtxoSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a reference to a UTXO in the set
|
/// Get a reference to a UTXO in the set
|
||||||
pub fn get_utxo<'a>(&'a self, txid: Sha256dHash, vout: u32) -> Option<(uint, &'a TxOut)> {
|
pub fn get_utxo<'a>(&'a self, txid: Sha256dHash, vout: u32) -> Option<(usize, &'a TxOut)> {
|
||||||
// Locate the UTXO, failing if not found
|
// Locate the UTXO, failing if not found
|
||||||
let node = match self.table.find(&txid) {
|
let node = match self.table.find(&txid) {
|
||||||
Some(node) => node,
|
Some(node) => node,
|
||||||
None => return None
|
None => return None
|
||||||
};
|
};
|
||||||
// Check that this specific output is there
|
// Check that this specific output is there
|
||||||
if vout as uint >= node.outputs.len() { return None; }
|
if vout as usize >= node.outputs.len() { return None; }
|
||||||
let replace = unsafe { node.outputs.get(vout as uint) };
|
let replace = unsafe { node.outputs.get(vout as usize) };
|
||||||
Some((node.height as uint, replace.as_ref().unwrap()))
|
Some((node.height as usize, replace.as_ref().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply the transactions contained in a block
|
/// Apply the transactions contained in a block
|
||||||
pub fn update(&mut self, block: &Block, blockheight: uint, validation: ValidationLevel)
|
pub fn update(&mut self, block: &Block, blockheight: usize, validation: ValidationLevel)
|
||||||
-> Result<(), UtxoSetError> {
|
-> Result<(), UtxoSetError> {
|
||||||
// Make sure we are extending the UTXO set in order
|
// Make sure we are extending the UTXO set in order
|
||||||
if validation >= ChainValidation &&
|
if validation >= ChainValidation &&
|
||||||
|
@ -214,7 +214,7 @@ impl UtxoSet {
|
||||||
// Set the next hash immediately so that if anything goes wrong,
|
// Set the next hash immediately so that if anything goes wrong,
|
||||||
// we can rewind from the point that we're at.
|
// we can rewind from the point that we're at.
|
||||||
self.last_hash = block.header.bitcoin_hash();
|
self.last_hash = block.header.bitcoin_hash();
|
||||||
let spent_idx = self.spent_idx as uint;
|
let spent_idx = self.spent_idx as usize;
|
||||||
self.spent_idx = (self.spent_idx + 1) % self.spent_txos.len() as u64;
|
self.spent_idx = (self.spent_idx + 1) % self.spent_txos.len() as u64;
|
||||||
self.spent_txos.get_mut(spent_idx).clear();
|
self.spent_txos.get_mut(spent_idx).clear();
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ impl UtxoSet {
|
||||||
// Otherwise put the replaced txouts into the `deleted` cache
|
// Otherwise put the replaced txouts into the `deleted` cache
|
||||||
// so that rewind will put them back.
|
// so that rewind will put them back.
|
||||||
self.spent_txos.get_mut(spent_idx).reserve_additional(replace.outputs.len());
|
self.spent_txos.get_mut(spent_idx).reserve_additional(replace.outputs.len());
|
||||||
for (n, input) in replace.outputs.mut_iter().enumerate() {
|
for (n, input) in replace.outputs.iter_mut().enumerate() {
|
||||||
match input.take() {
|
match input.take() {
|
||||||
Some(txo) => { self.spent_txos.get_mut(spent_idx).push(((txid, n as u32), (replace.height, txo))); }
|
Some(txo) => { self.spent_txos.get_mut(spent_idx).push(((txid, n as u32), (replace.height, txo))); }
|
||||||
None => {}
|
None => {}
|
||||||
|
@ -269,7 +269,7 @@ impl UtxoSet {
|
||||||
|
|
||||||
let s = self as *mut _ as *const UtxoSet;
|
let s = self as *mut _ as *const UtxoSet;
|
||||||
let txes = &block.txdata as *const _;
|
let txes = &block.txdata as *const _;
|
||||||
future_vec.push(Future::spawn(proc() {
|
future_vec.push(Future::spawn(move || {
|
||||||
let txes = unsafe {&*txes};
|
let txes = unsafe {&*txes};
|
||||||
for tx in txes.slice(start, end).iter() {
|
for tx in txes.slice(start, end).iter() {
|
||||||
match tx.validate(unsafe {&*s}) {
|
match tx.validate(unsafe {&*s}) {
|
||||||
|
@ -283,7 +283,7 @@ impl UtxoSet {
|
||||||
// Return the last error since we need to finish every future before
|
// Return the last error since we need to finish every future before
|
||||||
// leaving this function, and given that, it's easier to return the last.
|
// leaving this function, and given that, it's easier to return the last.
|
||||||
let mut last_error = Ok(());
|
let mut last_error = Ok(());
|
||||||
for res in future_vec.mut_iter().map(|f| f.get()) {
|
for res in future_vec.iter_mut().map(|f| f.get()) {
|
||||||
if res.is_err() {
|
if res.is_err() {
|
||||||
last_error = res;
|
last_error = res;
|
||||||
}
|
}
|
||||||
|
@ -348,8 +348,8 @@ impl UtxoSet {
|
||||||
// Read deleted txouts
|
// Read deleted txouts
|
||||||
if skipped_genesis {
|
if skipped_genesis {
|
||||||
let mut extract_vec = vec![];
|
let mut extract_vec = vec![];
|
||||||
mem::swap(&mut extract_vec, self.spent_txos.get_mut(self.spent_idx as uint));
|
mem::swap(&mut extract_vec, self.spent_txos.get_mut(self.spent_idx as usize));
|
||||||
for ((txid, n), (height, txo)) in extract_vec.move_iter() {
|
for ((txid, n), (height, txo)) in extract_vec.into_iter() {
|
||||||
// Remove the tx's utxo list and patch the txo into place
|
// Remove the tx's utxo list and patch the txo into place
|
||||||
let new_node =
|
let new_node =
|
||||||
match self.table.pop(&txid) {
|
match self.table.pop(&txid) {
|
||||||
|
@ -359,20 +359,20 @@ impl UtxoSet {
|
||||||
unsafe {
|
unsafe {
|
||||||
node.outputs.reserve(n + 1);
|
node.outputs.reserve(n + 1);
|
||||||
for i in range(old_len, n + 1) {
|
for i in range(old_len, n + 1) {
|
||||||
node.outputs.init(i as uint, None);
|
node.outputs.init(i as usize, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe { *node.outputs.get_mut(n as uint) = Some(txo); }
|
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 = ThinVec::with_capacity(n + 1);
|
||||||
for i in range(0, n) {
|
for i in range(0, n) {
|
||||||
thinvec.init(i as uint, None);
|
thinvec.init(i as usize, None);
|
||||||
}
|
}
|
||||||
thinvec.init(n as uint, Some(txo));
|
thinvec.init(n as usize, Some(txo));
|
||||||
UtxoNode { outputs: thinvec, height: height }
|
UtxoNode { outputs: thinvec, height: height }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,14 +397,14 @@ impl UtxoSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of UTXOs in the set
|
/// Get the number of UTXOs in the set
|
||||||
pub fn n_utxos(&self) -> uint {
|
pub fn n_utxos(&self) -> usize {
|
||||||
self.n_utxos as uint
|
self.n_utxos as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of UTXOs ever pruned from the set (this is not updated
|
/// Get the number of UTXOs ever pruned from the set (this is not updated
|
||||||
/// during reorgs, so it may return a higher number than is realistic).
|
/// during reorgs, so it may return a higher number than is realistic).
|
||||||
pub fn n_pruned(&self) -> uint {
|
pub fn n_pruned(&self) -> usize {
|
||||||
self.n_pruned as uint
|
self.n_pruned as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator over all UTXOs
|
/// Get an iterator over all UTXOs
|
||||||
|
|
|
@ -12,9 +12,7 @@
|
||||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
//
|
//
|
||||||
|
|
||||||
#![macro_escape]
|
macro_rules! impl_consensus_encoding {
|
||||||
|
|
||||||
macro_rules! impl_consensus_encoding(
|
|
||||||
($thing:ident, $($field:ident),+) => (
|
($thing:ident, $($field:ident),+) => (
|
||||||
impl<S: ::network::serialize::SimpleEncoder<E>, E> ::network::encodable::ConsensusEncodable<S, E> for $thing {
|
impl<S: ::network::serialize::SimpleEncoder<E>, E> ::network::encodable::ConsensusEncodable<S, E> for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -34,9 +32,9 @@ macro_rules! impl_consensus_encoding(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
)
|
}
|
||||||
|
|
||||||
macro_rules! impl_newtype_consensus_encoding(
|
macro_rules! impl_newtype_consensus_encoding {
|
||||||
($thing:ident) => (
|
($thing:ident) => (
|
||||||
impl<S: ::network::serialize::SimpleEncoder<E>, E> ::network::encodable::ConsensusEncodable<S, E> for $thing {
|
impl<S: ::network::serialize::SimpleEncoder<E>, E> ::network::encodable::ConsensusEncodable<S, E> for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -53,9 +51,9 @@ macro_rules! impl_newtype_consensus_encoding(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
)
|
}
|
||||||
|
|
||||||
macro_rules! impl_json(
|
macro_rules! impl_json {
|
||||||
($thing:ident, $($field:ident),+) => (
|
($thing:ident, $($field:ident),+) => (
|
||||||
impl ::serialize::json::ToJson for $thing {
|
impl ::serialize::json::ToJson for $thing {
|
||||||
fn to_json(&self) -> ::serialize::json::Json {
|
fn to_json(&self) -> ::serialize::json::Json {
|
||||||
|
@ -67,9 +65,9 @@ macro_rules! impl_json(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
)
|
}
|
||||||
|
|
||||||
macro_rules! impl_array_newtype(
|
macro_rules! impl_array_newtype {
|
||||||
($thing:ident, $ty:ty, $len:expr) => {
|
($thing:ident, $ty:ty, $len:expr) => {
|
||||||
impl $thing {
|
impl $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -81,21 +79,21 @@ macro_rules! impl_array_newtype(
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Provides an immutable view into the object from index `s` inclusive to `e` exclusive
|
/// Provides an immutable view into the object from index `s` inclusive to `e` exclusive
|
||||||
pub fn slice<'a>(&'a self, s: uint, e: uint) -> &'a [$ty] {
|
pub fn slice<'a>(&'a self, s: usize, e: usize) -> &'a [$ty] {
|
||||||
let &$thing(ref dat) = self;
|
let &$thing(ref dat) = self;
|
||||||
dat.slice(s, e)
|
dat.slice(s, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Provides an immutable view into the object, up to index `n` exclusive
|
/// Provides an immutable view into the object, up to index `n` exclusive
|
||||||
pub fn slice_to<'a>(&'a self, n: uint) -> &'a [$ty] {
|
pub fn slice_to<'a>(&'a self, n: usize) -> &'a [$ty] {
|
||||||
let &$thing(ref dat) = self;
|
let &$thing(ref dat) = self;
|
||||||
dat.slice_to(n)
|
dat.slice_to(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Provides an immutable view into the object, starting from index `n`
|
/// Provides an immutable view into the object, starting from index `n`
|
||||||
pub fn slice_from<'a>(&'a self, n: uint) -> &'a [$ty] {
|
pub fn slice_from<'a>(&'a self, n: usize) -> &'a [$ty] {
|
||||||
let &$thing(ref dat) = self;
|
let &$thing(ref dat) = self;
|
||||||
dat.slice_from(n)
|
dat.slice_from(n)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +114,7 @@ macro_rules! impl_array_newtype(
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Returns the length of the object as an array
|
/// Returns the length of the object as an array
|
||||||
pub fn len(&self) -> uint { $len }
|
pub fn len(&self) -> usize { $len }
|
||||||
|
|
||||||
/// Constructs a new object from raw data
|
/// Constructs a new object from raw data
|
||||||
pub fn from_slice(data: &[$ty]) -> $thing {
|
pub fn from_slice(data: &[$ty]) -> $thing {
|
||||||
|
@ -133,9 +131,9 @@ macro_rules! impl_array_newtype(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<uint, $ty> for $thing {
|
impl Index<usize, $ty> for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index<'a>(&'a self, idx: &uint) -> &'a $ty {
|
fn index<'a>(&'a self, idx: &usize) -> &'a $ty {
|
||||||
let &$thing(ref data) = self;
|
let &$thing(ref data) = self;
|
||||||
&data[*idx]
|
&data[*idx]
|
||||||
}
|
}
|
||||||
|
@ -157,9 +155,9 @@ 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) -> ::std::prelude::Result<$thing, E> {
|
||||||
|
@ -173,7 +171,7 @@ macro_rules! impl_array_newtype_encodable(
|
||||||
} else {
|
} else {
|
||||||
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 range(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)));
|
||||||
}
|
}
|
||||||
|
@ -190,9 +188,9 @@ macro_rules! impl_array_newtype_encodable(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
macro_rules! impl_array_newtype_show(
|
macro_rules! impl_array_newtype_show {
|
||||||
($thing:ident) => {
|
($thing:ident) => {
|
||||||
impl ::std::fmt::Show for $thing {
|
impl ::std::fmt::Show for $thing {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
|
@ -200,5 +198,5 @@ macro_rules! impl_array_newtype_show(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
|
|
11
src/lib.rs
11
src/lib.rs
|
@ -28,12 +28,8 @@
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
|
|
||||||
// Experimental features we need
|
// Experimental features we need
|
||||||
#![feature(globs)]
|
|
||||||
#![feature(macro_rules)]
|
|
||||||
#![feature(overloaded_calls)]
|
#![feature(overloaded_calls)]
|
||||||
#![feature(unsafe_destructor)]
|
#![feature(unsafe_destructor)]
|
||||||
#![feature(default_type_params)]
|
|
||||||
#![feature(struct_variant)]
|
|
||||||
#![feature(unboxed_closure_sugar)]
|
#![feature(unboxed_closure_sugar)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
|
||||||
|
@ -50,18 +46,17 @@
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate collections;
|
extern crate collections;
|
||||||
extern crate core;
|
extern crate core;
|
||||||
extern crate num;
|
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate rustrt;
|
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
extern crate sync;
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
|
||||||
extern crate "bitcoin-secp256k1-rs" as secp256k1;
|
extern crate "bitcoin-secp256k1-rs" as secp256k1;
|
||||||
extern crate "rust-crypto" as crypto;
|
extern crate crypto;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
mod internal_macros;
|
mod internal_macros;
|
||||||
|
#[macro_use]
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
pub mod network;
|
pub mod network;
|
||||||
pub mod blockdata;
|
pub mod blockdata;
|
||||||
|
|
|
@ -16,14 +16,12 @@
|
||||||
//!
|
//!
|
||||||
//! Macros available to users of the Bitcoin library
|
//! Macros available to users of the Bitcoin library
|
||||||
|
|
||||||
#![macro_escape]
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! nu_select(
|
macro_rules! nu_select {
|
||||||
($($name:pat from $rx:expr => $code:expr),+) => ({
|
($($name:pat = $rx:expr => $code:expr),+) => ({
|
||||||
nu_select!{ $($name from $rx using recv => $code),+ }
|
nu_select!{ $($name = $rx, recv => $code),+ }
|
||||||
});
|
});
|
||||||
($($name:pat from $rx:expr using $meth:ident => $code:expr),+) => ({
|
($($name:pat = $rx:expr, $meth:ident => $code:expr),+) => ({
|
||||||
use rustrt::local::Local;
|
use rustrt::local::Local;
|
||||||
use rustrt::task::Task;
|
use rustrt::task::Task;
|
||||||
use sync::comm::Packet;
|
use sync::comm::Packet;
|
||||||
|
@ -82,10 +80,10 @@ macro_rules! nu_select(
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! user_enum(
|
macro_rules! user_enum {
|
||||||
($(#[$attr:meta])* pub enum $name:ident { $(#[$doc:meta] $elem:ident <-> $txt:expr),* }) => (
|
($(#[$attr:meta])* pub enum $name:ident { $(#[$doc:meta] $elem:ident <-> $txt:expr),* }) => (
|
||||||
$(#[$attr])*
|
$(#[$attr])*
|
||||||
pub enum $name {
|
pub enum $name {
|
||||||
|
@ -114,5 +112,5 @@ macro_rules! user_enum(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
)
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub struct Address {
|
||||||
/// Services provided by the peer whose address this is
|
/// Services provided by the peer whose address this is
|
||||||
pub services: u64,
|
pub services: u64,
|
||||||
/// Network byte-order ipv6 address, or ipv4-mapped ipv6 address
|
/// Network byte-order ipv6 address, or ipv4-mapped ipv6 address
|
||||||
pub address: [u8, ..16],
|
pub address: [u8; 16],
|
||||||
/// Network port
|
/// Network port
|
||||||
pub port: u16
|
pub port: u16
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ mod test {
|
||||||
let mut addr: IoResult<Address> = deserialize(vec![1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
let mut addr: IoResult<Address> = deserialize(vec![1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0,
|
0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0,
|
||||||
0, 1, 0x20, 0x8d]);
|
0, 1, 0x20, 0x8d]);
|
||||||
assert!(addr.is_ok())
|
assert!(addr.is_ok());
|
||||||
let full = addr.unwrap();
|
let full = addr.unwrap();
|
||||||
assert!(full.services == 1);
|
assert!(full.services == 1);
|
||||||
assert!(full.address == [0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1]);
|
assert!(full.address == [0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1]);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{SimpleEncoder, SimpleDecoder};
|
use network::serialize::{SimpleEncoder, SimpleDecoder};
|
||||||
|
|
||||||
user_enum!(
|
user_enum! {
|
||||||
#[deriving(PartialEq, Eq, Clone, Hash)]
|
#[deriving(PartialEq, Eq, Clone, Hash)]
|
||||||
#[doc="The cryptocurrency to act on"]
|
#[doc="The cryptocurrency to act on"]
|
||||||
pub enum Network {
|
pub enum Network {
|
||||||
|
@ -30,11 +30,11 @@ user_enum!(
|
||||||
#[doc="Bitcoin's testnet"]
|
#[doc="Bitcoin's testnet"]
|
||||||
BitcoinTestnet <-> "testnet"
|
BitcoinTestnet <-> "testnet"
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
pub static PROTOCOL_VERSION: u32 = 70001;
|
pub const PROTOCOL_VERSION: u32 = 70001;
|
||||||
pub static SERVICES: u64 = 0;
|
pub const SERVICES: u64 = 0;
|
||||||
pub static USER_AGENT: &'static str = "bitcoin-rust v0.1";
|
pub const USER_AGENT: &'static str = "bitcoin-rust v0.1";
|
||||||
|
|
||||||
/// Return the network magic bytes, which should be encoded little-endian
|
/// Return the network magic bytes, which should be encoded little-endian
|
||||||
/// at the start of every message
|
/// at the start of every message
|
||||||
|
@ -79,7 +79,7 @@ mod tests {
|
||||||
assert_eq!(deserialize(vec![0xf9, 0xbe, 0xb4, 0xd9]), Ok(Bitcoin));
|
assert_eq!(deserialize(vec![0xf9, 0xbe, 0xb4, 0xd9]), Ok(Bitcoin));
|
||||||
assert_eq!(deserialize(vec![0x0b, 0x11, 0x09, 0x07]), Ok(BitcoinTestnet));
|
assert_eq!(deserialize(vec![0x0b, 0x11, 0x09, 0x07]), Ok(BitcoinTestnet));
|
||||||
|
|
||||||
let bad: Result<Network, _> = deserialize(Vec::from_slice("fakenet".as_bytes()));
|
let bad: Result<Network, _> = deserialize("fakenet".as_bytes().to_vec());
|
||||||
assert!(bad.is_err());
|
assert!(bad.is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,10 +94,10 @@ impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for VarInt {
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
||||||
let &VarInt(n) = self;
|
let &VarInt(n) = self;
|
||||||
match n {
|
match n {
|
||||||
0..0xFC => { (n as u8).consensus_encode(s) }
|
0...0xFC => { (n as u8).consensus_encode(s) }
|
||||||
0xFD..0xFFFF => { try!(s.emit_u8(0xFD)); (n as u16).consensus_encode(s) }
|
0xFD...0xFFFF => { try!(s.emit_u8(0xFD)); (n as u16).consensus_encode(s) }
|
||||||
0x10000..0xFFFFFFFF => { try!(s.emit_u8(0xFE)); (n as u32).consensus_encode(s) }
|
0x10000...0xFFFFFFFF => { try!(s.emit_u8(0xFE)); (n as u32).consensus_encode(s) }
|
||||||
_ => { try!(s.emit_u8(0xFF)); (n as u64).consensus_encode(s) }
|
_ => { try!(s.emit_u8(0xFF)); (n as u64).consensus_encode(s) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,9 +173,9 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for String {
|
||||||
|
|
||||||
|
|
||||||
// Arrays
|
// Arrays
|
||||||
macro_rules! impl_array(
|
macro_rules! impl_array {
|
||||||
( $size:expr ) => (
|
( $size:expr ) => (
|
||||||
impl<S:SimpleEncoder<E>, E, T:ConsensusEncodable<S, E>> ConsensusEncodable<S, E> for [T, ..$size] {
|
impl<S:SimpleEncoder<E>, E, T:ConsensusEncodable<S, E>> ConsensusEncodable<S, E> for [T; $size] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
||||||
for i in self.iter() { try!(i.consensus_encode(s)); }
|
for i in self.iter() { try!(i.consensus_encode(s)); }
|
||||||
|
@ -183,25 +183,25 @@ macro_rules! impl_array(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D:SimpleDecoder<E>, E, T:ConsensusDecodable<D, E>+Copy> ConsensusDecodable<D, E> for [T, ..$size] {
|
impl<D:SimpleDecoder<E>, E, T:ConsensusDecodable<D, E>+Copy> ConsensusDecodable<D, E> for [T; $size] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<[T, ..$size], E> {
|
fn consensus_decode(d: &mut D) -> Result<[T; $size], E> {
|
||||||
// Set everything to the first decode
|
// Set everything to the first decode
|
||||||
let mut ret = [try!(ConsensusDecodable::consensus_decode(d)), ..$size];
|
let mut ret = [try!(ConsensusDecodable::consensus_decode(d)); $size];
|
||||||
// Set the rest
|
// Set the rest
|
||||||
for i in range(1, $size) { ret[i] = try!(ConsensusDecodable::consensus_decode(d)); }
|
for i in range(1, $size) { ret[i] = try!(ConsensusDecodable::consensus_decode(d)); }
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
)
|
}
|
||||||
|
|
||||||
impl_array!(2)
|
impl_array!(2);
|
||||||
impl_array!(4)
|
impl_array!(4);
|
||||||
impl_array!(8)
|
impl_array!(8);
|
||||||
impl_array!(12)
|
impl_array!(12);
|
||||||
impl_array!(16)
|
impl_array!(16);
|
||||||
impl_array!(32)
|
impl_array!(32);
|
||||||
|
|
||||||
impl<'a, S:SimpleEncoder<E>, E, T:ConsensusEncodable<S, E>> ConsensusEncodable<S, E> for &'a [T] {
|
impl<'a, S:SimpleEncoder<E>, E, T:ConsensusEncodable<S, E>> ConsensusEncodable<S, E> for &'a [T] {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -224,7 +224,7 @@ impl<D:SimpleDecoder<E>, E, T:ConsensusDecodable<D, E>> ConsensusDecodable<D, E>
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Vec<T>, E> {
|
fn consensus_decode(d: &mut D) -> Result<Vec<T>, E> {
|
||||||
let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d));
|
let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d));
|
||||||
let mut ret = Vec::with_capacity(len as uint);
|
let mut ret = Vec::with_capacity(len as usize);
|
||||||
for _ in range(0, len) { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
|
for _ in range(0, len) { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ impl<D:SimpleDecoder<E>, E, T:ConsensusDecodable<D, E>> ConsensusDecodable<D, E>
|
||||||
// Huge danger: if this fails, the remaining uninitialized part of the ThinVec
|
// 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
|
// 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.
|
// destructor...and assuming there are no trap representations...very fragile.
|
||||||
for i in range(0, len as uint) { ret.init(i, try!(ConsensusDecodable::consensus_decode(d))); }
|
for i in range(0, len as usize) { ret.init(i, try!(ConsensusDecodable::consensus_decode(d))); }
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,9 +282,9 @@ impl<D:SimpleDecoder<E>, E, T:ConsensusDecodable<D, E>> ConsensusDecodable<D, E>
|
||||||
|
|
||||||
|
|
||||||
/// Do a double-SHA256 on some data and return the first 4 bytes
|
/// Do a double-SHA256 on some data and return the first 4 bytes
|
||||||
fn sha2_checksum(data: &[u8]) -> [u8, ..4] {
|
fn sha2_checksum(data: &[u8]) -> [u8; 4] {
|
||||||
let checksum = Sha256dHash::from_data(data);
|
let checksum = Sha256dHash::from_data(data);
|
||||||
[checksum[0u], checksum[1u], checksum[2u], checksum[3u]]
|
[checksum[0], checksum[1], checksum[2], checksum[3]]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checked data
|
// Checked data
|
||||||
|
@ -293,7 +293,7 @@ impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for CheckedData {
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
||||||
let &CheckedData(ref data) = self;
|
let &CheckedData(ref data) = self;
|
||||||
try!((data.len() as u32).consensus_encode(s));
|
try!((data.len() as u32).consensus_encode(s));
|
||||||
try!(sha2_checksum(data.as_slice()).consensus_encode(s))
|
try!(sha2_checksum(data.as_slice()).consensus_encode(s));
|
||||||
// We can't just pass to the slice encoder since it'll insert a length
|
// We can't just pass to the slice encoder since it'll insert a length
|
||||||
for ch in data.iter() {
|
for ch in data.iter() {
|
||||||
try!(ch.consensus_encode(s));
|
try!(ch.consensus_encode(s));
|
||||||
|
@ -306,8 +306,8 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for CheckedData {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<CheckedData, E> {
|
fn consensus_decode(d: &mut D) -> Result<CheckedData, E> {
|
||||||
let len: u32 = try!(ConsensusDecodable::consensus_decode(d));
|
let len: u32 = try!(ConsensusDecodable::consensus_decode(d));
|
||||||
let checksum: [u8, ..4] = try!(ConsensusDecodable::consensus_decode(d));
|
let checksum: [u8; 4] = try!(ConsensusDecodable::consensus_decode(d));
|
||||||
let mut ret = Vec::with_capacity(len as uint);
|
let mut ret = Vec::with_capacity(len as usize);
|
||||||
for _ in range(0, len) { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
|
for _ in range(0, len) { ret.push(try!(ConsensusDecodable::consensus_decode(d))); }
|
||||||
let expected_checksum = sha2_checksum(ret.as_slice());
|
let expected_checksum = sha2_checksum(ret.as_slice());
|
||||||
if expected_checksum != checksum {
|
if expected_checksum != checksum {
|
||||||
|
@ -319,7 +319,7 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for CheckedData {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tuples
|
// Tuples
|
||||||
macro_rules! tuple_encode(
|
macro_rules! tuple_encode {
|
||||||
($($x:ident),*) => (
|
($($x:ident),*) => (
|
||||||
impl <SS:SimpleEncoder<EE>, EE, $($x: ConsensusEncodable<SS, EE>),*> ConsensusEncodable<SS, EE> for ($($x),*) {
|
impl <SS:SimpleEncoder<EE>, EE, $($x: ConsensusEncodable<SS, EE>),*> ConsensusEncodable<SS, EE> for ($($x),*) {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -339,12 +339,12 @@ macro_rules! tuple_encode(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
)
|
}
|
||||||
|
|
||||||
tuple_encode!(A, B)
|
tuple_encode!(A, B);
|
||||||
tuple_encode!(A, B, C, D)
|
tuple_encode!(A, B, C, D);
|
||||||
tuple_encode!(A, B, C, D, E, F)
|
tuple_encode!(A, B, C, D, E, F);
|
||||||
tuple_encode!(A, B, C, D, E, F, G, H)
|
tuple_encode!(A, B, C, D, E, F, G, H);
|
||||||
|
|
||||||
|
|
||||||
// References
|
// References
|
||||||
|
@ -356,7 +356,7 @@ impl<S:SimpleEncoder<E>, E, T: ConsensusEncodable<S, E>> ConsensusEncodable<S, E
|
||||||
impl<D:SimpleDecoder<E>, E, T: ConsensusDecodable<D, E>> ConsensusDecodable<D, E> for Box<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<Box<T>, E> {
|
fn consensus_decode(d: &mut D) -> Result<Box<T>, E> {
|
||||||
ConsensusDecodable::consensus_decode(d).map(|res| box res)
|
ConsensusDecodable::consensus_decode(d).map(|res| Box::new(res))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ impl<D:SimpleDecoder<E>, E, T,
|
||||||
fn consensus_decode(d: &mut D) -> Result<HashMap<K, V, H>, E> {
|
fn consensus_decode(d: &mut D) -> Result<HashMap<K, V, H>, E> {
|
||||||
let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d));
|
let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d));
|
||||||
|
|
||||||
let mut ret = HashMap::with_capacity_and_hasher(len as uint, Default::default());
|
let mut ret = HashMap::with_capacity_and_hasher(len as usize, Default::default());
|
||||||
for _ in range(0, len) {
|
for _ in range(0, len) {
|
||||||
ret.insert(try!(ConsensusDecodable::consensus_decode(d)),
|
ret.insert(try!(ConsensusDecodable::consensus_decode(d)),
|
||||||
try!(ConsensusDecodable::consensus_decode(d)));
|
try!(ConsensusDecodable::consensus_decode(d)));
|
||||||
|
@ -474,9 +474,9 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_box_test() {
|
fn serialize_box_test() {
|
||||||
assert_eq!(serialize(&box 1u8), Ok(vec![1u8]));
|
assert_eq!(serialize(&Box::new(1u8)), Ok(vec![1u8]));
|
||||||
assert_eq!(serialize(&box 1u16), Ok(vec![1u8, 0]));
|
assert_eq!(serialize(&Box::new(1u16)), Ok(vec![1u8, 0]));
|
||||||
assert_eq!(serialize(&box 1u64), Ok(vec![1u8, 0, 0, 0, 0, 0, 0, 0]));
|
assert_eq!(serialize(&Box::new(1u64)), Ok(vec![1u8, 0, 0, 0, 0, 0, 0, 0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -560,8 +560,8 @@ mod tests {
|
||||||
fn deserialize_box_test() {
|
fn deserialize_box_test() {
|
||||||
let zero: IoResult<Box<u8>> = deserialize(vec![0u8]);
|
let zero: IoResult<Box<u8>> = deserialize(vec![0u8]);
|
||||||
let one: IoResult<Box<u8>> = deserialize(vec![1u8]);
|
let one: IoResult<Box<u8>> = deserialize(vec![1u8]);
|
||||||
assert_eq!(zero, Ok(box 0));
|
assert_eq!(zero, Ok(Box::new(0)));
|
||||||
assert_eq!(one, Ok(box 1));
|
assert_eq!(one, Ok(Box::new(1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
use std::io::{IoResult, standard_error, ConnectionFailed};
|
use std::io::{IoResult, standard_error, ConnectionFailed};
|
||||||
|
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
use network::message::{mod, SocketResponse, MessageReceived, Verack};
|
use network::message::{self, SocketResponse, MessageReceived, Verack};
|
||||||
use network::socket::Socket;
|
use network::socket::Socket;
|
||||||
|
|
||||||
/// A message which can be sent on the Bitcoin network
|
/// A message which can be sent on the Bitcoin network
|
||||||
|
@ -49,7 +49,7 @@ pub trait Listener {
|
||||||
try!(sock.send_message(version_message));
|
try!(sock.send_message(version_message));
|
||||||
|
|
||||||
// Message loop
|
// Message loop
|
||||||
spawn(proc() {
|
spawn(move || {
|
||||||
let mut handshake_complete = false;
|
let mut handshake_complete = false;
|
||||||
let mut sock = sock;
|
let mut sock = sock;
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for CommandString {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
||||||
let &CommandString(ref inner_str) = self;
|
let &CommandString(ref inner_str) = self;
|
||||||
let mut rawbytes = [0u8, ..12];
|
let mut rawbytes = [0u8; 12];
|
||||||
rawbytes.clone_from_slice(inner_str.as_bytes().as_slice());
|
rawbytes.clone_from_slice(inner_str.as_bytes().as_slice());
|
||||||
rawbytes.consensus_encode(s)
|
rawbytes.consensus_encode(s)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for CommandString {
|
||||||
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for CommandString {
|
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for CommandString {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<CommandString, E> {
|
fn consensus_decode(d: &mut D) -> Result<CommandString, E> {
|
||||||
let rawbytes: [u8, ..12] = try!(ConsensusDecodable::consensus_decode(d));
|
let rawbytes: [u8; 12] = try!(ConsensusDecodable::consensus_decode(d));
|
||||||
let rv = FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None }));
|
let rv = FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None }));
|
||||||
Ok(CommandString(rv))
|
Ok(CommandString(rv))
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl GetBlocksMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash)
|
impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash);
|
||||||
|
|
||||||
impl GetHeadersMessage {
|
impl GetHeadersMessage {
|
||||||
/// Construct a new `getheaders` message
|
/// Construct a new `getheaders` message
|
||||||
|
@ -95,7 +95,7 @@ impl GetHeadersMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash)
|
impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash);
|
||||||
|
|
||||||
impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for Inventory {
|
impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for Inventory {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -119,7 +119,7 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Inventory {
|
||||||
1 => InvTransaction,
|
1 => InvTransaction,
|
||||||
2 => InvBlock,
|
2 => InvBlock,
|
||||||
// TODO do not fail here
|
// TODO do not fail here
|
||||||
_ => { fail!("bad inventory type field") }
|
_ => { panic!("bad inventory type field") }
|
||||||
},
|
},
|
||||||
hash: try!(ConsensusDecodable::consensus_decode(d))
|
hash: try!(ConsensusDecodable::consensus_decode(d))
|
||||||
})
|
})
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl VersionMessage {
|
||||||
|
|
||||||
impl_consensus_encoding!(VersionMessage, version, services, timestamp,
|
impl_consensus_encoding!(VersionMessage, version, services, timestamp,
|
||||||
receiver, sender, nonce,
|
receiver, sender, nonce,
|
||||||
user_agent, start_height, relay)
|
user_agent, start_height, relay);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -34,7 +34,7 @@ use network::serialize::{RawEncoder, RawDecoder};
|
||||||
use util::misc::prepend_err;
|
use util::misc::prepend_err;
|
||||||
|
|
||||||
/// Format an IP address in the 16-byte bitcoin protocol serialization
|
/// Format an IP address in the 16-byte bitcoin protocol serialization
|
||||||
fn ipaddr_to_bitcoin_addr(ipaddr: &ip::IpAddr) -> [u8, ..16] {
|
fn ipaddr_to_bitcoin_addr(ipaddr: &ip::IpAddr) -> [u8; 16] {
|
||||||
match *ipaddr {
|
match *ipaddr {
|
||||||
ip::Ipv4Addr(a, b, c, d) =>
|
ip::Ipv4Addr(a, b, c, d) =>
|
||||||
[0, 0, 0, 0, 0, 0, 0, 0,
|
[0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
|
@ -28,18 +28,18 @@ pub enum Base58Error {
|
||||||
/// Checksum was not correct (expected, actual)
|
/// Checksum was not correct (expected, actual)
|
||||||
BadChecksum(u32, u32),
|
BadChecksum(u32, u32),
|
||||||
/// The length (in bytes) of the object was not correct
|
/// The length (in bytes) of the object was not correct
|
||||||
InvalidLength(uint),
|
InvalidLength(usize),
|
||||||
/// Version byte(s) were not recognized
|
/// Version byte(s) were not recognized
|
||||||
InvalidVersion(Vec<u8>),
|
InvalidVersion(Vec<u8>),
|
||||||
/// Checked data was less than 4 bytes
|
/// Checked data was less than 4 bytes
|
||||||
TooShort(uint),
|
TooShort(usize),
|
||||||
/// Any other error
|
/// Any other error
|
||||||
OtherBase58Error(String)
|
OtherBase58Error(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
static BASE58_CHARS: &'static [u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
static BASE58_CHARS: &'static [u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||||
|
|
||||||
static BASE58_DIGITS: [Option<u8>, ..128] = [
|
static BASE58_DIGITS: [Option<u8>; 128] = [
|
||||||
None, None, None, None, None, None, None, None, // 0-7
|
None, None, None, None, None, None, None, None, // 0-7
|
||||||
None, None, None, None, None, None, None, None, // 8-15
|
None, None, None, None, None, None, None, None, // 8-15
|
||||||
None, None, None, None, None, None, None, None, // 16-23
|
None, None, None, None, None, None, None, None, // 16-23
|
||||||
|
@ -71,14 +71,14 @@ pub trait FromBase58 {
|
||||||
// Build in base 256
|
// Build in base 256
|
||||||
for d58 in data.bytes() {
|
for d58 in data.bytes() {
|
||||||
// Compute "X = X * 58 + next_digit" in base 256
|
// Compute "X = X * 58 + next_digit" in base 256
|
||||||
if d58 as uint > BASE58_DIGITS.len() {
|
if d58 as usize > BASE58_DIGITS.len() {
|
||||||
return Err(BadByte(d58));
|
return Err(BadByte(d58));
|
||||||
}
|
}
|
||||||
let mut carry = match BASE58_DIGITS[d58 as uint] {
|
let mut carry = match BASE58_DIGITS[d58 as usize] {
|
||||||
Some(d58) => d58 as u32,
|
Some(d58) => d58 as u32,
|
||||||
None => { return Err(BadByte(d58)); }
|
None => { return Err(BadByte(d58)); }
|
||||||
};
|
};
|
||||||
for d256 in scratch.mut_iter().rev() {
|
for d256 in scratch.iter_mut().rev() {
|
||||||
carry += *d256 as u32 * 58;
|
carry += *d256 as u32 * 58;
|
||||||
*d256 = carry as u8;
|
*d256 = carry as u8;
|
||||||
carry /= 256;
|
carry /= 256;
|
||||||
|
@ -91,7 +91,7 @@ pub trait FromBase58 {
|
||||||
.map(|_| 0)
|
.map(|_| 0)
|
||||||
.collect();
|
.collect();
|
||||||
// Copy rest of string
|
// Copy rest of string
|
||||||
ret.extend(scratch.move_iter().skip_while(|&x| x == 0));
|
ret.extend(scratch.into_iter().skip_while(|&x| x == 0));
|
||||||
FromBase58::from_base58_layout(ret)
|
FromBase58::from_base58_layout(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,8 +121,8 @@ pub fn base58_encode_slice(data: &[u8]) -> String {
|
||||||
for &d256 in data.base58_layout().iter() {
|
for &d256 in data.base58_layout().iter() {
|
||||||
// Compute "X = X * 256 + next_digit" in base 58
|
// Compute "X = X * 256 + next_digit" in base 58
|
||||||
let mut carry = d256 as u32;
|
let mut carry = d256 as u32;
|
||||||
for d58 in scratch.mut_iter().rev() {
|
for d58 in scratch.iter_mut().rev() {
|
||||||
carry += *d58 as u32 << 8;
|
carry += (*d58 as u32) << 8;
|
||||||
*d58 = (carry % 58) as u8;
|
*d58 = (carry % 58) as u8;
|
||||||
carry /= 58;
|
carry /= 58;
|
||||||
}
|
}
|
||||||
|
@ -136,8 +136,8 @@ pub fn base58_encode_slice(data: &[u8]) -> String {
|
||||||
.map(|_| BASE58_CHARS[0])
|
.map(|_| BASE58_CHARS[0])
|
||||||
.collect());
|
.collect());
|
||||||
// Copy rest of string
|
// Copy rest of string
|
||||||
ret.as_mut_vec().extend(scratch.move_iter().skip_while(|&x| x == 0)
|
ret.as_mut_vec().extend(scratch.into_iter().skip_while(|&x| x == 0)
|
||||||
.map(|x| BASE58_CHARS[x as uint]));
|
.map(|x| BASE58_CHARS[x as usize]));
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ pub trait ToBase58 {
|
||||||
|
|
||||||
// Trivial implementations for slices and vectors
|
// Trivial implementations for slices and vectors
|
||||||
impl<'a> ToBase58 for &'a [u8] {
|
impl<'a> ToBase58 for &'a [u8] {
|
||||||
fn base58_layout(&self) -> Vec<u8> { Vec::from_slice(*self) }
|
fn base58_layout(&self) -> Vec<u8> { self.to_vec() }
|
||||||
fn to_base58(&self) -> String { base58_encode_slice(*self) }
|
fn to_base58(&self) -> String { base58_encode_slice(*self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ impl ToBase58 for Vec<u8> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToBase58 for ThinVec<u8> {
|
impl ToBase58 for ThinVec<u8> {
|
||||||
fn base58_layout(&self) -> Vec<u8> { Vec::from_slice(self.as_slice()) }
|
fn base58_layout(&self) -> Vec<u8> { self.as_slice().to_vec() }
|
||||||
fn to_base58(&self) -> String { base58_encode_slice(self.as_slice()) }
|
fn to_base58(&self) -> String { base58_encode_slice(self.as_slice()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub type BitcoinResult<T> = Result<T, BitcoinError>;
|
||||||
#[deriving(PartialEq, Eq, Show, Clone)]
|
#[deriving(PartialEq, Eq, Show, Clone)]
|
||||||
pub enum BitcoinError {
|
pub enum BitcoinError {
|
||||||
/// An I/O error
|
/// An I/O error
|
||||||
IoError(IoError),
|
InputOutput(IoError),
|
||||||
/// An object was attempted to be added twice
|
/// An object was attempted to be added twice
|
||||||
DuplicateHash,
|
DuplicateHash,
|
||||||
/// Some operation was attempted on a block (or blockheader) that doesn't exist
|
/// Some operation was attempted on a block (or blockheader) that doesn't exist
|
||||||
|
|
135
src/util/hash.rs
135
src/util/hash.rs
|
@ -19,10 +19,11 @@ use core::char::from_digit;
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::io::extensions::u64_from_be_bytes;
|
||||||
use std::io::MemWriter;
|
use std::io::MemWriter;
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
use std::hash;
|
use std::hash;
|
||||||
use serialize::json::{mod, ToJson};
|
use serialize::json::{self, ToJson};
|
||||||
|
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
use crypto::sha2::Sha256;
|
use crypto::sha2::Sha256;
|
||||||
|
@ -30,12 +31,11 @@ use crypto::ripemd160::Ripemd160;
|
||||||
|
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder};
|
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder};
|
||||||
use util::uint::Uint128;
|
|
||||||
use util::uint::Uint256;
|
use util::uint::Uint256;
|
||||||
|
|
||||||
/// A Bitcoin hash, 32-bytes, computed from x as SHA256(SHA256(x))
|
/// A Bitcoin hash, 32-bytes, computed from x as SHA256(SHA256(x))
|
||||||
pub struct Sha256dHash([u8, ..32]);
|
pub struct Sha256dHash([u8; 32]);
|
||||||
impl_array_newtype!(Sha256dHash, u8, 32)
|
impl_array_newtype!(Sha256dHash, u8, 32);
|
||||||
|
|
||||||
impl ::std::fmt::Show for Sha256dHash {
|
impl ::std::fmt::Show for Sha256dHash {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
|
@ -44,12 +44,18 @@ impl ::std::fmt::Show for Sha256dHash {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A RIPEMD-160 hash
|
/// A RIPEMD-160 hash
|
||||||
pub struct Ripemd160Hash([u8, ..20]);
|
pub struct Ripemd160Hash([u8; 20]);
|
||||||
impl_array_newtype!(Ripemd160Hash, u8, 20)
|
impl_array_newtype!(Ripemd160Hash, u8, 20);
|
||||||
|
|
||||||
/// A "hasher" which just truncates
|
/// A "hasher" which just truncates and adds data to its state. Should
|
||||||
|
/// only be used for hashtables indexed by "already random" data such
|
||||||
|
/// as SHA2 hashes
|
||||||
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
pub struct DumbHasher;
|
pub struct DumbHasher;
|
||||||
|
|
||||||
|
/// The state of a `DumbHasher`
|
||||||
|
pub struct DumbHasherState([u8; 8]);
|
||||||
|
|
||||||
/// A 32-bit hash obtained by truncating a real hash
|
/// A 32-bit hash obtained by truncating a real hash
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
pub struct Hash32((u8, u8, u8, u8));
|
pub struct Hash32((u8, u8, u8, u8));
|
||||||
|
@ -64,65 +70,34 @@ pub struct Hash64((u8, u8, u8, u8, u8, u8, u8, u8));
|
||||||
|
|
||||||
|
|
||||||
// Allow these to be used as a key for Rust's HashMap et. al.
|
// Allow these to be used as a key for Rust's HashMap et. al.
|
||||||
impl hash::Hash<u64> for Sha256dHash {
|
impl hash::Hash<DumbHasherState> for Sha256dHash {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, state: &mut u64) {
|
fn hash(&self, state: &mut DumbHasherState) {
|
||||||
use std::mem;
|
let &Sha256dHash(ref hash) = self;
|
||||||
let myarr: [u64, ..4] = unsafe { mem::transmute(*self) };
|
let &DumbHasherState(ref mut arr) = state;
|
||||||
*state = myarr[0];
|
for i in range(0, 8) {
|
||||||
|
arr[i] += hash[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl hash::Hash<u64> for Uint256 {
|
impl hash::Hasher<DumbHasherState> for DumbHasher {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, state: &mut u64) {
|
fn hash<T: hash::Hash<DumbHasherState>>(&self, value: &T) -> u64 {
|
||||||
use std::mem;
|
let mut ret = DumbHasherState([0; 8]);
|
||||||
let myarr: [u64, ..4] = unsafe { mem::transmute(*self) };
|
|
||||||
*state = myarr[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl hash::Hash<u64> for Uint128 {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut u64) {
|
|
||||||
use std::mem;
|
|
||||||
let myarr: [u64, ..2] = unsafe { mem::transmute(*self) };
|
|
||||||
*state = myarr[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl hash::Hash<u64> for Hash32 {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut u64) {
|
|
||||||
let &Hash32((a, b, c, d)) = self;
|
|
||||||
*state = a as u64 + (b as u64 << 8) + (c as u64 << 16) + (d as u64 << 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl hash::Hash<u64> for Hash48 {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut u64) {
|
|
||||||
let &Hash48((a, b, c, d, e, f)) = self;
|
|
||||||
*state = a as u64 + (b as u64 << 8) + (c as u64 << 16) + (d as u64 << 24) +
|
|
||||||
(e as u64 << 32) + (f as u64 << 40);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl hash::Hash<u64> for Hash64 {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut u64) {
|
|
||||||
let &Hash64((a, b, c, d, e, f, g, h)) = self;
|
|
||||||
*state = a as u64 + (b as u64 << 8) + (c as u64 << 16) + (d as u64 << 24) +
|
|
||||||
(e as u64 << 32) + (f as u64 << 40) + (g as u64 << 48) + (h as u64 << 56);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl hash::Hasher<u64> for DumbHasher {
|
|
||||||
#[inline]
|
|
||||||
fn hash<T: hash::Hash<u64>>(&self, value: &T) -> u64 {
|
|
||||||
let mut ret = 0u64;
|
|
||||||
value.hash(&mut ret);
|
value.hash(&mut ret);
|
||||||
ret
|
let DumbHasherState(res) = ret;
|
||||||
|
u64_from_be_bytes(res.as_slice(), 0, 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl hash::Writer for DumbHasherState {
|
||||||
|
#[inline]
|
||||||
|
fn write(&mut self, msg: &[u8]) {
|
||||||
|
let &DumbHasherState(ref mut arr) = self;
|
||||||
|
for (n, &ch) in msg.iter().enumerate() {
|
||||||
|
arr[n % 8] += ch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +109,7 @@ impl Default for DumbHasher {
|
||||||
impl Ripemd160Hash {
|
impl Ripemd160Hash {
|
||||||
/// Create a hash by hashing some data
|
/// Create a hash by hashing some data
|
||||||
pub fn from_data(data: &[u8]) -> Ripemd160Hash {
|
pub fn from_data(data: &[u8]) -> Ripemd160Hash {
|
||||||
let mut ret = [0, ..20];
|
let mut ret = [0; 20];
|
||||||
let mut rmd = Ripemd160::new();
|
let mut rmd = Ripemd160::new();
|
||||||
rmd.input(data);
|
rmd.input(data);
|
||||||
rmd.result(ret.as_mut_slice());
|
rmd.result(ret.as_mut_slice());
|
||||||
|
@ -146,7 +121,7 @@ impl Ripemd160Hash {
|
||||||
// in the C++ reference client
|
// in the C++ reference client
|
||||||
impl Default for Sha256dHash {
|
impl Default for Sha256dHash {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Sha256dHash { Sha256dHash([0u8, ..32]) }
|
fn default() -> Sha256dHash { Sha256dHash([0u8; 32]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sha256dHash {
|
impl Sha256dHash {
|
||||||
|
@ -166,8 +141,8 @@ impl Sha256dHash {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_le(self) -> Uint256 {
|
pub fn into_le(self) -> Uint256 {
|
||||||
let Sha256dHash(data) = self;
|
let Sha256dHash(data) = self;
|
||||||
let mut ret: [u64, ..4] = unsafe { transmute(data) };
|
let mut ret: [u64; 4] = unsafe { transmute(data) };
|
||||||
for x in ret.as_mut_slice().mut_iter() { *x = x.to_le(); }
|
for x in ret.as_mut_slice().iter_mut() { *x = x.to_le(); }
|
||||||
Uint256(ret)
|
Uint256(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +151,8 @@ impl Sha256dHash {
|
||||||
pub fn into_be(self) -> Uint256 {
|
pub fn into_be(self) -> Uint256 {
|
||||||
let Sha256dHash(mut data) = self;
|
let Sha256dHash(mut data) = self;
|
||||||
data.reverse();
|
data.reverse();
|
||||||
let mut ret: [u64, ..4] = unsafe { transmute(data) };
|
let mut ret: [u64; 4] = unsafe { transmute(data) };
|
||||||
for x in ret.mut_iter() { *x = x.to_be(); }
|
for x in ret.iter_mut() { *x = x.to_be(); }
|
||||||
Uint256(ret)
|
Uint256(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,9 +184,9 @@ impl Sha256dHash {
|
||||||
pub fn le_hex_string(&self) -> String {
|
pub fn le_hex_string(&self) -> String {
|
||||||
let &Sha256dHash(data) = self;
|
let &Sha256dHash(data) = self;
|
||||||
let mut ret = String::with_capacity(64);
|
let mut ret = String::with_capacity(64);
|
||||||
for i in range(0u, 32) {
|
for i in range(0, 32) {
|
||||||
ret.push_char(from_digit((data[i] / 0x10) as uint, 16).unwrap());
|
ret.push_char(from_digit((data[i] / 0x10) as usize, 16).unwrap());
|
||||||
ret.push_char(from_digit((data[i] & 0x0f) as uint, 16).unwrap());
|
ret.push_char(from_digit((data[i] & 0x0f) as usize, 16).unwrap());
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
@ -220,9 +195,9 @@ impl Sha256dHash {
|
||||||
pub fn be_hex_string(&self) -> String {
|
pub fn be_hex_string(&self) -> String {
|
||||||
let &Sha256dHash(data) = self;
|
let &Sha256dHash(data) = self;
|
||||||
let mut ret = String::with_capacity(64);
|
let mut ret = String::with_capacity(64);
|
||||||
for i in range(0u, 32).rev() {
|
for i in range(0, 32).rev() {
|
||||||
ret.push_char(from_digit((data[i] / 0x10) as uint, 16).unwrap());
|
ret.push_char(from_digit((data[i] / 0x10) as usize, 16).unwrap());
|
||||||
ret.push_char(from_digit((data[i] & 0x0f) as uint, 16).unwrap());
|
ret.push_char(from_digit((data[i] & 0x0f) as usize, 16).unwrap());
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
@ -258,7 +233,7 @@ impl<D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for Sha256dHash
|
||||||
}
|
}
|
||||||
let raw_str = try!(hex_str.as_slice().from_hex()
|
let raw_str = try!(hex_str.as_slice().from_hex()
|
||||||
.map_err(|_| d.error("non-hexadecimal hash string")));
|
.map_err(|_| d.error("non-hexadecimal hash string")));
|
||||||
let mut ret = [0u8, ..32];
|
let mut ret = [0u8; 32];
|
||||||
for i in range(0, 32) {
|
for i in range(0, 32) {
|
||||||
ret[i] = raw_str[31 - i];
|
ret[i] = raw_str[31 - i];
|
||||||
}
|
}
|
||||||
|
@ -267,19 +242,19 @@ impl<D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for Sha256dHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consensus encoding (little-endian)
|
// Consensus encoding (little-endian)
|
||||||
impl_newtype_consensus_encoding!(Hash32)
|
impl_newtype_consensus_encoding!(Hash32);
|
||||||
impl_newtype_consensus_encoding!(Hash48)
|
impl_newtype_consensus_encoding!(Hash48);
|
||||||
impl_newtype_consensus_encoding!(Hash64)
|
impl_newtype_consensus_encoding!(Hash64);
|
||||||
impl_newtype_consensus_encoding!(Sha256dHash)
|
impl_newtype_consensus_encoding!(Sha256dHash);
|
||||||
|
|
||||||
impl fmt::LowerHex for Sha256dHash {
|
impl fmt::LowerHex for Sha256dHash {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let &Sha256dHash(data) = self;
|
let &Sha256dHash(data) = self;
|
||||||
let mut rv = [0, ..64];
|
let mut rv = [0; 64];
|
||||||
let mut hex = data.iter().rev().map(|n| *n).enumerate();
|
let mut hex = data.iter().rev().map(|n| *n).enumerate();
|
||||||
for (i, ch) in hex {
|
for (i, ch) in hex {
|
||||||
rv[2*i] = from_digit(ch as uint / 16, 16).unwrap() as u8;
|
rv[2*i] = from_digit(ch as usize / 16, 16).unwrap() as u8;
|
||||||
rv[2*i + 1] = from_digit(ch as uint % 16, 16).unwrap() as u8;
|
rv[2*i + 1] = from_digit(ch as usize % 16, 16).unwrap() as u8;
|
||||||
}
|
}
|
||||||
f.write(rv.as_slice())
|
f.write(rv.as_slice())
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl<A, I: Iterator<A>> Iterator<(A, A)> for Pair<A, I> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
match self.iter.size_hint() {
|
match self.iter.size_hint() {
|
||||||
(n, None) => (n/2, None),
|
(n, None) => (n/2, None),
|
||||||
(n, Some(m)) => (n/2, Some(m/2))
|
(n, Some(m)) => (n/2, Some(m/2))
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub fn prepend_err<T>(s: &str, res: IoResult<T>) -> IoResult<T> {
|
||||||
IoError {
|
IoError {
|
||||||
kind: err.kind,
|
kind: err.kind,
|
||||||
desc: err.desc,
|
desc: err.desc,
|
||||||
detail: Some(format!("{:s}: {:}", s, match err.detail { Some(s) => s, None => String::new() }))
|
detail: Some(format!("{}: {}", s, match err.detail { Some(s) => s, None => String::new() }))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -71,14 +71,14 @@ pub fn prepend_err<T>(s: &str, res: IoResult<T>) -> IoResult<T> {
|
||||||
pub fn consume_err<T>(s: &str, res: IoResult<T>) {
|
pub fn consume_err<T>(s: &str, res: IoResult<T>) {
|
||||||
match res {
|
match res {
|
||||||
Ok(_) => {},
|
Ok(_) => {},
|
||||||
Err(e) => { println!("{:s}: {:}", s, e); }
|
Err(e) => { println!("{}: {}", s, e); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for `needle` in the vector `haystack` and remove every
|
/// Search for `needle` in the vector `haystack` and remove every
|
||||||
/// instance of it, returning the number of instances removed.
|
/// instance of it, returning the number of instances removed.
|
||||||
/// Loops through the vector opcode by opcode, skipping pushed data.
|
/// Loops through the vector opcode by opcode, skipping pushed data.
|
||||||
pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> uint {
|
pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> usize {
|
||||||
if needle.len() > haystack.len() { return 0; }
|
if needle.len() > haystack.len() { return 0; }
|
||||||
if needle.len() == 0 { return 0; }
|
if needle.len() == 0 { return 0; }
|
||||||
|
|
||||||
|
|
|
@ -28,15 +28,15 @@ 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
|
||||||
pub trait BitArray {
|
pub trait BitArray {
|
||||||
/// Is bit set?
|
/// Is bit set?
|
||||||
fn bit(&self, idx: uint) -> bool;
|
fn bit(&self, idx: usize) -> bool;
|
||||||
|
|
||||||
/// Returns an array which is just the bits from start to end
|
/// Returns an array which is just the bits from start to end
|
||||||
fn bit_slice(&self, start: uint, end: uint) -> Self;
|
fn bit_slice(&self, start: usize, end: usize) -> Self;
|
||||||
|
|
||||||
/// Bitwise and with `n` ones
|
/// Bitwise and with `n` ones
|
||||||
fn mask(&self, n: uint) -> Self;
|
fn mask(&self, n: usize) -> Self;
|
||||||
|
|
||||||
/// Trailing zeros
|
/// Trailing zeros
|
||||||
fn trailing_zeros(&self) -> uint;
|
fn trailing_zeros(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub struct PatriciaTree<K, V> {
|
||||||
skip_len: u8
|
skip_len: u8
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree<K, V> {
|
impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<usize,K>+Shr<usize,K>, V> PatriciaTree<K, V> {
|
||||||
/// Constructs a new Patricia tree
|
/// Constructs a new Patricia tree
|
||||||
pub fn new() -> PatriciaTree<K, V> {
|
pub fn new() -> PatriciaTree<K, V> {
|
||||||
PatriciaTree {
|
PatriciaTree {
|
||||||
|
@ -51,7 +51,7 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup a value by exactly matching `key` and return a referenc
|
/// Lookup a value by exactly matching `key` and return a referenc
|
||||||
pub fn lookup_mut<'a>(&'a mut self, key: &K, key_len: uint) -> Option<&'a mut V> {
|
pub fn lookup_mut<'a>(&'a mut self, key: &K, key_len: usize) -> Option<&'a mut V> {
|
||||||
// Caution: `lookup_mut` never modifies its self parameter (in fact its
|
// Caution: `lookup_mut` never modifies its self parameter (in fact its
|
||||||
// internal recursion uses a non-mutable self, so we are OK to just
|
// internal recursion uses a non-mutable self, so we are OK to just
|
||||||
// transmute our self pointer into a mutable self before passing it in.
|
// transmute our self pointer into a mutable self before passing it in.
|
||||||
|
@ -60,28 +60,28 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup a value by exactly matching `key` and return a mutable reference
|
/// Lookup a value by exactly matching `key` and return a mutable reference
|
||||||
pub fn lookup<'a>(&'a self, key: &K, key_len: uint) -> Option<&'a V> {
|
pub fn lookup<'a>(&'a self, key: &K, key_len: usize) -> Option<&'a V> {
|
||||||
let mut node = self;
|
let mut node = self;
|
||||||
let mut key_idx = 0;
|
let mut key_idx = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// If the search key is shorter than the node prefix, there is no
|
// If the search key is shorter than the node prefix, there is no
|
||||||
// way we can match, so fail.
|
// way we can match, so fail.
|
||||||
if key_len - key_idx < node.skip_len as uint {
|
if key_len - key_idx < node.skip_len as usize {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key fails to match prefix --- no match
|
// Key fails to match prefix --- no match
|
||||||
if node.skip_prefix != key.bit_slice(key_idx, key_idx + node.skip_len as uint) {
|
if node.skip_prefix != key.bit_slice(key_idx, key_idx + node.skip_len as usize) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key matches prefix: if they are an exact match, return the data
|
// Key matches prefix: if they are an exact match, return the data
|
||||||
if node.skip_len as uint == key_len - key_idx {
|
if node.skip_len as usize == key_len - key_idx {
|
||||||
return node.data.as_ref();
|
return node.data.as_ref();
|
||||||
} else {
|
} else {
|
||||||
// Key matches prefix: search key longer than node key, recurse
|
// Key matches prefix: search key longer than node key, recurse
|
||||||
key_idx += 1 + node.skip_len as uint;
|
key_idx += 1 + node.skip_len as usize;
|
||||||
let subtree = if key.bit(key_idx - 1) { &node.child_r } else { &node.child_l };
|
let subtree = if key.bit(key_idx - 1) { &node.child_r } else { &node.child_l };
|
||||||
match subtree {
|
match subtree {
|
||||||
&Some(ref bx) => {
|
&Some(ref bx) => {
|
||||||
|
@ -96,23 +96,23 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
/// Inserts a value with key `key`, returning true on success. If a value is already
|
/// Inserts a value with key `key`, returning true on success. If a value is already
|
||||||
/// stored against `key`, do nothing and return false.
|
/// stored against `key`, do nothing and return false.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn insert(&mut self, key: &K, key_len: uint, value: V) -> bool {
|
pub fn insert(&mut self, key: &K, key_len: usize, value: V) -> bool {
|
||||||
self.real_insert(key, key_len, value, false)
|
self.real_insert(key, key_len, value, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts a value with key `key`, returning true on success. If a value is already
|
/// Inserts a value with key `key`, returning true on success. If a value is already
|
||||||
/// stored against `key`, overwrite it and return false.
|
/// stored against `key`, overwrite it and return false.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn insert_or_update(&mut self, key: &K, key_len: uint, value: V) -> bool {
|
pub fn insert_or_update(&mut self, key: &K, key_len: usize, value: V) -> bool {
|
||||||
self.real_insert(key, key_len, value, true)
|
self.real_insert(key, key_len, value, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn real_insert(&mut self, key: &K, key_len: uint, value: V, overwrite: bool) -> bool {
|
fn real_insert(&mut self, key: &K, key_len: usize, value: V, overwrite: bool) -> bool {
|
||||||
let mut node = self;
|
let mut node = self;
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
loop {
|
loop {
|
||||||
// Mask in case search key is shorter than node key
|
// Mask in case search key is shorter than node key
|
||||||
let slice_len = cmp::min(node.skip_len as uint, key_len - idx);
|
let slice_len = cmp::min(node.skip_len as usize, key_len - idx);
|
||||||
let masked_prefix = node.skip_prefix.mask(slice_len);
|
let masked_prefix = node.skip_prefix.mask(slice_len);
|
||||||
let key_slice = key.bit_slice(idx, idx + slice_len);
|
let key_slice = key.bit_slice(idx, idx + slice_len);
|
||||||
|
|
||||||
|
@ -128,20 +128,20 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
let (insert, neighbor) = if key_slice.bit(diff)
|
let (insert, neighbor) = if key_slice.bit(diff)
|
||||||
{ (&mut tmp.child_r, &mut tmp.child_l) }
|
{ (&mut tmp.child_r, &mut tmp.child_l) }
|
||||||
else { (&mut tmp.child_l, &mut tmp.child_r) };
|
else { (&mut tmp.child_l, &mut tmp.child_r) };
|
||||||
*insert = Some(box PatriciaTree {
|
*insert = Some(Box::new(PatriciaTree {
|
||||||
data: None,
|
data: None,
|
||||||
child_l: None,
|
child_l: None,
|
||||||
child_r: None,
|
child_r: None,
|
||||||
skip_prefix: key.bit_slice(idx + diff + 1, key_len),
|
skip_prefix: key.bit_slice(idx + diff + 1, key_len),
|
||||||
skip_len: (key_len - idx - diff - 1) as u8
|
skip_len: (key_len - idx - diff - 1) as u8
|
||||||
});
|
}));
|
||||||
*neighbor = Some(box PatriciaTree {
|
*neighbor = Some(Box::new(PatriciaTree {
|
||||||
data: value_neighbor,
|
data: value_neighbor,
|
||||||
child_l: child_l,
|
child_l: child_l,
|
||||||
child_r: child_r,
|
child_r: child_r,
|
||||||
skip_prefix: tmp.skip_prefix >> (diff + 1),
|
skip_prefix: tmp.skip_prefix >> (diff + 1),
|
||||||
skip_len: tmp.skip_len - diff as u8 - 1
|
skip_len: tmp.skip_len - diff as u8 - 1
|
||||||
});
|
}));
|
||||||
// Chop the prefix down
|
// Chop the prefix down
|
||||||
tmp.skip_len = diff as u8;
|
tmp.skip_len = diff as u8;
|
||||||
tmp.skip_prefix = tmp.skip_prefix.mask(diff);
|
tmp.skip_prefix = tmp.skip_prefix.mask(diff);
|
||||||
|
@ -154,7 +154,7 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
let slice_len = key_len - idx;
|
let slice_len = key_len - idx;
|
||||||
// Search key is shorter than skip prefix: truncate the prefix and attach
|
// Search key is shorter than skip prefix: truncate the prefix and attach
|
||||||
// the old data as a child
|
// the old data as a child
|
||||||
if node.skip_len as uint > slice_len {
|
if node.skip_len as usize > slice_len {
|
||||||
// Remove the old node's children
|
// Remove the old node's children
|
||||||
let child_l = node.child_l.take();
|
let child_l = node.child_l.take();
|
||||||
let child_r = node.child_r.take();
|
let child_r = node.child_r.take();
|
||||||
|
@ -162,13 +162,13 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
// Put the old data in a new child, with the remainder of the prefix
|
// Put the old data in a new child, with the remainder of the prefix
|
||||||
let new_child = if node.skip_prefix.bit(slice_len)
|
let new_child = if node.skip_prefix.bit(slice_len)
|
||||||
{ &mut node.child_r } else { &mut node.child_l };
|
{ &mut node.child_r } else { &mut node.child_l };
|
||||||
*new_child = Some(box PatriciaTree {
|
*new_child = Some(Box::new(PatriciaTree {
|
||||||
data: value_neighbor,
|
data: value_neighbor,
|
||||||
child_l: child_l,
|
child_l: child_l,
|
||||||
child_r: child_r,
|
child_r: child_r,
|
||||||
skip_prefix: node.skip_prefix >> (slice_len + 1),
|
skip_prefix: node.skip_prefix >> (slice_len + 1),
|
||||||
skip_len: node.skip_len - slice_len as u8 - 1
|
skip_len: node.skip_len - slice_len as u8 - 1
|
||||||
});
|
}));
|
||||||
// Chop the prefix down and put the new data in place
|
// Chop the prefix down and put the new data in place
|
||||||
node.skip_len = slice_len as u8;
|
node.skip_len = slice_len as u8;
|
||||||
node.skip_prefix = key_slice;
|
node.skip_prefix = key_slice;
|
||||||
|
@ -176,7 +176,7 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// If we have an exact match, great, insert it
|
// If we have an exact match, great, insert it
|
||||||
else if node.skip_len as uint == slice_len {
|
else if node.skip_len as usize == slice_len {
|
||||||
if node.data.is_none() {
|
if node.data.is_none() {
|
||||||
node.data = Some(value);
|
node.data = Some(value);
|
||||||
return true;
|
return true;
|
||||||
|
@ -189,18 +189,18 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
// Search key longer than node key, recurse
|
// Search key longer than node key, recurse
|
||||||
else {
|
else {
|
||||||
let tmp = node; // hack to appease borrowck
|
let tmp = node; // hack to appease borrowck
|
||||||
idx += tmp.skip_len as uint + 1;
|
idx += tmp.skip_len as usize + 1;
|
||||||
let subtree = if key.bit(idx - 1)
|
let subtree = if key.bit(idx - 1)
|
||||||
{ &mut tmp.child_r } else { &mut tmp.child_l };
|
{ &mut tmp.child_r } else { &mut tmp.child_l };
|
||||||
// Recurse, adding a new node if necessary
|
// Recurse, adding a new node if necessary
|
||||||
if subtree.is_none() {
|
if subtree.is_none() {
|
||||||
*subtree = Some(box PatriciaTree {
|
*subtree = Some(Box::new(PatriciaTree {
|
||||||
data: None,
|
data: None,
|
||||||
child_l: None,
|
child_l: None,
|
||||||
child_r: None,
|
child_r: None,
|
||||||
skip_prefix: key.bit_slice(idx, key_len),
|
skip_prefix: key.bit_slice(idx, key_len),
|
||||||
skip_len: key_len as u8 - idx as u8
|
skip_len: key_len as u8 - idx as u8
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
// subtree.get_mut_ref is a &mut Box<U> here, so &mut ** gets a &mut U
|
// subtree.get_mut_ref is a &mut Box<U> here, so &mut ** gets a &mut U
|
||||||
node = &mut **subtree.as_mut().unwrap();
|
node = &mut **subtree.as_mut().unwrap();
|
||||||
|
@ -211,23 +211,23 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
|
|
||||||
/// Deletes a value with key `key`, returning it on success. If no value with
|
/// Deletes a value with key `key`, returning it on success. If no value with
|
||||||
/// the given key is found, return None
|
/// the given key is found, return None
|
||||||
pub fn delete(&mut self, key: &K, key_len: uint) -> Option<V> {
|
pub fn delete(&mut self, key: &K, key_len: usize) -> Option<V> {
|
||||||
/// Return value is (deletable, actual return value), where `deletable` is true
|
/// Return value is (deletable, actual return value), where `deletable` is true
|
||||||
/// is true when the entire node can be deleted (i.e. it has no children)
|
/// is true when the entire node can be deleted (i.e. it has no children)
|
||||||
fn recurse<K:BitArray+Eq+Zero+One+Add<K,K>+Shr<uint,K>+Shl<uint,K>, V>(tree: &mut PatriciaTree<K, V>, key: &K, key_len: uint) -> (bool, Option<V>) {
|
fn recurse<K:BitArray+Eq+Zero+One+Add<K,K>+Shr<usize,K>+Shl<usize,K>, V>(tree: &mut PatriciaTree<K, V>, key: &K, key_len: usize) -> (bool, Option<V>) {
|
||||||
// If the search key is shorter than the node prefix, there is no
|
// If the search key is shorter than the node prefix, there is no
|
||||||
// way we can match, so fail.
|
// way we can match, so fail.
|
||||||
if key_len < tree.skip_len as uint {
|
if key_len < tree.skip_len as usize {
|
||||||
return (false, None);
|
return (false, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key fails to match prefix --- no match
|
// Key fails to match prefix --- no match
|
||||||
if tree.skip_prefix != key.mask(tree.skip_len as uint) {
|
if tree.skip_prefix != key.mask(tree.skip_len as usize) {
|
||||||
return (false, None);
|
return (false, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are here, the key matches the prefix
|
// If we are here, the key matches the prefix
|
||||||
if tree.skip_len as uint == key_len {
|
if tree.skip_len as usize == key_len {
|
||||||
// Exact match -- delete and return
|
// Exact match -- delete and return
|
||||||
let ret = tree.data.take();
|
let ret = tree.data.take();
|
||||||
let bit = tree.child_r.is_some();
|
let bit = tree.child_r.is_some();
|
||||||
|
@ -238,17 +238,17 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
}
|
}
|
||||||
match (tree.child_l.take(), tree.child_r.take()) {
|
match (tree.child_l.take(), tree.child_r.take()) {
|
||||||
(Some(_), Some(_)) => unreachable!(),
|
(Some(_), Some(_)) => unreachable!(),
|
||||||
(Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len }), None) |
|
(Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })), None) |
|
||||||
(None, Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })) => {
|
(None, Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len }))) => {
|
||||||
tree.data = data;
|
tree.data = data;
|
||||||
tree.child_l = child_l;
|
tree.child_l = child_l;
|
||||||
tree.child_r = child_r;
|
tree.child_r = child_r;
|
||||||
let new_bit = if bit { let ret: K = One::one();
|
let new_bit = if bit { let ret: K = One::one();
|
||||||
ret << (tree.skip_len as uint) }
|
ret << (tree.skip_len as usize) }
|
||||||
else { Zero::zero() };
|
else { Zero::zero() };
|
||||||
tree.skip_prefix = tree.skip_prefix +
|
tree.skip_prefix = tree.skip_prefix +
|
||||||
new_bit +
|
new_bit +
|
||||||
(skip_prefix << (1 + tree.skip_len as uint));
|
(skip_prefix << (1 + tree.skip_len as usize));
|
||||||
tree.skip_len += 1 + skip_len;
|
tree.skip_len += 1 + skip_len;
|
||||||
return (false, ret);
|
return (false, ret);
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, the key is longer than the prefix and we need to recurse
|
// Otherwise, the key is longer than the prefix and we need to recurse
|
||||||
let next_bit = key.bit(tree.skip_len as uint);
|
let next_bit = key.bit(tree.skip_len as usize);
|
||||||
// Recursively get the return value. This awkward scope is required
|
// Recursively get the return value. This awkward scope is required
|
||||||
// to shorten the time we mutably borrow the node's children -- we
|
// to shorten the time we mutably borrow the node's children -- we
|
||||||
// might want to borrow the sibling later, so the borrow needs to end.
|
// might want to borrow the sibling later, so the borrow needs to end.
|
||||||
|
@ -271,8 +271,8 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
}
|
}
|
||||||
// Otherwise, do it
|
// Otherwise, do it
|
||||||
let (delete_child, ret) = recurse(&mut **target.as_mut().unwrap(),
|
let (delete_child, ret) = recurse(&mut **target.as_mut().unwrap(),
|
||||||
&key.shr(&(tree.skip_len as uint + 1)),
|
&key.shr(&(tree.skip_len as usize + 1)),
|
||||||
key_len - tree.skip_len as uint - 1);
|
key_len - tree.skip_len as usize - 1);
|
||||||
if delete_child {
|
if delete_child {
|
||||||
target.take();
|
target.take();
|
||||||
}
|
}
|
||||||
|
@ -296,17 +296,17 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
return (false, ret);
|
return (false, ret);
|
||||||
}
|
}
|
||||||
// One child? Consolidate
|
// One child? Consolidate
|
||||||
(bit, Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len }), None) |
|
(bit, Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })), None) |
|
||||||
(bit, None, Some(box PatriciaTree { data, child_l, child_r, skip_prefix, skip_len })) => {
|
(bit, None, Some(Box::new(PatriciaTree { data, child_l, child_r, skip_prefix, skip_len }))) => {
|
||||||
tree.data = data;
|
tree.data = data;
|
||||||
tree.child_l = child_l;
|
tree.child_l = child_l;
|
||||||
tree.child_r = child_r;
|
tree.child_r = child_r;
|
||||||
let new_bit = if bit { let ret: K = One::one();
|
let new_bit = if bit { let ret: K = One::one();
|
||||||
ret << (tree.skip_len as uint) }
|
ret << (tree.skip_len as usize) }
|
||||||
else { Zero::zero() };
|
else { Zero::zero() };
|
||||||
tree.skip_prefix = tree.skip_prefix +
|
tree.skip_prefix = tree.skip_prefix +
|
||||||
new_bit +
|
new_bit +
|
||||||
(skip_prefix << (1 + tree.skip_len as uint));
|
(skip_prefix << (1 + tree.skip_len as usize));
|
||||||
tree.skip_len += 1 + skip_len;
|
tree.skip_len += 1 + skip_len;
|
||||||
return (false, ret);
|
return (false, ret);
|
||||||
}
|
}
|
||||||
|
@ -321,8 +321,8 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Count all the nodes
|
/// Count all the nodes
|
||||||
pub fn node_count(&self) -> uint {
|
pub fn node_count(&self) -> usize {
|
||||||
fn recurse<K, V>(node: &Option<Box<PatriciaTree<K, V>>>) -> uint {
|
fn recurse<K, V>(node: &Option<Box<PatriciaTree<K, V>>>) -> usize {
|
||||||
match node {
|
match node {
|
||||||
&Some(ref node) => { 1 + recurse(&node.child_l) + recurse(&node.child_r) }
|
&Some(ref node) => { 1 + recurse(&node.child_l) + recurse(&node.child_r) }
|
||||||
&None => 0
|
&None => 0
|
||||||
|
@ -354,30 +354,30 @@ impl<K:BitArray+Eq+Zero+One+BitXor<K,K>+Shl<uint,K>+Shr<uint,K>, V> PatriciaTree
|
||||||
impl<K:BitArray, V:Show> PatriciaTree<K, V> {
|
impl<K:BitArray, V:Show> PatriciaTree<K, V> {
|
||||||
/// Print the entire tree
|
/// Print the entire tree
|
||||||
pub fn print<'a>(&'a self) {
|
pub fn print<'a>(&'a self) {
|
||||||
fn recurse<'a, K:BitArray, V:Show>(tree: &'a PatriciaTree<K, V>, depth: uint) {
|
fn recurse<'a, K:BitArray, V:Show>(tree: &'a PatriciaTree<K, V>, depth: usize) {
|
||||||
for i in range(0, tree.skip_len as uint) {
|
for i in range(0, tree.skip_len as usize) {
|
||||||
print!("{:}", if tree.skip_prefix.bit(i) { 1u } else { 0 });
|
print!("{:}", if tree.skip_prefix.bit(i) { 1 } else { 0 });
|
||||||
}
|
}
|
||||||
println!(": {:}", tree.data);
|
println!(": {:}", tree.data);
|
||||||
// left gets no indentation
|
// left gets no indentation
|
||||||
match tree.child_l {
|
match tree.child_l {
|
||||||
Some(ref t) => {
|
Some(ref t) => {
|
||||||
for _ in range(0, depth + tree.skip_len as uint) {
|
for _ in range(0, depth + tree.skip_len as usize) {
|
||||||
print!("-");
|
print!("-");
|
||||||
}
|
}
|
||||||
print!("0");
|
print!("0");
|
||||||
recurse(&**t, depth + tree.skip_len as uint + 1);
|
recurse(&**t, depth + tree.skip_len as usize + 1);
|
||||||
}
|
}
|
||||||
None => { }
|
None => { }
|
||||||
}
|
}
|
||||||
// right one gets indentation
|
// right one gets indentation
|
||||||
match tree.child_r {
|
match tree.child_r {
|
||||||
Some(ref t) => {
|
Some(ref t) => {
|
||||||
for _ in range(0, depth + tree.skip_len as uint) {
|
for _ in range(0, depth + tree.skip_len as usize) {
|
||||||
print!("_");
|
print!("_");
|
||||||
}
|
}
|
||||||
print!("1");
|
print!("1");
|
||||||
recurse(&**t, depth + tree.skip_len as uint + 1);
|
recurse(&**t, depth + tree.skip_len as usize + 1);
|
||||||
}
|
}
|
||||||
None => { }
|
None => { }
|
||||||
}
|
}
|
||||||
|
@ -529,8 +529,8 @@ mod tests {
|
||||||
|
|
||||||
use network::serialize::{deserialize, serialize};
|
use network::serialize::{deserialize, serialize};
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
use util::uint::Uint128;
|
use util::usize::Uint128;
|
||||||
use util::uint::Uint256;
|
use util::usize::Uint256;
|
||||||
use util::patricia_tree::PatriciaTree;
|
use util::patricia_tree::PatriciaTree;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -601,14 +601,14 @@ mod tests {
|
||||||
// Do the actual test -- note that we also test insertion and deletion
|
// Do the actual test -- note that we also test insertion and deletion
|
||||||
// at the root here.
|
// at the root here.
|
||||||
for i in range(0u32, 10) {
|
for i in range(0u32, 10) {
|
||||||
tree.insert(&Zero::zero(), i as uint, i);
|
tree.insert(&Zero::zero(), i as usize, i);
|
||||||
}
|
}
|
||||||
for i in range(0u32, 10) {
|
for i in range(0u32, 10) {
|
||||||
let m = tree.lookup(&Zero::zero(), i as uint);
|
let m = tree.lookup(&Zero::zero(), i as usize);
|
||||||
assert_eq!(m, Some(&i));
|
assert_eq!(m, Some(&i));
|
||||||
}
|
}
|
||||||
for i in range(0u32, 10) {
|
for i in range(0u32, 10) {
|
||||||
let m = tree.delete(&Zero::zero(), i as uint);
|
let m = tree.delete(&Zero::zero(), i as usize);
|
||||||
assert_eq!(m, Some(i));
|
assert_eq!(m, Some(i));
|
||||||
}
|
}
|
||||||
// Check that the chunder was unharmed
|
// Check that the chunder was unharmed
|
||||||
|
|
|
@ -44,7 +44,7 @@ impl<T> ThinVec<T> {
|
||||||
} else if capacity == 0 {
|
} else if capacity == 0 {
|
||||||
ThinVec::new()
|
ThinVec::new()
|
||||||
} else {
|
} else {
|
||||||
let size = (capacity as uint).checked_mul(&mem::size_of::<T>())
|
let size = (capacity as usize).checked_mul(&mem::size_of::<T>())
|
||||||
.expect("ThinVec::reserve: capacity overflow");
|
.expect("ThinVec::reserve: capacity overflow");
|
||||||
let ptr = allocate(size, mem::min_align_of::<T>());
|
let ptr = allocate(size, mem::min_align_of::<T>());
|
||||||
ThinVec { ptr: ptr as *mut T, cap: capacity }
|
ThinVec { ptr: ptr as *mut T, cap: capacity }
|
||||||
|
@ -55,7 +55,7 @@ impl<T> ThinVec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_vec(mut v: Vec<T>) -> ThinVec<T> {
|
pub fn from_vec(mut v: Vec<T>) -> ThinVec<T> {
|
||||||
v.shrink_to_fit();
|
v.shrink_to_fit();
|
||||||
assert!(v.len() <= u32::MAX as uint);
|
assert!(v.len() <= u32::MAX as usize);
|
||||||
let ret = ThinVec { ptr: v.as_mut_ptr(), cap: v.len() as u32 };
|
let ret = ThinVec { ptr: v.as_mut_ptr(), cap: v.len() as u32 };
|
||||||
unsafe { mem::forget(v); }
|
unsafe { mem::forget(v); }
|
||||||
ret
|
ret
|
||||||
|
@ -69,49 +69,49 @@ impl<T> ThinVec<T> {
|
||||||
|
|
||||||
/// Mutable iterator over elements of the vector
|
/// Mutable iterator over elements of the vector
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T> {
|
pub fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T> {
|
||||||
self.as_mut_slice().mut_iter()
|
self.as_mut_slice().iter_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get vector as mutable slice
|
/// Get vector as mutable slice
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
|
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 uint }) }
|
unsafe { mem::transmute(raw::Slice { data: self.ptr as *const T, len: self.cap as usize }) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accessor
|
/// Accessor
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn get<'a>(&'a self, index: uint) -> &'a T {
|
pub unsafe fn get<'a>(&'a self, index: usize) -> &'a T {
|
||||||
&self.as_slice()[index]
|
&self.as_slice()[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutable accessor NOT for first use
|
/// Mutable accessor NOT for first use
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
|
pub unsafe fn get_mut<'a>(&'a mut self, index: usize) -> &'a mut T {
|
||||||
&mut self.as_mut_slice()[index]
|
&mut self.as_mut_slice()[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutable accessor for first use
|
/// Mutable accessor for first use
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn init<'a>(&'a mut self, index: uint, value: T) {
|
pub unsafe fn init<'a>(&'a mut self, index: usize, value: T) {
|
||||||
ptr::write(&mut *self.ptr.offset(index as int), value);
|
ptr::write(&mut *self.ptr.offset(index as isize), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a slice starting from `index`
|
/// Returns a slice starting from `index`
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn slice_from<'a>(&'a self, index: uint) -> &'a [T] {
|
pub fn slice_from<'a>(&'a self, index: usize) -> &'a [T] {
|
||||||
self.as_slice().slice_from(index)
|
self.as_slice().slice_from(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a slice ending just before `index`
|
/// Returns a slice ending just before `index`
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn slice_to<'a>(&'a self, index: uint) -> &'a [T] {
|
pub fn slice_to<'a>(&'a self, index: usize) -> &'a [T] {
|
||||||
self.as_slice().slice_to(index)
|
self.as_slice().slice_to(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a slice starting from `s` ending just before `e`
|
/// Returns a slice starting from `s` ending just before `e`
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn slice<'a>(&'a self, s: uint, e: uint) -> &'a [T] {
|
pub fn slice<'a>(&'a self, s: usize, e: usize) -> &'a [T] {
|
||||||
self.as_slice().slice(s, e)
|
self.as_slice().slice(s, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,18 +122,18 @@ impl<T> ThinVec<T> {
|
||||||
if mem::size_of::<T>() == 0 {
|
if mem::size_of::<T>() == 0 {
|
||||||
unsafe { mem::forget(value); }
|
unsafe { mem::forget(value); }
|
||||||
} else {
|
} else {
|
||||||
let old_size = (self.cap - 1) as uint * mem::size_of::<T>();
|
let old_size = (self.cap - 1) as usize * mem::size_of::<T>();
|
||||||
let new_size = self.cap as uint * mem::size_of::<T>();
|
let new_size = self.cap as usize * mem::size_of::<T>();
|
||||||
if new_size < old_size { fail!("ThinVec::push: cap overflow") }
|
if new_size < old_size { panic!("ThinVec::push: cap overflow") }
|
||||||
unsafe {
|
unsafe {
|
||||||
self.ptr =
|
self.ptr =
|
||||||
if old_size == 0 {
|
if old_size == 0 {
|
||||||
allocate(new_size, mem::min_align_of::<T>()) as *mut T
|
allocate(new_size, mem::min_align_of::<T>()) as *mut T
|
||||||
} else {
|
} else {
|
||||||
reallocate(self.ptr as *mut u8, new_size,
|
reallocate(self.ptr as *mut u8, new_size,
|
||||||
mem::min_align_of::<T>(), self.cap as uint) as *mut T
|
mem::min_align_of::<T>(), self.cap as usize) as *mut T
|
||||||
};
|
};
|
||||||
ptr::write(&mut *self.ptr.offset((self.cap - 1) as int), value);
|
ptr::write(&mut *self.ptr.offset((self.cap - 1) as isize), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,14 +141,14 @@ impl<T> ThinVec<T> {
|
||||||
/// Set the length of the vector to the minimum of the current capacity and new capacity
|
/// 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) {
|
pub unsafe fn reserve(&mut self, new_cap: u32) {
|
||||||
if new_cap > self.cap {
|
if new_cap > self.cap {
|
||||||
let new_size = (new_cap as uint).checked_mul(&mem::size_of::<T>())
|
let new_size = (new_cap as usize).checked_mul(&mem::size_of::<T>())
|
||||||
.expect("ThinVec::reserve: capacity overflow");
|
.expect("ThinVec::reserve: capacity overflow");
|
||||||
self.ptr =
|
self.ptr =
|
||||||
if self.cap == 0 {
|
if self.cap == 0 {
|
||||||
allocate(new_size, mem::min_align_of::<T>()) as *mut T
|
allocate(new_size, mem::min_align_of::<T>()) as *mut T
|
||||||
} else {
|
} else {
|
||||||
reallocate(self.ptr as *mut u8, new_size,
|
reallocate(self.ptr as *mut u8, new_size,
|
||||||
mem::min_align_of::<T>(), self.cap as uint) as *mut T
|
mem::min_align_of::<T>(), self.cap as usize) as *mut T
|
||||||
};
|
};
|
||||||
self.cap = new_cap;
|
self.cap = new_cap;
|
||||||
}
|
}
|
||||||
|
@ -165,29 +165,33 @@ impl<T:Clone> ThinVec<T> {
|
||||||
/// Push an entire slice onto the ThinVec
|
/// Push an entire slice onto the ThinVec
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn push_all(&mut self, other: &[T]) {
|
pub fn push_all(&mut self, other: &[T]) {
|
||||||
let old_cap = self.cap as uint;
|
let old_cap = self.cap as usize;
|
||||||
unsafe { self.reserve_additional(other.len() as u32); }
|
unsafe { self.reserve_additional(other.len() as u32); }
|
||||||
// Copied from vec.rs, which claims this will be optimized to a memcpy
|
// Copied from vec.rs, which claims this will be optimized to a memcpy
|
||||||
// if T is Copy
|
// if T is Copy
|
||||||
for i in range(0, other.len()) {
|
for i in range(0, other.len()) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::write(self.as_mut_slice().unsafe_mut_ref(old_cap + i),
|
ptr::write(self.as_mut_slice().unsafe_mut(old_cap + i),
|
||||||
other.unsafe_get(i).clone());
|
other.unsafe_get(i).clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructor from a slice
|
impl<T:Clone> CloneableVector<T> for ThinVec<T> {
|
||||||
#[inline]
|
fn to_vec(&self) -> Vec<T> {
|
||||||
pub fn from_slice(v: &[T]) -> ThinVec<T> {
|
self.as_slice().to_vec()
|
||||||
ThinVec::from_vec(Vec::from_slice(v))
|
}
|
||||||
|
|
||||||
|
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> {
|
impl<T> Slice<T> for ThinVec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_slice<'a>(&'a self) -> &'a [T] {
|
fn as_slice<'a>(&'a self) -> &'a [T] {
|
||||||
unsafe { mem::transmute(raw::Slice { data: self.ptr as *const T, len: self.cap as uint }) }
|
unsafe { mem::transmute(raw::Slice { data: self.ptr as *const T, len: self.cap as usize }) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +202,7 @@ impl<T:Clone> Clone for ThinVec<T> {
|
||||||
// Copied from vec.rs, which claims this will be optimized to a memcpy
|
// Copied from vec.rs, which claims this will be optimized to a memcpy
|
||||||
// if T is Copy
|
// if T is Copy
|
||||||
for i in range(0, self.len()) {
|
for i in range(0, self.len()) {
|
||||||
ptr::write(ret.as_mut_slice().unsafe_mut_ref(i),
|
ptr::write(ret.as_mut_slice().unsafe_mut(i),
|
||||||
self.as_slice().unsafe_get(i).clone());
|
self.as_slice().unsafe_get(i).clone());
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
|
@ -212,7 +216,7 @@ impl<T> FromIterator<T> for ThinVec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_iter<I: Iterator<T>>(iter: I) -> ThinVec<T> {
|
fn from_iter<I: Iterator<T>>(iter: I) -> ThinVec<T> {
|
||||||
let (lower, _) = iter.size_hint();
|
let (lower, _) = iter.size_hint();
|
||||||
assert!(lower <= u32::MAX as uint);
|
assert!(lower <= u32::MAX as usize);
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut vector = ThinVec::with_capacity(lower as u32);
|
let mut vector = ThinVec::with_capacity(lower as u32);
|
||||||
for (n, elem) in iter.enumerate() {
|
for (n, elem) in iter.enumerate() {
|
||||||
|
@ -235,7 +239,7 @@ impl<T> Extendable<T> for ThinVec<T> {
|
||||||
unsafe { self.reserve_additional(lower as u32); }
|
unsafe { self.reserve_additional(lower as u32); }
|
||||||
for (n, elem) in iter.enumerate() {
|
for (n, elem) in iter.enumerate() {
|
||||||
if n < lower {
|
if n < lower {
|
||||||
unsafe { self.init(old_cap as uint + n, elem) };
|
unsafe { self.init(old_cap as usize + n, elem) };
|
||||||
} else {
|
} else {
|
||||||
self.push(elem);
|
self.push(elem);
|
||||||
}
|
}
|
||||||
|
@ -245,7 +249,7 @@ impl<T> Extendable<T> for ThinVec<T> {
|
||||||
|
|
||||||
impl<T> Collection for ThinVec<T> {
|
impl<T> Collection for ThinVec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn len(&self) -> uint { self.cap as uint }
|
fn len(&self) -> usize { self.cap as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T:fmt::Show> fmt::Show for ThinVec<T> {
|
impl<T:fmt::Show> fmt::Show for ThinVec<T> {
|
||||||
|
@ -273,7 +277,7 @@ impl<T> Drop for ThinVec<T> {
|
||||||
}
|
}
|
||||||
if mem::size_of::<T>() != 0 {
|
if mem::size_of::<T>() != 0 {
|
||||||
deallocate(self.ptr as *mut u8,
|
deallocate(self.ptr as *mut u8,
|
||||||
self.cap as uint * mem::size_of::<T>(),
|
self.cap as usize * mem::size_of::<T>(),
|
||||||
mem::min_align_of::<T>());
|
mem::min_align_of::<T>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,12 +296,12 @@ mod tests {
|
||||||
let mut thinvec = ThinVec::with_capacity(cap);
|
let mut thinvec = ThinVec::with_capacity(cap);
|
||||||
|
|
||||||
for i in range(0, cap) {
|
for i in range(0, cap) {
|
||||||
thinvec.init(i as uint, Some(box i));
|
thinvec.init(i, Some(Box::new(i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in range(0, cap) {
|
for i in range(0, cap) {
|
||||||
assert_eq!(thinvec.get_mut(i as uint).take(), Some(box i));
|
assert_eq!(thinvec.get_mut(i).take(), Some(Box::new(i)));
|
||||||
assert_eq!(thinvec.get_mut(i as uint).take(), None);
|
assert_eq!(thinvec.get_mut(i).take(), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
104
src/util/uint.rs
104
src/util/uint.rs
|
@ -24,12 +24,12 @@ use std::num::{Zero, One};
|
||||||
use network::serialize::RawEncoder;
|
use network::serialize::RawEncoder;
|
||||||
use util::BitArray;
|
use util::BitArray;
|
||||||
|
|
||||||
macro_rules! construct_uint(
|
macro_rules! construct_uint {
|
||||||
($name:ident, $n_words:expr) => (
|
($name:ident, $n_words:expr) => (
|
||||||
/// Little-endian large integer type
|
/// Little-endian large integer type
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct $name(pub [u64, ..$n_words]);
|
pub struct $name(pub [u64; $n_words]);
|
||||||
impl_array_newtype!($name, u64, $n_words)
|
impl_array_newtype!($name, u64, $n_words);
|
||||||
|
|
||||||
impl $name {
|
impl $name {
|
||||||
/// Conversion to u32
|
/// Conversion to u32
|
||||||
|
@ -41,20 +41,20 @@ 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) -> uint {
|
pub fn bits(&self) -> uzise {
|
||||||
let &$name(ref arr) = self;
|
let &$name(ref arr) = self;
|
||||||
for i in range(1u, $n_words) {
|
for i in range(1, $n_words) {
|
||||||
if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as uint; }
|
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() as uint
|
0x40 - arr[0].leading_zeros()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Multiplication by u32
|
/// Multiplication by u32
|
||||||
pub fn mul_u32(&self, other: u32) -> $name {
|
pub fn mul_u32(&self, other: u32) -> $name {
|
||||||
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(0u, $n_words) {
|
for i in range(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 {
|
||||||
|
@ -69,7 +69,7 @@ macro_rules! construct_uint(
|
||||||
impl FromPrimitive for $name {
|
impl FromPrimitive for $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_u64(init: u64) -> Option<$name> {
|
fn from_u64(init: u64) -> Option<$name> {
|
||||||
let mut ret = [0, ..$n_words];
|
let mut ret = [0; $n_words];
|
||||||
ret[0] = init;
|
ret[0] = init;
|
||||||
Some($name(ret))
|
Some($name(ret))
|
||||||
}
|
}
|
||||||
|
@ -81,13 +81,13 @@ macro_rules! construct_uint(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Zero for $name {
|
impl Zero for $name {
|
||||||
fn zero() -> $name { $name([0, ..$n_words]) }
|
fn zero() -> $name { $name([0; $n_words]) }
|
||||||
fn is_zero(&self) -> bool { *self == Zero::zero() }
|
fn is_zero(&self) -> bool { *self == Zero::zero() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl One for $name {
|
impl One for $name {
|
||||||
fn one() -> $name {
|
fn one() -> $name {
|
||||||
$name({ let mut ret = [0, ..$n_words]; ret[0] = 1; ret })
|
$name({ let mut ret = [0; $n_words]; ret[0] = 1; ret })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,10 +95,10 @@ macro_rules! construct_uint(
|
||||||
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(0u, $n_words) {
|
for i in range(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;
|
||||||
|
@ -120,7 +120,7 @@ macro_rules! construct_uint(
|
||||||
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(0u, 2 * $n_words) {
|
for i in range(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
|
||||||
|
@ -131,7 +131,7 @@ macro_rules! construct_uint(
|
||||||
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;
|
||||||
let mut ret = [0u64, ..$n_words];
|
let mut ret = [0u64; $n_words];
|
||||||
|
|
||||||
let my_bits = self.bits();
|
let my_bits = self.bits();
|
||||||
let your_bits = other.bits();
|
let your_bits = other.bits();
|
||||||
|
@ -163,21 +163,21 @@ macro_rules! construct_uint(
|
||||||
|
|
||||||
impl BitArray for $name {
|
impl BitArray for $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bit(&self, index: uint) -> bool {
|
fn bit(&self, index: usize) -> bool {
|
||||||
let &$name(ref arr) = self;
|
let &$name(ref arr) = self;
|
||||||
arr[index / 64] & (1 << (index % 64)) != 0
|
arr[index / 64] & (1 << (index % 64)) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bit_slice(&self, start: uint, end: uint) -> $name {
|
fn bit_slice(&self, start: usize, end: usize) -> $name {
|
||||||
(self >> start).mask(end - start)
|
(self >> start).mask(end - start)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mask(&self, n: uint) -> $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(0u, $n_words) {
|
for i in range(0, $n_words) {
|
||||||
if n >= 0x40 * (i + 1) {
|
if n >= 0x40 * (i + 1) {
|
||||||
ret[i] = arr[i];
|
ret[i] = arr[i];
|
||||||
} else {
|
} else {
|
||||||
|
@ -189,12 +189,12 @@ macro_rules! construct_uint(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn trailing_zeros(&self) -> uint {
|
fn trailing_zeros(&self) -> usize {
|
||||||
let &$name(ref arr) = self;
|
let &$name(ref arr) = self;
|
||||||
for i in range(0u, $n_words - 1) {
|
for i in range(0, $n_words - 1) {
|
||||||
if arr[i] > 0 { return (0x40 * i) + arr[i].trailing_zeros() as uint; }
|
if arr[i] > 0 { return (0x40 * i) + arr[i].trailing_zeros(); }
|
||||||
}
|
}
|
||||||
(0x40 * ($n_words - 1)) + arr[3].trailing_zeros() as uint
|
(0x40 * ($n_words - 1)) + arr[3].trailing_zeros()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,8 +203,8 @@ macro_rules! construct_uint(
|
||||||
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(0u, $n_words) {
|
for i in range(0, $n_words) {
|
||||||
ret[i] = arr1[i] & arr2[i];
|
ret[i] = arr1[i] & arr2[i];
|
||||||
}
|
}
|
||||||
$name(ret)
|
$name(ret)
|
||||||
|
@ -216,8 +216,8 @@ macro_rules! construct_uint(
|
||||||
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(0u, $n_words) {
|
for i in range(0, $n_words) {
|
||||||
ret[i] = arr1[i] ^ arr2[i];
|
ret[i] = arr1[i] ^ arr2[i];
|
||||||
}
|
}
|
||||||
$name(ret)
|
$name(ret)
|
||||||
|
@ -229,8 +229,8 @@ macro_rules! construct_uint(
|
||||||
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(0u, $n_words) {
|
for i in range(0, $n_words) {
|
||||||
ret[i] = arr1[i] | arr2[i];
|
ret[i] = arr1[i] | arr2[i];
|
||||||
}
|
}
|
||||||
$name(ret)
|
$name(ret)
|
||||||
|
@ -241,21 +241,21 @@ macro_rules! construct_uint(
|
||||||
#[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(0u, $n_words) {
|
for i in range(0, $n_words) {
|
||||||
ret[i] = !arr[i];
|
ret[i] = !arr[i];
|
||||||
}
|
}
|
||||||
$name(ret)
|
$name(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Shl<uint,$name> for $name {
|
impl Shl<usize, $name> for $name {
|
||||||
fn shl(&self, shift: &uint) -> $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(0u, $n_words) {
|
for i in range(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 +269,14 @@ macro_rules! construct_uint(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Shr<uint,$name> for $name {
|
impl Shr<usize, $name> for $name {
|
||||||
#[allow(unsigned_negate)]
|
#[allow(unsigned_negate)]
|
||||||
fn shr(&self, shift: &uint) -> $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(0u, $n_words) {
|
for i in range(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;
|
||||||
|
@ -330,15 +330,15 @@ macro_rules! construct_uint(
|
||||||
impl<D: ::network::serialize::SimpleDecoder<E>, E> ::network::encodable::ConsensusDecodable<D, E> for $name {
|
impl<D: ::network::serialize::SimpleDecoder<E>, E> ::network::encodable::ConsensusDecodable<D, E> for $name {
|
||||||
fn consensus_decode(d: &mut D) -> Result<$name, E> {
|
fn consensus_decode(d: &mut D) -> Result<$name, E> {
|
||||||
use network::encodable::ConsensusDecodable;
|
use network::encodable::ConsensusDecodable;
|
||||||
let ret: [u64, ..$n_words] = try!(ConsensusDecodable::consensus_decode(d));
|
let ret: [u64; $n_words] = try!(ConsensusDecodable::consensus_decode(d));
|
||||||
Ok($name(ret))
|
Ok($name(ret))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
)
|
}
|
||||||
|
|
||||||
construct_uint!(Uint256, 4)
|
construct_uint!(Uint256, 4);
|
||||||
construct_uint!(Uint128, 2)
|
construct_uint!(Uint128, 2);
|
||||||
|
|
||||||
impl Uint256 {
|
impl Uint256 {
|
||||||
/// Increment by 1
|
/// Increment by 1
|
||||||
|
@ -384,11 +384,11 @@ mod tests {
|
||||||
|
|
||||||
// Try to read the following lines out loud quickly
|
// Try to read the following lines out loud quickly
|
||||||
let mut shl: Uint256 = from_u64(70000).unwrap();
|
let mut shl: Uint256 = from_u64(70000).unwrap();
|
||||||
shl = shl << 100u;
|
shl = shl << 100;
|
||||||
assert_eq!(shl.bits(), 117);
|
assert_eq!(shl.bits(), 117);
|
||||||
shl = shl << 100u;
|
shl = shl << 100;
|
||||||
assert_eq!(shl.bits(), 217);
|
assert_eq!(shl.bits(), 217);
|
||||||
shl = shl << 100u;
|
shl = shl << 100;
|
||||||
assert_eq!(shl.bits(), 0);
|
assert_eq!(shl.bits(), 0);
|
||||||
|
|
||||||
// Bit set check
|
// Bit set check
|
||||||
|
@ -424,9 +424,9 @@ mod tests {
|
||||||
let add = init.add(©);
|
let add = init.add(©);
|
||||||
assert_eq!(add, Uint256([0xBD5B7DDFBD5B7DDEu64, 1, 0, 0]));
|
assert_eq!(add, Uint256([0xBD5B7DDFBD5B7DDEu64, 1, 0, 0]));
|
||||||
// Bitshifts
|
// Bitshifts
|
||||||
let shl = add << 88u;
|
let shl = add << 88;
|
||||||
assert_eq!(shl, Uint256([0u64, 0xDFBD5B7DDE000000, 0x1BD5B7D, 0]));
|
assert_eq!(shl, Uint256([0u64, 0xDFBD5B7DDE000000, 0x1BD5B7D, 0]));
|
||||||
let shr = shl >> 40u;
|
let shr = shl >> 40;
|
||||||
assert_eq!(shr, Uint256([0x7DDE000000000000u64, 0x0001BD5B7DDFBD5B, 0, 0]));
|
assert_eq!(shr, Uint256([0x7DDE000000000000u64, 0x0001BD5B7DDFBD5B, 0, 0]));
|
||||||
// Increment
|
// Increment
|
||||||
let mut incr = shr;
|
let mut incr = shr;
|
||||||
|
|
|
@ -38,15 +38,6 @@ pub struct Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
/// Creates an address the raw 20 bytes of a hash
|
|
||||||
#[inline]
|
|
||||||
pub fn from_slice(network: Network, data: &[u8]) -> Address {
|
|
||||||
Address {
|
|
||||||
network: network,
|
|
||||||
hash: Ripemd160Hash::from_slice(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a byteslice view of the `Address` --- note that no network information
|
/// Returns a byteslice view of the `Address` --- note that no network information
|
||||||
/// is contained in this.
|
/// is contained in this.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -80,6 +71,22 @@ impl Address {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Conversion from other types into an address
|
||||||
|
pub trait ToAddress {
|
||||||
|
/// Copies `self` into a new `Address`
|
||||||
|
fn to_address(&self, network: Network) -> Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToAddress for &'a [u8] {
|
||||||
|
#[inline]
|
||||||
|
fn to_address(&self, network: Network) -> Address {
|
||||||
|
Address {
|
||||||
|
network: network,
|
||||||
|
hash: Ripemd160Hash::from_slice(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToBase58 for Address {
|
impl ToBase58 for Address {
|
||||||
fn base58_layout(&self) -> Vec<u8> {
|
fn base58_layout(&self) -> Vec<u8> {
|
||||||
let mut ret = vec![
|
let mut ret = vec![
|
||||||
|
|
|
@ -21,18 +21,46 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use collections::hash::sip::hash_with_keys;
|
use collections::hash::sip::hash_with_keys;
|
||||||
|
|
||||||
|
use secp256k1::key::SecretKey;
|
||||||
|
|
||||||
use blockdata::transaction::{TxOut, PayToPubkeyHash};
|
use blockdata::transaction::{TxOut, PayToPubkeyHash};
|
||||||
use blockdata::utxoset::UtxoSet;
|
use blockdata::utxoset::UtxoSet;
|
||||||
use blockdata::script::Script;
|
use blockdata::script::Script;
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
use wallet::address::Address;
|
use wallet::address::Address;
|
||||||
use wallet::wallet::Wallet;
|
use wallet::wallet::Wallet;
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::{DumbHasher, Sha256dHash};
|
||||||
|
|
||||||
|
/// The type of a wallet-spendable txout
|
||||||
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
|
pub enum WalletTxOutType {
|
||||||
|
/// Pay-to-address transaction redeemable using an ECDSA key
|
||||||
|
PayToAddress(SecretKey),
|
||||||
|
/// Undetermined
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A txout that is spendable by the wallet
|
||||||
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
|
pub struct WalletTxOut {
|
||||||
|
/// The TXID of the transaction this output is part of
|
||||||
|
pub txid: Sha256dHash,
|
||||||
|
/// The index of the output in its transaction
|
||||||
|
pub vout: u32,
|
||||||
|
/// The blockheight at which this output appeared in the blockchain
|
||||||
|
pub height: u32,
|
||||||
|
/// The actual output
|
||||||
|
pub txo: TxOut,
|
||||||
|
/// A classification of the output
|
||||||
|
pub kind: WalletTxOutType
|
||||||
|
}
|
||||||
|
|
||||||
/// An address index
|
/// An address index
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
pub struct AddressIndex {
|
pub struct AddressIndex {
|
||||||
index: HashMap<Script, Vec<(Sha256dHash, uint, TxOut, uint)>>,
|
tentative_index: HashMap<Script, Vec<WalletTxOut>>,
|
||||||
|
index: HashMap<(Sha256dHash, u32), Vec<WalletTxOut>, DumbHasher>,
|
||||||
network: Network,
|
network: Network,
|
||||||
k1: u64,
|
k1: u64,
|
||||||
k2: u64
|
k2: u64
|
||||||
|
@ -44,21 +72,35 @@ impl AddressIndex {
|
||||||
pub fn new(utxo_set: &UtxoSet, wallet: &Wallet) -> AddressIndex {
|
pub fn new(utxo_set: &UtxoSet, wallet: &Wallet) -> AddressIndex {
|
||||||
let (k1, k2) = wallet.siphash_key();
|
let (k1, k2) = wallet.siphash_key();
|
||||||
let mut ret = AddressIndex {
|
let mut ret = AddressIndex {
|
||||||
index: HashMap::with_capacity(utxo_set.n_utxos() / 256),
|
tentative_index: HashMap::with_capacity(utxo_set.n_utxos() / 256),
|
||||||
|
index: HashMap::with_hasher(DumbHasher),
|
||||||
network: wallet.network(),
|
network: wallet.network(),
|
||||||
k1: k1,
|
k1: k1,
|
||||||
k2: k2
|
k2: k2
|
||||||
};
|
};
|
||||||
for (key, idx, txo, height) in utxo_set.iter() {
|
for (key, idx, txo, height) in utxo_set.iter() {
|
||||||
if ret.admissible_txo(txo) {
|
if ret.admissible_txo(txo) {
|
||||||
ret.index.insert_or_update_with(txo.script_pubkey.clone(),
|
let new = WalletTxOut {
|
||||||
vec![(key, idx, txo.clone(), height)],
|
txid: key,
|
||||||
|_, v| v.push((key, idx, txo.clone(), height)));
|
vout: idx,
|
||||||
|
height: height,
|
||||||
|
txo: txo.clone(),
|
||||||
|
kind: Unknown
|
||||||
|
};
|
||||||
|
ret.tentative_index.find_or_insert(txo.script_pubkey.clone(), vec![]).push(new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
#[inline]
|
||||||
|
pub fn index_wallet_txo(&mut self, wtx: &WalletTxOut, kind: WalletTxOutType) {
|
||||||
|
let mut new = wtx.clone();
|
||||||
|
new.kind = kind;
|
||||||
|
self.index.find_or_insert((wtx.txid, wtx.vout), vec![]).push(new);
|
||||||
|
}
|
||||||
|
|
||||||
/// A filtering function used for creating a small address index.
|
/// A filtering function used for creating a small address index.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn admissible_address(&self, addr: &Address) -> bool {
|
pub fn admissible_address(&self, addr: &Address) -> bool {
|
||||||
|
@ -77,8 +119,8 @@ impl AddressIndex {
|
||||||
/// Lookup a txout by its scriptpubkey. Returns a slice because there
|
/// Lookup a txout by its scriptpubkey. Returns a slice because there
|
||||||
/// may be more than one for any given scriptpubkey.
|
/// may be more than one for any given scriptpubkey.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn find_by_script<'a>(&'a self, pubkey: &Script) -> &'a [(Sha256dHash, uint, TxOut, uint)] {
|
pub fn find_by_script<'a>(&'a self, pubkey: &Script) -> &'a [WalletTxOut] {
|
||||||
self.index.find(pubkey).map(|v| v.as_slice()).unwrap_or(&[])
|
self.tentative_index.find(pubkey).map(|v| v.as_slice()).unwrap_or(&[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,16 +35,16 @@ use util::base58::{Base58Error,
|
||||||
FromBase58, ToBase58};
|
FromBase58, ToBase58};
|
||||||
|
|
||||||
/// A chain code
|
/// A chain code
|
||||||
pub struct ChainCode([u8, ..32]);
|
pub struct ChainCode([u8; 32]);
|
||||||
impl_array_newtype!(ChainCode, u8, 32)
|
impl_array_newtype!(ChainCode, u8, 32);
|
||||||
impl_array_newtype_show!(ChainCode)
|
impl_array_newtype_show!(ChainCode);
|
||||||
impl_array_newtype_encodable!(ChainCode, u8, 32)
|
impl_array_newtype_encodable!(ChainCode, u8, 32);
|
||||||
|
|
||||||
/// A fingerprint
|
/// A fingerprint
|
||||||
pub struct Fingerprint([u8, ..4]);
|
pub struct Fingerprint([u8; 4]);
|
||||||
impl_array_newtype!(Fingerprint, u8, 4)
|
impl_array_newtype!(Fingerprint, u8, 4);
|
||||||
impl_array_newtype_show!(Fingerprint)
|
impl_array_newtype_show!(Fingerprint);
|
||||||
impl_array_newtype_encodable!(Fingerprint, u8, 4)
|
impl_array_newtype_encodable!(Fingerprint, u8, 4);
|
||||||
|
|
||||||
impl Default for Fingerprint {
|
impl Default for Fingerprint {
|
||||||
fn default() -> Fingerprint { Fingerprint([0, 0, 0, 0]) }
|
fn default() -> Fingerprint { Fingerprint([0, 0, 0, 0]) }
|
||||||
|
@ -56,7 +56,7 @@ 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,
|
||||||
/// How many derivations this key is from the master (which is 0)
|
/// How many derivations this key is from the master (which is 0)
|
||||||
pub depth: uint,
|
pub depth: u8,
|
||||||
/// Fingerprint of the parent key (0 for master)
|
/// Fingerprint of the parent key (0 for master)
|
||||||
pub parent_fingerprint: Fingerprint,
|
pub parent_fingerprint: Fingerprint,
|
||||||
/// Child number of the key used to derive from parent (0 for master)
|
/// Child number of the key used to derive from parent (0 for master)
|
||||||
|
@ -73,7 +73,7 @@ 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,
|
||||||
/// How many derivations this key is from the master (which is 0)
|
/// How many derivations this key is from the master (which is 0)
|
||||||
pub depth: uint,
|
pub depth: u8,
|
||||||
/// Fingerprint of the parent key
|
/// Fingerprint of the parent key
|
||||||
pub parent_fingerprint: Fingerprint,
|
pub parent_fingerprint: Fingerprint,
|
||||||
/// Child number of the key used to derive from parent (0 for master)
|
/// Child number of the key used to derive from parent (0 for master)
|
||||||
|
@ -129,7 +129,7 @@ pub enum Error {
|
||||||
impl ExtendedPrivKey {
|
impl ExtendedPrivKey {
|
||||||
/// Construct a new master key from a seed value
|
/// Construct a new master key from a seed value
|
||||||
pub fn new_master(network: Network, seed: &[u8]) -> Result<ExtendedPrivKey, Error> {
|
pub fn new_master(network: Network, seed: &[u8]) -> Result<ExtendedPrivKey, Error> {
|
||||||
let mut result = [0, ..64];
|
let mut result = [0; 64];
|
||||||
let mut hmac = Hmac::new(Sha512::new(), b"Bitcoin seed".as_slice());
|
let mut hmac = Hmac::new(Sha512::new(), b"Bitcoin seed".as_slice());
|
||||||
hmac.input(seed);
|
hmac.input(seed);
|
||||||
hmac.raw_result(result.as_mut_slice());
|
hmac.raw_result(result.as_mut_slice());
|
||||||
|
@ -156,7 +156,7 @@ impl ExtendedPrivKey {
|
||||||
|
|
||||||
/// Private->Private child key derivation
|
/// Private->Private child key derivation
|
||||||
pub fn ckd_priv(&self, i: ChildNumber) -> Result<ExtendedPrivKey, Error> {
|
pub fn ckd_priv(&self, i: ChildNumber) -> Result<ExtendedPrivKey, Error> {
|
||||||
let mut result = [0, ..64];
|
let mut result = [0; 64];
|
||||||
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 {
|
||||||
Normal(n) => {
|
Normal(n) => {
|
||||||
|
@ -190,9 +190,9 @@ impl ExtendedPrivKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the HASH160 of the chaincode
|
/// Returns the HASH160 of the chaincode
|
||||||
pub fn identifier(&self) -> [u8, ..20] {
|
pub fn identifier(&self) -> [u8; 20] {
|
||||||
let mut sha2_res = [0, ..32];
|
let mut sha2_res = [0; 32];
|
||||||
let mut ripemd_res = [0, ..20];
|
let mut ripemd_res = [0; 20];
|
||||||
// Compute extended public key
|
// Compute extended public key
|
||||||
let pk = ExtendedPubKey::from_private(self);
|
let pk = ExtendedPubKey::from_private(self);
|
||||||
// Do SHA256 of just the ECDSA pubkey
|
// Do SHA256 of just the ECDSA pubkey
|
||||||
|
@ -242,7 +242,7 @@ impl ExtendedPubKey {
|
||||||
hmac.input(self.public_key.as_slice());
|
hmac.input(self.public_key.as_slice());
|
||||||
u64_to_be_bytes(n as u64, 4, |raw| hmac.input(raw));
|
u64_to_be_bytes(n as u64, 4, |raw| hmac.input(raw));
|
||||||
|
|
||||||
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(EcdsaError));
|
||||||
|
@ -262,9 +262,9 @@ impl ExtendedPubKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the HASH160 of the chaincode
|
/// Returns the HASH160 of the chaincode
|
||||||
pub fn identifier(&self) -> [u8, ..20] {
|
pub fn identifier(&self) -> [u8; 20] {
|
||||||
let mut sha2_res = [0, ..32];
|
let mut sha2_res = [0; 32];
|
||||||
let mut ripemd_res = [0, ..20];
|
let mut ripemd_res = [0; 20];
|
||||||
// Do SHA256 of just the ECDSA pubkey
|
// Do SHA256 of just the ECDSA pubkey
|
||||||
let mut sha2 = Sha256::new();
|
let mut sha2 = Sha256::new();
|
||||||
sha2.input(self.public_key.as_slice());
|
sha2.input(self.public_key.as_slice());
|
||||||
|
@ -321,9 +321,9 @@ impl FromBase58 for ExtendedPrivKey {
|
||||||
network: match data.slice_to(4) {
|
network: match data.slice_to(4) {
|
||||||
[0x04, 0x88, 0xAD, 0xE4] => Bitcoin,
|
[0x04, 0x88, 0xAD, 0xE4] => Bitcoin,
|
||||||
[0x04, 0x35, 0x83, 0x94] => BitcoinTestnet,
|
[0x04, 0x35, 0x83, 0x94] => BitcoinTestnet,
|
||||||
_ => { return Err(InvalidVersion(Vec::from_slice(data.slice_to(4)))); }
|
_ => { return Err(InvalidVersion(data.slice_to(4).to_vec())); }
|
||||||
},
|
},
|
||||||
depth: data[4] as uint,
|
depth: data[4],
|
||||||
parent_fingerprint: Fingerprint::from_slice(data.slice(5, 9)),
|
parent_fingerprint: Fingerprint::from_slice(data.slice(5, 9)),
|
||||||
child_number: child_number,
|
child_number: child_number,
|
||||||
chain_code: ChainCode::from_slice(data.slice(13, 45)),
|
chain_code: ChainCode::from_slice(data.slice(13, 45)),
|
||||||
|
@ -372,9 +372,9 @@ impl FromBase58 for ExtendedPubKey {
|
||||||
network: match data.slice_to(4) {
|
network: match data.slice_to(4) {
|
||||||
[0x04, 0x88, 0xB2, 0x1E] => Bitcoin,
|
[0x04, 0x88, 0xB2, 0x1E] => Bitcoin,
|
||||||
[0x04, 0x35, 0x87, 0xCF] => BitcoinTestnet,
|
[0x04, 0x35, 0x87, 0xCF] => BitcoinTestnet,
|
||||||
_ => { return Err(InvalidVersion(Vec::from_slice(data.slice_to(4)))); }
|
_ => { return Err(InvalidVersion(data.slice_to(4).to_vec())); }
|
||||||
},
|
},
|
||||||
depth: data[4] as uint,
|
depth: data[4],
|
||||||
parent_fingerprint: Fingerprint::from_slice(data.slice(5, 9)),
|
parent_fingerprint: Fingerprint::from_slice(data.slice(5, 9)),
|
||||||
child_number: child_number,
|
child_number: child_number,
|
||||||
chain_code: ChainCode::from_slice(data.slice(13, 45)),
|
chain_code: ChainCode::from_slice(data.slice(13, 45)),
|
||||||
|
|
|
@ -25,7 +25,7 @@ use secp256k1::key::PublicKey;
|
||||||
|
|
||||||
use blockdata::utxoset::UtxoSet;
|
use blockdata::utxoset::UtxoSet;
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
use wallet::bip32::{mod, ChildNumber, ExtendedPrivKey, ExtendedPubKey, Normal, Hardened};
|
use wallet::bip32::{self, ChildNumber, ExtendedPrivKey, ExtendedPubKey, Normal, Hardened};
|
||||||
use wallet::address::Address;
|
use wallet::address::Address;
|
||||||
use wallet::address_index::AddressIndex;
|
use wallet::address_index::AddressIndex;
|
||||||
|
|
||||||
|
@ -273,8 +273,8 @@ impl Wallet {
|
||||||
let sk = try!(master.ckd_priv(cnum).map_err(Bip32Error));
|
let sk = try!(master.ckd_priv(cnum).map_err(Bip32Error));
|
||||||
let pk = ExtendedPubKey::from_private(&sk);
|
let pk = ExtendedPubKey::from_private(&sk);
|
||||||
let addr = Address::from_key(pk.network, &pk.public_key);
|
let addr = Address::from_key(pk.network, &pk.public_key);
|
||||||
for &(_, _, ref out, _) in index.find_by_script(&addr.script_pubkey()).iter() {
|
for out in index.find_by_script(&addr.script_pubkey()).iter() {
|
||||||
ret += out.value;
|
ret += out.txo.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sum external balance
|
// Sum external balance
|
||||||
|
@ -285,8 +285,8 @@ impl Wallet {
|
||||||
let sk = try!(master.ckd_priv(cnum).map_err(Bip32Error));
|
let sk = try!(master.ckd_priv(cnum).map_err(Bip32Error));
|
||||||
let pk = ExtendedPubKey::from_private(&sk);
|
let pk = ExtendedPubKey::from_private(&sk);
|
||||||
let addr = Address::from_key(pk.network, &pk.public_key);
|
let addr = Address::from_key(pk.network, &pk.public_key);
|
||||||
for &(_, _, ref out, _) in index.find_by_script(&addr.script_pubkey()).iter() {
|
for out in index.find_by_script(&addr.script_pubkey()).iter() {
|
||||||
ret += out.value;
|
ret += out.txo.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue