Changes for cargo-clippy warnings
This commit is contained in:
parent
8daf06cc1d
commit
5e03adc9aa
|
@ -39,7 +39,8 @@ using the same rules to validate data, and this library is simply unable
|
||||||
to implement the same rules as Core.
|
to implement the same rules as Core.
|
||||||
|
|
||||||
Given the complexity of both C++ and Rust, it is unlikely that this will
|
Given the complexity of both C++ and Rust, it is unlikely that this will
|
||||||
ever be fixed, and there are no plans to do so.
|
ever be fixed, and there are no plans to do so. Of course, patches to
|
||||||
|
fix specific consensus incompatibilities are welcome.
|
||||||
|
|
||||||
## Memory Usage
|
## Memory Usage
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,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 usize), 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))
|
||||||
}
|
}
|
||||||
|
@ -98,11 +98,11 @@ impl BlockHeader {
|
||||||
/// is correct, but does not verify that the transactions are valid or encoded
|
/// is correct, but does not verify that the transactions are valid or encoded
|
||||||
/// correctly.
|
/// correctly.
|
||||||
pub fn spv_validate(&self, required_target: &Uint256) -> Result<(), util::Error> {
|
pub fn spv_validate(&self, required_target: &Uint256) -> Result<(), util::Error> {
|
||||||
let ref target = self.target();
|
let target = &self.target();
|
||||||
if target != required_target {
|
if target != required_target {
|
||||||
return Err(SpvBadTarget);
|
return Err(SpvBadTarget);
|
||||||
}
|
}
|
||||||
let ref hash = self.bitcoin_hash().into_le();
|
let hash = &self.bitcoin_hash().into_le();
|
||||||
if hash <= target { Ok(()) } else { Err(SpvBadProofOfWork) }
|
if hash <= target { Ok(()) } else { Err(SpvBadProofOfWork) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,8 +65,8 @@ impl BlockchainNode {
|
||||||
/// Is the node on the main chain?
|
/// Is the node on the main chain?
|
||||||
fn is_on_main_chain(&self, chain: &Blockchain) -> bool {
|
fn is_on_main_chain(&self, chain: &Blockchain) -> bool {
|
||||||
if self.block.header == unsafe { (*chain.best_tip).block.header } {
|
if self.block.header == unsafe { (*chain.best_tip).block.header } {
|
||||||
return true;
|
true
|
||||||
}
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut scan = self.next;
|
let mut scan = self.next;
|
||||||
while !scan.is_null() {
|
while !scan.is_null() {
|
||||||
|
@ -76,7 +76,8 @@ impl BlockchainNode {
|
||||||
scan = (*scan).next;
|
scan = (*scan).next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +386,7 @@ impl Blockchain {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Looks up a block in the chain and returns the BlockchainNode containing it
|
/// Looks up a block in the chain and returns the BlockchainNode containing it
|
||||||
pub fn get_block<'a>(&'a self, hash: Sha256dHash) -> Option<&'a BlockchainNode> {
|
pub fn get_block(&self, hash: Sha256dHash) -> Option<&BlockchainNode> {
|
||||||
self.tree.lookup(&hash.into_le(), 256).map(|node| &**node)
|
self.tree.lookup(&hash.into_le(), 256).map(|node| &**node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +413,7 @@ impl Blockchain {
|
||||||
fn real_add_block(&mut self, block: Block, has_txdata: bool) -> Result<(), util::Error> {
|
fn real_add_block(&mut self, block: Block, has_txdata: bool) -> Result<(), util::Error> {
|
||||||
// get_prev optimizes the common case where we are extending the best tip
|
// get_prev optimizes the common case where we are extending the best tip
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_prev<'a>(chain: &'a Blockchain, hash: Sha256dHash) -> Option<NodePtr> {
|
fn get_prev(chain: &Blockchain, hash: Sha256dHash) -> Option<NodePtr> {
|
||||||
if hash == chain.best_hash {
|
if hash == chain.best_hash {
|
||||||
Some(chain.best_tip)
|
Some(chain.best_tip)
|
||||||
} else {
|
} else {
|
||||||
|
@ -535,7 +536,7 @@ impl Blockchain {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the best tip
|
/// Returns the best tip
|
||||||
pub fn best_tip<'a>(&'a self) -> &'a Block {
|
pub fn best_tip(&self) -> &Block {
|
||||||
unsafe { &(*self.best_tip).block }
|
unsafe { &(*self.best_tip).block }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -891,14 +891,14 @@ impl AbstractStackElem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Looks up another stack item by index
|
/// Looks up another stack item by index
|
||||||
unsafe fn lookup<'a>(&'a self, idx: usize) -> &'a AbstractStackElem {
|
unsafe fn lookup(&self, idx: usize) -> &AbstractStackElem {
|
||||||
let mypos = self as *const _;
|
let mypos = self as *const _;
|
||||||
let myidx = self.alloc_index.unwrap() as isize;
|
let myidx = self.alloc_index.unwrap() as isize;
|
||||||
&*mypos.offset(idx as isize - 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: usize) -> &'a mut AbstractStackElem {
|
unsafe fn lookup_mut(&self, idx: usize) -> &mut AbstractStackElem {
|
||||||
let mypos = self as *const _ as *mut _;
|
let mypos = self as *const _ as *mut _;
|
||||||
let myidx = self.alloc_index.unwrap() as isize;
|
let myidx = self.alloc_index.unwrap() as isize;
|
||||||
&mut *mypos.offset(idx as isize - myidx)
|
&mut *mypos.offset(idx as isize - myidx)
|
||||||
|
@ -910,7 +910,7 @@ impl AbstractStackElem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the raw value of the stack element, if it can be determined
|
/// Retrieves the raw value of the stack element, if it can be determined
|
||||||
pub fn raw_value<'a>(&'a self) -> Option<&'a [u8]> {
|
pub fn raw_value(&self) -> Option<&[u8]> {
|
||||||
self.raw.as_ref().map(|x| &x[..])
|
self.raw.as_ref().map(|x| &x[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1177,9 +1177,7 @@ impl AbstractStack {
|
||||||
|
|
||||||
/// Construct the initial stack in the end
|
/// Construct the initial stack in the end
|
||||||
pub fn build_initial_stack(&self) -> Vec<AbstractStackElem> {
|
pub fn build_initial_stack(&self) -> Vec<AbstractStackElem> {
|
||||||
let res: Vec<AbstractStackElem> =
|
self.initial_stack.iter().map(|&i| self.alloc[i].clone()).collect()
|
||||||
self.initial_stack.iter().map(|&i| self.alloc[i].clone()).collect();
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increase the stack size to `n`, adding elements to the initial
|
/// Increase the stack size to `n`, adding elements to the initial
|
||||||
|
@ -1196,7 +1194,7 @@ impl AbstractStack {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push a new element
|
/// Push a new element
|
||||||
pub fn push_alloc<'a>(&'a mut self, elem: AbstractStackElem) -> &'a mut AbstractStackElem {
|
pub fn push_alloc(&mut self, elem: AbstractStackElem) -> &mut AbstractStackElem {
|
||||||
let idx = self.allocate(elem);
|
let idx = self.allocate(elem);
|
||||||
self.stack.push(idx);
|
self.stack.push(idx);
|
||||||
&mut self.alloc[idx]
|
&mut self.alloc[idx]
|
||||||
|
@ -1204,8 +1202,8 @@ impl AbstractStack {
|
||||||
|
|
||||||
|
|
||||||
/// Obtain a mutable element to the top stack element
|
/// Obtain a mutable element to the top stack element
|
||||||
pub fn peek_mut<'a>(&'a mut self) -> &'a mut AbstractStackElem {
|
pub fn peek_mut(&mut self) -> &mut AbstractStackElem {
|
||||||
if self.stack.len() == 0 {
|
if self.stack.is_empty() {
|
||||||
self.push_initial(AbstractStackElem::new_unknown());
|
self.push_initial(AbstractStackElem::new_unknown());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1214,7 +1212,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) -> usize {
|
pub fn peek_index(&mut self) -> usize {
|
||||||
if self.stack.len() == 0 {
|
if self.stack.is_empty() {
|
||||||
self.push_initial(AbstractStackElem::new_unknown());
|
self.push_initial(AbstractStackElem::new_unknown());
|
||||||
}
|
}
|
||||||
*self.stack.last().unwrap()
|
*self.stack.last().unwrap()
|
||||||
|
@ -1222,15 +1220,15 @@ impl AbstractStack {
|
||||||
|
|
||||||
/// Drop the top stack item
|
/// Drop the top stack item
|
||||||
fn pop(&mut self) -> usize {
|
fn pop(&mut self) -> usize {
|
||||||
if self.stack.len() == 0 {
|
if self.stack.is_empty() {
|
||||||
self.push_initial(AbstractStackElem::new_unknown());
|
self.push_initial(AbstractStackElem::new_unknown());
|
||||||
}
|
}
|
||||||
self.stack.pop().unwrap()
|
self.stack.pop().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain a mutable reference to the top stack item, but remove it from the stack
|
/// Obtain a mutable reference to the top stack item, but remove it from the stack
|
||||||
fn pop_mut<'a>(&'a mut self) -> &'a mut AbstractStackElem {
|
fn pop_mut(&mut self) -> &mut AbstractStackElem {
|
||||||
if self.stack.len() == 0 {
|
if self.stack.is_empty() {
|
||||||
self.push_initial(AbstractStackElem::new_unknown());
|
self.push_initial(AbstractStackElem::new_unknown());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1239,8 +1237,8 @@ impl AbstractStack {
|
||||||
|
|
||||||
|
|
||||||
/// Move the top stack item to the altstack
|
/// Move the top stack item to the altstack
|
||||||
pub fn to_altstack(&mut self) {
|
pub fn top_to_altstack(&mut self) {
|
||||||
if self.stack.len() == 0 {
|
if self.stack.is_empty() {
|
||||||
self.push_initial(AbstractStackElem::new_unknown());
|
self.push_initial(AbstractStackElem::new_unknown());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1252,7 +1250,7 @@ impl AbstractStack {
|
||||||
/// altstack is empty. (Note that input scripts pass their
|
/// altstack is empty. (Note that input scripts pass their
|
||||||
/// stack to the output script but /not/ the altstack, so
|
/// stack to the output script but /not/ the altstack, so
|
||||||
/// there is no input that can make an empty altstack nonempty.)
|
/// there is no input that can make an empty altstack nonempty.)
|
||||||
pub fn from_altstack(&mut self) -> Result<(), Error> {
|
pub fn top_from_altstack(&mut self) -> Result<(), Error> {
|
||||||
match self.alt_stack.pop() {
|
match self.alt_stack.pop() {
|
||||||
Some(x) => { self.stack.push(x); Ok(()) }
|
Some(x) => { self.stack.push(x); Ok(()) }
|
||||||
None => Err(Error::PopEmptyStack)
|
None => Err(Error::PopEmptyStack)
|
||||||
|
@ -1549,7 +1547,7 @@ pub fn read_scriptint(v: &[u8]) -> Result<i64, Error> {
|
||||||
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;
|
||||||
}
|
}
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
|
@ -1559,7 +1557,7 @@ pub fn read_scriptint(v: &[u8]) -> Result<i64, Error> {
|
||||||
/// else as true", except that the overflow rules don't apply.
|
/// else as true", except that the overflow rules don't apply.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_scriptbool(v: &[u8]) -> bool {
|
pub fn read_scriptbool(v: &[u8]) -> bool {
|
||||||
!(v.len() == 0 ||
|
!(v.is_empty() ||
|
||||||
((v[v.len() - 1] == 0 || v[v.len() - 1] == 0x80) &&
|
((v[v.len() - 1] == 0 || v[v.len() - 1] == 0x80) &&
|
||||||
v.iter().rev().skip(1).all(|&w| w == 0)))
|
v.iter().rev().skip(1).all(|&w| w == 0)))
|
||||||
}
|
}
|
||||||
|
@ -1809,6 +1807,9 @@ impl Script {
|
||||||
/// The length in bytes of the script
|
/// The length in bytes of the script
|
||||||
pub fn len(&self) -> usize { self.0.len() }
|
pub fn len(&self) -> usize { self.0.len() }
|
||||||
|
|
||||||
|
/// Whether the script is the empty script
|
||||||
|
pub fn is_empty(&self) -> bool { self.0.is_empty() }
|
||||||
|
|
||||||
/// Trace a script
|
/// Trace a script
|
||||||
pub fn trace<'a>(&'a self, secp: &Secp256k1, stack: &mut Vec<MaybeOwned<'a>>,
|
pub fn trace<'a>(&'a self, secp: &Secp256k1, stack: &mut Vec<MaybeOwned<'a>>,
|
||||||
input_context: Option<(&Transaction, usize)>)
|
input_context: Option<(&Transaction, usize)>)
|
||||||
|
@ -1852,7 +1853,7 @@ impl Script {
|
||||||
errored: true,
|
errored: true,
|
||||||
op_count: op_count,
|
op_count: op_count,
|
||||||
effect: opcode.classify(),
|
effect: opcode.classify(),
|
||||||
stack: vec!["<failed to execute opcode>".to_string()]
|
stack: vec!["<failed to execute opcode>".to_owned()]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
|
@ -2108,7 +2109,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 = (&self.0[codeseparator_index..]).to_vec();
|
let mut script = (&self.0[codeseparator_index..]).to_vec();
|
||||||
for sig in sigs.iter() {
|
for sig in &sigs {
|
||||||
let mut remove = Builder::new();
|
let mut remove = Builder::new();
|
||||||
remove.push_slice(&sig[..]);
|
remove.push_slice(&sig[..]);
|
||||||
script_find_and_remove(&mut script, &remove[..]);
|
script_find_and_remove(&mut script, &remove[..]);
|
||||||
|
@ -2185,7 +2186,7 @@ impl Script {
|
||||||
/// Evaluate the script to determine whether any possible input will cause it
|
/// Evaluate the script to determine whether any possible input will cause it
|
||||||
/// to accept. Returns true if it is guaranteed to fail; false otherwise.
|
/// to accept. Returns true if it is guaranteed to fail; false otherwise.
|
||||||
pub fn satisfy(&self) -> Result<Vec<AbstractStackElem>, Error> {
|
pub fn satisfy(&self) -> Result<Vec<AbstractStackElem>, Error> {
|
||||||
fn recurse<'a>(script: &'a [u8],
|
fn recurse(script: &[u8],
|
||||||
mut stack: AbstractStack,
|
mut stack: AbstractStack,
|
||||||
mut exec_stack: Vec<bool>,
|
mut exec_stack: Vec<bool>,
|
||||||
depth: usize) -> Result<Vec<AbstractStackElem>, Error> {
|
depth: usize) -> Result<Vec<AbstractStackElem>, Error> {
|
||||||
|
@ -2334,8 +2335,8 @@ impl Script {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opcodes::Ordinary::OP_VERIFY => op_verify_satisfy!(stack),
|
opcodes::Ordinary::OP_VERIFY => op_verify_satisfy!(stack),
|
||||||
opcodes::Ordinary::OP_TOALTSTACK => { stack.to_altstack(); }
|
opcodes::Ordinary::OP_TOALTSTACK => { stack.top_to_altstack(); }
|
||||||
opcodes::Ordinary::OP_FROMALTSTACK => { try!(stack.from_altstack()); }
|
opcodes::Ordinary::OP_FROMALTSTACK => { try!(stack.top_from_altstack()); }
|
||||||
opcodes::Ordinary::OP_2DROP => stack_opcode!(stack(2): require 2 drop 1; drop 2),
|
opcodes::Ordinary::OP_2DROP => stack_opcode!(stack(2): require 2 drop 1; drop 2),
|
||||||
opcodes::Ordinary::OP_2DUP => stack_opcode!(stack(2): require 2 copy 2; copy 1),
|
opcodes::Ordinary::OP_2DUP => stack_opcode!(stack(2): require 2 copy 2; copy 1),
|
||||||
opcodes::Ordinary::OP_3DUP => stack_opcode!(stack(3): require 3 copy 3; copy 2; copy 1),
|
opcodes::Ordinary::OP_3DUP => stack_opcode!(stack(3): require 3 copy 3; copy 2; copy 1),
|
||||||
|
@ -2558,7 +2559,7 @@ impl<'a> Iterator for Instructions<'a> {
|
||||||
type Item = Instruction<'a>;
|
type Item = Instruction<'a>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Instruction<'a>> {
|
fn next(&mut self) -> Option<Instruction<'a>> {
|
||||||
if self.data.len() == 0 {
|
if self.data.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2622,6 +2623,9 @@ impl Builder {
|
||||||
/// The length in bytes of the script
|
/// The length in bytes of the script
|
||||||
pub fn len(&self) -> usize { self.0.len() }
|
pub fn len(&self) -> usize { self.0.len() }
|
||||||
|
|
||||||
|
/// Whether the script is the empty script
|
||||||
|
pub fn is_empty(&self) -> bool { self.0.is_empty() }
|
||||||
|
|
||||||
/// Adds instructions to push an integer onto the stack. Integers are
|
/// Adds instructions to push an integer onto the stack. Integers are
|
||||||
/// encoded as little-endian signed-magnitude numbers, but there are
|
/// encoded as little-endian signed-magnitude numbers, but there are
|
||||||
/// dedicated opcodes to push some small integers.
|
/// dedicated opcodes to push some small integers.
|
||||||
|
@ -2833,8 +2837,8 @@ mod test {
|
||||||
// before needing a transaction
|
// before needing a transaction
|
||||||
assert_eq!(script_pk.evaluate(&s, &mut vec![], None, None), Err(Error::PopEmptyStack));
|
assert_eq!(script_pk.evaluate(&s, &mut vec![], None, None), Err(Error::PopEmptyStack));
|
||||||
assert_eq!(script_pk.evaluate(&s, &mut vec![Owned(vec![]), Owned(vec![])], None, None),
|
assert_eq!(script_pk.evaluate(&s, &mut vec![Owned(vec![]), Owned(vec![])], None, None),
|
||||||
Err(Error::EqualVerifyFailed("e729dea4a3a81108e16376d1cc329c91db589994".to_string(),
|
Err(Error::EqualVerifyFailed("e729dea4a3a81108e16376d1cc329c91db589994".to_owned(),
|
||||||
"b472a266d0bd89c13706a4132ccfb16f7c3b9fcb".to_string())));
|
"b472a266d0bd89c13706a4132ccfb16f7c3b9fcb".to_owned())));
|
||||||
// But if the signature is there, we need a tx to check it
|
// But if the signature is there, we need a tx to check it
|
||||||
assert_eq!(script_pk.evaluate(&s, &mut vec![Owned(vec![]), Owned("026d5d4cfef5f3d97d2263941b4d8e7aaa82910bf8e6f7c6cf1d8f0d755b9d2d1a".from_hex().unwrap())], None, None), Err(Error::NoTransaction));
|
assert_eq!(script_pk.evaluate(&s, &mut vec![Owned(vec![]), Owned("026d5d4cfef5f3d97d2263941b4d8e7aaa82910bf8e6f7c6cf1d8f0d755b9d2d1a".from_hex().unwrap())], None, None), Err(Error::NoTransaction));
|
||||||
assert_eq!(script_pk.evaluate(&s, &mut vec![Owned(vec![0]), Owned("026d5d4cfef5f3d97d2263941b4d8e7aaa82910bf8e6f7c6cf1d8f0d755b9d2d1a".from_hex().unwrap())], None, None), Err(Error::NoTransaction));
|
assert_eq!(script_pk.evaluate(&s, &mut vec![Owned(vec![0]), Owned("026d5d4cfef5f3d97d2263941b4d8e7aaa82910bf8e6f7c6cf1d8f0d755b9d2d1a".from_hex().unwrap())], None, None), Err(Error::NoTransaction));
|
||||||
|
|
|
@ -145,7 +145,7 @@ impl TxIn {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => { return Err(Error::InputScriptFailure(e)); }
|
Err(e) => { return Err(Error::InputScriptFailure(e)); }
|
||||||
}
|
}
|
||||||
if txo.script_pubkey.is_p2sh() && stack.len() > 0 {
|
if txo.script_pubkey.is_p2sh() && !stack.is_empty() {
|
||||||
p2sh_stack = stack.clone();
|
p2sh_stack = stack.clone();
|
||||||
p2sh_script = match p2sh_stack.pop() {
|
p2sh_script = match p2sh_stack.pop() {
|
||||||
Some(script::MaybeOwned::Owned(v)) => Script::from(v),
|
Some(script::MaybeOwned::Owned(v)) => Script::from(v),
|
||||||
|
@ -225,7 +225,7 @@ impl Transaction {
|
||||||
let err = trace.sig_trace.error.as_ref().map(|e| e.clone());
|
let err = trace.sig_trace.error.as_ref().map(|e| e.clone());
|
||||||
err.map(|e| trace.error = Some(Error::InputScriptFailure(e)));
|
err.map(|e| trace.error = Some(Error::InputScriptFailure(e)));
|
||||||
|
|
||||||
if txo.script_pubkey.is_p2sh() && stack.len() > 0 {
|
if txo.script_pubkey.is_p2sh() && !stack.is_empty() {
|
||||||
p2sh_stack = stack.clone();
|
p2sh_stack = stack.clone();
|
||||||
p2sh_script = match p2sh_stack.pop() {
|
p2sh_script = match p2sh_stack.pop() {
|
||||||
Some(script::MaybeOwned::Owned(v)) => Script::from(v),
|
Some(script::MaybeOwned::Owned(v)) => Script::from(v),
|
||||||
|
|
|
@ -96,16 +96,19 @@ impl<'a> Iterator for UtxoIterator<'a> {
|
||||||
None => { self.current = None; }
|
None => { self.current = None; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None;
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A mapping from a spent-txo to an actual txout ((txid, vout), (height, txout))
|
||||||
|
pub type StxoRef = ((Sha256dHash, u32), (u32, TxOut));
|
||||||
|
|
||||||
/// The UTXO set
|
/// The UTXO set
|
||||||
pub struct UtxoSet {
|
pub struct UtxoSet {
|
||||||
table: HashMap<Sha256dHash, UtxoNode>,
|
table: HashMap<Sha256dHash, UtxoNode>,
|
||||||
last_hash: Sha256dHash,
|
last_hash: Sha256dHash,
|
||||||
// A circular buffer of deleted utxos, grouped by block
|
// A circular buffer of deleted utxos, grouped by block
|
||||||
spent_txos: Vec<Vec<((Sha256dHash, u32), (u32, TxOut))>>,
|
spent_txos: Vec<Vec<StxoRef>>,
|
||||||
// The last index into the above buffer that was assigned to
|
// The last index into the above buffer that was assigned to
|
||||||
spent_idx: u64,
|
spent_idx: u64,
|
||||||
n_utxos: u64,
|
n_utxos: u64,
|
||||||
|
@ -137,7 +140,7 @@ impl UtxoSet {
|
||||||
// Locate node if it's already there
|
// Locate node if it's already there
|
||||||
let new_node = {
|
let new_node = {
|
||||||
let mut new_node = Vec::with_capacity(tx.output.len());
|
let mut new_node = Vec::with_capacity(tx.output.len());
|
||||||
for txo in tx.output.iter() {
|
for txo in &tx.output {
|
||||||
if txo.script_pubkey.is_provably_unspendable() {
|
if txo.script_pubkey.is_provably_unspendable() {
|
||||||
new_node.push(None);
|
new_node.push(None);
|
||||||
self.n_utxos -= 1;
|
self.n_utxos -= 1;
|
||||||
|
@ -188,7 +191,7 @@ 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<(usize, &'a TxOut)> {
|
pub fn get_utxo(&self, txid: Sha256dHash, vout: u32) -> Option<(usize, &TxOut)> {
|
||||||
// Locate the UTXO, failing if not found
|
// Locate the UTXO, failing if not found
|
||||||
let node = match self.table.get(&txid) {
|
let node = match self.table.get(&txid) {
|
||||||
Some(node) => node,
|
Some(node) => node,
|
||||||
|
@ -221,7 +224,7 @@ impl UtxoSet {
|
||||||
// same block. (Note that Bitcoin requires chained transactions to be in
|
// same block. (Note that Bitcoin requires chained transactions to be in
|
||||||
// the correct order, which we do not check, so we are minorly too permissive.
|
// the correct order, which we do not check, so we are minorly too permissive.
|
||||||
// TODO this is a consensus bug.)
|
// TODO this is a consensus bug.)
|
||||||
for tx in block.txdata.iter() {
|
for tx in &block.txdata {
|
||||||
let txid = tx.bitcoin_hash();
|
let txid = tx.bitcoin_hash();
|
||||||
// Add outputs -- add_utxos returns the original transaction if this is a dupe.
|
// Add outputs -- add_utxos returns the original transaction if this is a dupe.
|
||||||
// Note that this can only happen with coinbases, and in this case the block
|
// Note that this can only happen with coinbases, and in this case the block
|
||||||
|
@ -231,8 +234,8 @@ impl UtxoSet {
|
||||||
match self.add_utxos(tx, blockheight as u32) {
|
match self.add_utxos(tx, blockheight as u32) {
|
||||||
Some(mut replace) => {
|
Some(mut replace) => {
|
||||||
let blockhash = block.header.bitcoin_hash().be_hex_string();
|
let blockhash = block.header.bitcoin_hash().be_hex_string();
|
||||||
if blockhash == "00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec".to_string() ||
|
if blockhash == "00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec" ||
|
||||||
blockhash == "00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721".to_string() {
|
blockhash == "00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721" {
|
||||||
// For these specific blocks, overwrite the old UTXOs.
|
// For these specific blocks, overwrite the old UTXOs.
|
||||||
// (Actually add_utxos() already did this, so we do nothing.)
|
// (Actually add_utxos() already did this, so we do nothing.)
|
||||||
} else {
|
} else {
|
||||||
|
@ -330,7 +333,7 @@ impl UtxoSet {
|
||||||
|
|
||||||
// Delete added txouts
|
// Delete added txouts
|
||||||
let mut skipped_genesis = false;
|
let mut skipped_genesis = false;
|
||||||
for tx in block.txdata.iter() {
|
for tx in &block.txdata {
|
||||||
let txhash = tx.bitcoin_hash();
|
let txhash = tx.bitcoin_hash();
|
||||||
for n in 0..tx.output.len() {
|
for n in 0..tx.output.len() {
|
||||||
// Just bomb out the whole transaction
|
// Just bomb out the whole transaction
|
||||||
|
@ -374,7 +377,7 @@ impl UtxoSet {
|
||||||
self.spent_idx = (self.spent_idx + self.spent_txos.len() as u64 - 1) %
|
self.spent_idx = (self.spent_idx + self.spent_txos.len() as u64 - 1) %
|
||||||
self.spent_txos.len() as u64;
|
self.spent_txos.len() as u64;
|
||||||
self.last_hash = block.header.prev_blockhash;
|
self.last_hash = block.header.prev_blockhash;
|
||||||
return true;
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the hash of the last block added to the utxo set
|
/// Get the hash of the last block added to the utxo set
|
||||||
|
|
|
@ -73,6 +73,10 @@ 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) -> usize { $len }
|
pub fn len(&self) -> usize { $len }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Returns whether the object, as an array, is empty. Always false.
|
||||||
|
pub fn is_empty(&self) -> bool { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a [$ty]> for $thing {
|
impl<'a> From<&'a [$ty]> for $thing {
|
||||||
|
|
|
@ -128,7 +128,7 @@ impl<D: SimpleDecoder> ConsensusDecodable<D> for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<String, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<String, D::Error> {
|
||||||
String::from_utf8(try!(ConsensusDecodable::consensus_decode(d)))
|
String::from_utf8(try!(ConsensusDecodable::consensus_decode(d)))
|
||||||
.map_err(|_| d.error("String was not valid UTF8".to_string()))
|
.map_err(|_| d.error("String was not valid UTF8".to_owned()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for CheckedData {
|
||||||
try!((self.0.len() as u32).consensus_encode(s));
|
try!((self.0.len() as u32).consensus_encode(s));
|
||||||
try!(sha2_checksum(&self.0).consensus_encode(s));
|
try!(sha2_checksum(&self.0).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 self.0.iter() {
|
for ch in &self.0 {
|
||||||
try!(ch.consensus_encode(s));
|
try!(ch.consensus_encode(s));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -308,7 +308,7 @@ impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Box<T
|
||||||
impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Box<T> {
|
impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Box<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Box<T>, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Box<T>, D::Error> {
|
||||||
ConsensusDecodable::consensus_decode(d).map(|res| Box::new(res))
|
ConsensusDecodable::consensus_decode(d).map(Box::new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ use util;
|
||||||
/// A message which can be sent on the Bitcoin network
|
/// A message which can be sent on the Bitcoin network
|
||||||
pub trait Listener {
|
pub trait Listener {
|
||||||
/// Return a string encoding of the peer's network address
|
/// Return a string encoding of the peer's network address
|
||||||
fn peer<'a>(&'a self) -> &'a str;
|
fn peer(&self) -> &str;
|
||||||
/// Return the port we have connected to the peer on
|
/// Return the port we have connected to the peer on
|
||||||
fn port(&self) -> u16;
|
fn port(&self) -> u16;
|
||||||
/// Return the network this `Listener` is operating on
|
/// Return the network this `Listener` is operating on
|
||||||
|
@ -40,7 +40,7 @@ pub trait Listener {
|
||||||
// Open socket
|
// Open socket
|
||||||
let mut ret_sock = Socket::new(self.network());
|
let mut ret_sock = Socket::new(self.network());
|
||||||
if let Err(e) = ret_sock.connect(self.peer(), self.port()) {
|
if let Err(e) = ret_sock.connect(self.peer(), self.port()) {
|
||||||
return Err(util::Error::Detail("listener".to_string(), Box::new(e)));
|
return Err(util::Error::Detail("listener".to_owned(), Box::new(e)));
|
||||||
}
|
}
|
||||||
let mut sock = ret_sock.clone();
|
let mut sock = ret_sock.clone();
|
||||||
|
|
||||||
|
@ -59,9 +59,8 @@ pub trait Listener {
|
||||||
match sock.receive_message() {
|
match sock.receive_message() {
|
||||||
Ok(payload) => {
|
Ok(payload) => {
|
||||||
// React to any network messages that affect our state.
|
// React to any network messages that affect our state.
|
||||||
match payload {
|
if let Verack = payload {
|
||||||
// Make an exception for verack since there is no response required
|
// Make an exception for verack since there is no response required
|
||||||
Verack => {
|
|
||||||
// TODO: when the timeout stuff in std::io::net::tcp is sorted out we should
|
// TODO: when the timeout stuff in std::io::net::tcp is sorted out we should
|
||||||
// actually time out if the verack doesn't come in in time
|
// actually time out if the verack doesn't come in in time
|
||||||
if handshake_complete {
|
if handshake_complete {
|
||||||
|
@ -69,8 +68,6 @@ pub trait Listener {
|
||||||
} else {
|
} else {
|
||||||
handshake_complete = true;
|
handshake_complete = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
};
|
||||||
// We have to pass the message to the main thread for processing,
|
// We have to pass the message to the main thread for processing,
|
||||||
// unfortunately, because sipa says we have to handle everything
|
// unfortunately, because sipa says we have to handle everything
|
||||||
|
|
|
@ -133,7 +133,7 @@ impl RawNetworkMessage {
|
||||||
NetworkMessage::Headers(_) => "headers",
|
NetworkMessage::Headers(_) => "headers",
|
||||||
NetworkMessage::Ping(_) => "ping",
|
NetworkMessage::Ping(_) => "ping",
|
||||||
NetworkMessage::Pong(_) => "pong",
|
NetworkMessage::Pong(_) => "pong",
|
||||||
}.to_string()
|
}.to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,19 +170,19 @@ impl<D: SimpleDecoder<Error=util::Error>> ConsensusDecodable<D> for RawNetworkMe
|
||||||
|
|
||||||
let mut mem_d = RawDecoder::new(Cursor::new(raw_payload));
|
let mut mem_d = RawDecoder::new(Cursor::new(raw_payload));
|
||||||
let payload = match &cmd[..] {
|
let payload = match &cmd[..] {
|
||||||
"version" => NetworkMessage::Version(try!(propagate_err("version".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"version" => NetworkMessage::Version(try!(propagate_err("version".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"verack" => NetworkMessage::Verack,
|
"verack" => NetworkMessage::Verack,
|
||||||
"addr" => NetworkMessage::Addr(try!(propagate_err("addr".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"addr" => NetworkMessage::Addr(try!(propagate_err("addr".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"inv" => NetworkMessage::Inv(try!(propagate_err("inv".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"inv" => NetworkMessage::Inv(try!(propagate_err("inv".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"getdata" => NetworkMessage::GetData(try!(propagate_err("getdata".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"getdata" => NetworkMessage::GetData(try!(propagate_err("getdata".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"notfound" => NetworkMessage::NotFound(try!(propagate_err("notfound".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"notfound" => NetworkMessage::NotFound(try!(propagate_err("notfound".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"getblocks" => NetworkMessage::GetBlocks(try!(propagate_err("getblocks".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"getblocks" => NetworkMessage::GetBlocks(try!(propagate_err("getblocks".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"getheaders" => NetworkMessage::GetHeaders(try!(propagate_err("getheaders".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"getheaders" => NetworkMessage::GetHeaders(try!(propagate_err("getheaders".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"block" => NetworkMessage::Block(try!(propagate_err("block".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"block" => NetworkMessage::Block(try!(propagate_err("block".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"headers" => NetworkMessage::Headers(try!(propagate_err("headers".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"headers" => NetworkMessage::Headers(try!(propagate_err("headers".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"ping" => NetworkMessage::Ping(try!(propagate_err("ping".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"ping" => NetworkMessage::Ping(try!(propagate_err("ping".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"pong" => NetworkMessage::Ping(try!(propagate_err("pong".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"pong" => NetworkMessage::Ping(try!(propagate_err("pong".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
"tx" => NetworkMessage::Tx(try!(propagate_err("tx".to_string(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
"tx" => NetworkMessage::Tx(try!(propagate_err("tx".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
|
||||||
cmd => return Err(d.error(format!("unrecognized network command `{}`", cmd)))
|
cmd => return Err(d.error(format!("unrecognized network command `{}`", cmd)))
|
||||||
};
|
};
|
||||||
Ok(RawNetworkMessage {
|
Ok(RawNetworkMessage {
|
||||||
|
@ -200,7 +200,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_commandstring_test() {
|
fn serialize_commandstring_test() {
|
||||||
let cs = CommandString("Andrew".to_string());
|
let cs = CommandString("Andrew".to_owned());
|
||||||
assert_eq!(serialize(&cs).ok(), Some(vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]));
|
assert_eq!(serialize(&cs).ok(), Some(vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ mod test {
|
||||||
fn deserialize_commandstring_test() {
|
fn deserialize_commandstring_test() {
|
||||||
let cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
|
let cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
|
||||||
assert!(cs.is_ok());
|
assert!(cs.is_ok());
|
||||||
assert_eq!(cs.unwrap(), CommandString("Andrew".to_string()));
|
assert_eq!(cs.unwrap(), CommandString("Andrew".to_owned()));
|
||||||
|
|
||||||
let short_cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
|
let short_cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
|
||||||
assert!(short_cs.is_err());
|
assert!(short_cs.is_err());
|
||||||
|
|
|
@ -62,7 +62,7 @@ macro_rules! with_socket(($s:ident, $sock:ident, $body:block) => ({
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
||||||
"socket: socket mutex was poisoned");
|
"socket: socket mutex was poisoned");
|
||||||
return Err(util::Error::Io(io_err));
|
Err(util::Error::Io(io_err))
|
||||||
}
|
}
|
||||||
Ok(mut guard) => {
|
Ok(mut guard) => {
|
||||||
match *guard.deref_mut() {
|
match *guard.deref_mut() {
|
||||||
|
@ -72,7 +72,7 @@ macro_rules! with_socket(($s:ident, $sock:ident, $body:block) => ({
|
||||||
None => {
|
None => {
|
||||||
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
||||||
"socket: not connected to peer");
|
"socket: not connected to peer");
|
||||||
return Err(util::Error::Io(io_err));
|
Err(util::Error::Io(io_err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ impl Socket {
|
||||||
socket: Arc::new(Mutex::new(None)),
|
socket: Arc::new(Mutex::new(None)),
|
||||||
services: 0,
|
services: 0,
|
||||||
version_nonce: rng.gen(),
|
version_nonce: rng.gen(),
|
||||||
user_agent: constants::USER_AGENT.to_string(),
|
user_agent: constants::USER_AGENT.to_owned(),
|
||||||
magic: constants::magic(network)
|
magic: constants::magic(network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ impl Socket {
|
||||||
match decode {
|
match decode {
|
||||||
// Check for parse errors...
|
// Check for parse errors...
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
propagate_err("receive_message".to_string(), Err(e))
|
propagate_err("receive_message".to_owned(), Err(e))
|
||||||
},
|
},
|
||||||
Ok(ret) => {
|
Ok(ret) => {
|
||||||
// Then for magic (this should come before parse error, but we can't
|
// Then for magic (this should come before parse error, but we can't
|
||||||
|
|
|
@ -144,7 +144,7 @@ pub fn base58_encode_slice(data: &[u8]) -> String {
|
||||||
// 7/5 is just over log_58(256)
|
// 7/5 is just over log_58(256)
|
||||||
let mut scratch = vec![0u8; 1 + data.len() * 7 / 5];
|
let mut scratch = vec![0u8; 1 + data.len() * 7 / 5];
|
||||||
// Build in base 58
|
// Build in base 58
|
||||||
for &d256 in data.base58_layout().iter() {
|
for &d256 in &data.base58_layout() {
|
||||||
// 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.iter_mut().rev() {
|
for d58 in scratch.iter_mut().rev() {
|
||||||
|
|
|
@ -57,7 +57,7 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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: usize) -> Option<&'a mut V> {
|
pub fn lookup_mut(&mut self, key: &K, key_len: usize) -> Option<&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.
|
||||||
|
@ -66,7 +66,7 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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: usize) -> Option<&'a V> {
|
pub fn lookup(&self, key: &K, key_len: usize) -> Option<&V> {
|
||||||
let mut node = self;
|
let mut node = self;
|
||||||
let mut key_idx = 0;
|
let mut key_idx = 0;
|
||||||
|
|
||||||
|
@ -89,11 +89,11 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
// 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 usize;
|
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) => {
|
||||||
node = &**bx; // bx is a &Box<U> here, so &**bx gets &U
|
node = &**bx; // bx is a &Box<U> here, so &**bx gets &U
|
||||||
}
|
}
|
||||||
&None => { return None; }
|
None => { return None; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // end loop
|
} // end loop
|
||||||
|
@ -305,7 +305,7 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
(_, Some(child_l), Some(child_r)) => {
|
(_, Some(child_l), Some(child_r)) => {
|
||||||
tree.child_l = Some(child_l);
|
tree.child_l = Some(child_l);
|
||||||
tree.child_r = Some(child_r);
|
tree.child_r = Some(child_r);
|
||||||
return (false, ret);
|
(false, ret)
|
||||||
}
|
}
|
||||||
// One child? Consolidate
|
// One child? Consolidate
|
||||||
(bit, Some(child), None) | (bit, None, Some(child)) => {
|
(bit, Some(child), None) | (bit, None, Some(child)) => {
|
||||||
|
@ -321,11 +321,11 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
new_bit +
|
new_bit +
|
||||||
(skip_prefix << (1 + tree.skip_len as usize));
|
(skip_prefix << (1 + tree.skip_len as usize));
|
||||||
tree.skip_len += 1 + skip_len;
|
tree.skip_len += 1 + skip_len;
|
||||||
return (false, ret);
|
(false, ret)
|
||||||
}
|
}
|
||||||
// No children? Delete
|
// No children? Delete
|
||||||
(_, None, None) => {
|
(_, None, None) => {
|
||||||
return (true, ret);
|
(true, ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,9 +336,9 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
/// Count all the nodes
|
/// Count all the nodes
|
||||||
pub fn node_count(&self) -> usize {
|
pub fn node_count(&self) -> usize {
|
||||||
fn recurse<K: Copy, V>(node: &Option<Box<PatriciaTree<K, V>>>) -> usize {
|
fn recurse<K: Copy, 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 + recurse(&self.child_l) + recurse(&self.child_r)
|
1 + recurse(&self.child_l) + recurse(&self.child_r)
|
||||||
|
@ -366,8 +366,8 @@ impl<K, V> PatriciaTree<K, V>
|
||||||
|
|
||||||
impl<K: Copy + BitArray, V: Debug> Debug for PatriciaTree<K, V> {
|
impl<K: Copy + BitArray, V: Debug> Debug for PatriciaTree<K, V> {
|
||||||
/// Print the entire tree
|
/// Print the entire tree
|
||||||
fn fmt<'a>(&'a self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
fn recurse<'a, K, V>(tree: &'a PatriciaTree<K, V>, f: &mut fmt::Formatter, depth: usize) -> Result<(), fmt::Error>
|
fn recurse<K, V>(tree: &PatriciaTree<K, V>, f: &mut fmt::Formatter, depth: usize) -> Result<(), fmt::Error>
|
||||||
where K: Copy + BitArray, V: Debug
|
where K: Copy + BitArray, V: Debug
|
||||||
{
|
{
|
||||||
for i in 0..tree.skip_len as usize {
|
for i in 0..tree.skip_len as usize {
|
||||||
|
@ -453,7 +453,7 @@ impl<'a, K: Copy, V> Iterator for Items<'a, K, V> {
|
||||||
type Item = &'a V;
|
type Item = &'a V;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<&'a V> {
|
fn next(&mut self) -> Option<&'a V> {
|
||||||
fn borrow_opt<'a, K: Copy, V>(opt_ptr: &'a Option<Box<PatriciaTree<K, V>>>) -> Option<&'a PatriciaTree<K, V>> {
|
fn borrow_opt<K: Copy, V>(opt_ptr: &Option<Box<PatriciaTree<K, V>>>) -> Option<&PatriciaTree<K, V>> {
|
||||||
opt_ptr.as_ref().map(|b| &**b)
|
opt_ptr.as_ref().map(|b| &**b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +499,7 @@ impl<'a, K: Copy, V> Iterator for MutItems<'a, K, V> {
|
||||||
type Item = &'a mut V;
|
type Item = &'a mut V;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<&'a mut V> {
|
fn next(&mut self) -> Option<&'a mut V> {
|
||||||
fn borrow_opt<'a, K: Copy, V>(opt_ptr: &'a Option<Box<PatriciaTree<K, V>>>) -> *mut PatriciaTree<K, V> {
|
fn borrow_opt<K: Copy, V>(opt_ptr: &Option<Box<PatriciaTree<K, V>>>) -> *mut PatriciaTree<K, V> {
|
||||||
match *opt_ptr {
|
match *opt_ptr {
|
||||||
Some(ref data) => &**data as *const _ as *mut _,
|
Some(ref data) => &**data as *const _ as *mut _,
|
||||||
None => ptr::null_mut()
|
None => ptr::null_mut()
|
||||||
|
|
|
@ -127,7 +127,7 @@ macro_rules! construct_uint {
|
||||||
let mut me = self;
|
let mut me = self;
|
||||||
// TODO: be more efficient about this
|
// TODO: be more efficient about this
|
||||||
for i in 0..(2 * $n_words) {
|
for i in 0..(2 * $n_words) {
|
||||||
me = me + me.mul_u32((other >> (32 * i)).low_u32()) << (32 * i);
|
me = (me + me.mul_u32((other >> (32 * i)).low_u32())) << (32 * i);
|
||||||
}
|
}
|
||||||
me
|
me
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,7 @@ macro_rules! construct_uint {
|
||||||
if me[$n_words - 1 - i] < you[$n_words - 1 - i] { return ::std::cmp::Ordering::Less; }
|
if me[$n_words - 1 - i] < you[$n_words - 1 - i] { return ::std::cmp::Ordering::Less; }
|
||||||
if me[$n_words - 1 - i] > you[$n_words - 1 - i] { return ::std::cmp::Ordering::Greater; }
|
if me[$n_words - 1 - i] > you[$n_words - 1 - i] { return ::std::cmp::Ordering::Greater; }
|
||||||
}
|
}
|
||||||
return ::std::cmp::Ordering::Equal;
|
::std::cmp::Ordering::Equal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue