Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Backports for beta #1888

Merged
merged 11 commits into from
Aug 9, 2016
109 changes: 75 additions & 34 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions ethcore/src/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,12 +775,20 @@ impl BlockChain {

/// Applt pending insertion updates
pub fn commit(&self) {
let mut best_block = self.best_block.write();
let mut write_hashes = self.block_hashes.write();
let mut write_txs = self.transaction_addresses.write();
let mut pending_best_block = self.pending_best_block.write();
let mut pending_write_hashes = self.pending_block_hashes.write();
let mut pending_write_txs = self.pending_transaction_addresses.write();

for n in pending_write_hashes.keys() {
self.note_used(CacheID::BlockHashes(*n));
}
for hash in pending_write_txs.keys() {
self.note_used(CacheID::TransactionAddresses(hash.clone()));
}

let mut best_block = self.best_block.write();
let mut write_hashes = self.block_hashes.write();
let mut write_txs = self.transaction_addresses.write();
// update best block
if let Some(block) = pending_best_block.take() {
*best_block = block;
Expand Down
34 changes: 25 additions & 9 deletions ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,19 +594,35 @@ impl Client {
}
}

/// Take a snapshot.
pub fn take_snapshot<W: snapshot_io::SnapshotWriter + Send>(&self, writer: W) -> Result<(), ::error::Error> {
/// Take a snapshot at the given block.
/// If the ID given is "latest", this will default to 1000 blocks behind.
pub fn take_snapshot<W: snapshot_io::SnapshotWriter + Send>(&self, writer: W, at: BlockID, p: &snapshot::Progress) -> Result<(), ::error::Error> {
let db = self.state_db.lock().boxed_clone();
let best_block_number = self.chain_info().best_block_number;
let start_block_number = if best_block_number > 1000 {
best_block_number - 1000
} else {
0
let block_number = try!(self.block_number(at).ok_or(snapshot::Error::InvalidStartingBlock(at)));

if best_block_number > HISTORY + block_number && db.is_pruned() {
return Err(snapshot::Error::OldBlockPrunedDB.into());
}

let start_hash = match at {
BlockID::Latest => {
let start_num = if best_block_number > 1000 {
best_block_number - 1000
} else {
0
};

self.block_hash(BlockID::Number(start_num))
.expect("blocks within HISTORY are always stored.")
}
_ => match self.block_hash(at) {
Some(hash) => hash,
None => return Err(snapshot::Error::InvalidStartingBlock(at).into()),
},
};
let start_hash = self.block_hash(BlockID::Number(start_block_number))
.expect("blocks within HISTORY are always stored.");

try!(snapshot::take_snapshot(&self.chain, start_hash, db.as_hashdb(), writer));
try!(snapshot::take_snapshot(&self.chain, start_hash, db.as_hashdb(), writer, p));

Ok(())
}
Expand Down
22 changes: 20 additions & 2 deletions ethcore/src/evm/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,14 @@ impl CostType for usize {
}

fn from_u256(val: U256) -> Result<Self> {
if U256::from(val.low_u64()) != val {
let res = val.low_u64() as usize;

// validate if value fits into usize
if U256::from(res) != val {
return Err(Error::OutOfGas);
}
Ok(val.low_u64() as usize)

Ok(res)
}

fn as_usize(&self) -> usize {
Expand Down Expand Up @@ -191,6 +195,7 @@ pub trait Evm {


#[test]
#[cfg(test)]
fn should_calculate_overflow_mul_shr_without_overflow() {
// given
let num = 1048576;
Expand All @@ -207,6 +212,7 @@ fn should_calculate_overflow_mul_shr_without_overflow() {
}

#[test]
#[cfg(test)]
fn should_calculate_overflow_mul_shr_with_overflow() {
// given
let max = ::std::u64::MAX;
Expand All @@ -225,3 +231,15 @@ fn should_calculate_overflow_mul_shr_with_overflow() {
assert!(o1);
}

#[test]
#[cfg(test)]
fn should_validate_u256_to_usize_conversion() {
// given
let v = U256::from(::std::usize::MAX) + U256::from(1);

// when
let res = usize::from_u256(v);

// then
assert!(res.is_err());
}
8 changes: 4 additions & 4 deletions ethcore/src/evm/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,11 +515,11 @@ impl<Cost: CostType> Interpreter<Cost> {
Ok(InstructionResult::Ok)
}

fn copy_data_to_memory(&mut self, stack: &mut Stack<U256>, data: &[u8]) {
fn copy_data_to_memory(&mut self, stack: &mut Stack<U256>, source: &[u8]) {
let dest_offset = stack.pop_back();
let source_offset = stack.pop_back();
let size = stack.pop_back();
let source_size = U256::from(data.len());
let source_size = U256::from(source.len());

let output_end = match source_offset > source_size || size > source_size || source_offset + size > source_size {
true => {
Expand All @@ -531,14 +531,14 @@ impl<Cost: CostType> Interpreter<Cost> {
for i in zero_slice.iter_mut() {
*i = 0;
}
data.len()
source.len()
},
false => (size.low_u64() + source_offset.low_u64()) as usize
};

if source_offset < source_size {
let output_begin = source_offset.low_u64() as usize;
self.mem.write_slice(dest_offset, &data[output_begin..output_end]);
self.mem.write_slice(dest_offset, &source[output_begin..output_end]);
}
}

Expand Down
7 changes: 3 additions & 4 deletions ethcore/src/miner/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,11 @@ pub struct Miner {
// NOTE [ToDr] When locking always lock in this order!
transaction_queue: Arc<Mutex<TransactionQueue>>,
sealing_work: Mutex<SealingWork>,

next_allowed_reseal: Mutex<Instant>,
sealing_block_last_request: Mutex<u64>,
// for sealing...
options: MinerOptions,

next_allowed_reseal: Mutex<Instant>,
sealing_block_last_request: Mutex<u64>,
gas_range_target: RwLock<(U256, U256)>,
author: RwLock<Address>,
extra_data: RwLock<Bytes>,
Expand Down Expand Up @@ -736,11 +735,11 @@ impl MinerService for Miner {
fn update_sealing(&self, chain: &MiningBlockChainClient) {
trace!(target: "miner", "update_sealing");
let requires_reseal = {
let has_local_transactions = self.transaction_queue.lock().has_local_pending_transactions();
let mut sealing_work = self.sealing_work.lock();
if sealing_work.enabled {
trace!(target: "miner", "update_sealing: sealing enabled");
let current_no = chain.chain_info().best_block_number;
let has_local_transactions = self.transaction_queue.lock().has_local_pending_transactions();
let last_request = *self.sealing_block_last_request.lock();
let should_disable_sealing = !self.forced_sealing()
&& !has_local_transactions
Expand Down
13 changes: 11 additions & 2 deletions ethcore/src/snapshot/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

use std::fmt;

use ids::BlockID;

use util::H256;
use util::trie::TrieError;
use util::rlp::DecoderError;
Expand All @@ -26,9 +28,13 @@ use util::rlp::DecoderError;
#[derive(Debug)]
pub enum Error {
/// Invalid starting block for snapshot.
InvalidStartingBlock(H256),
InvalidStartingBlock(BlockID),
/// Block not found.
BlockNotFound(H256),
/// Incomplete chain.
IncompleteChain,
/// Old starting block in a pruned database.
OldBlockPrunedDB,
/// Trie error.
Trie(TrieError),
/// Decoder error.
Expand All @@ -40,8 +46,11 @@ pub enum Error {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::InvalidStartingBlock(ref hash) => write!(f, "Invalid starting block hash: {}", hash),
Error::InvalidStartingBlock(ref id) => write!(f, "Invalid starting block: {:?}", id),
Error::BlockNotFound(ref hash) => write!(f, "Block not found in chain: {}", hash),
Error::IncompleteChain => write!(f, "Cannot create snapshot due to incomplete chain."),
Error::OldBlockPrunedDB => write!(f, "Attempted to create a snapshot at an old block while using \
a pruned database. Please re-run with the --pruning archive flag."),
Error::Io(ref err) => err.fmt(f),
Error::Decoder(ref err) => err.fmt(f),
Error::Trie(ref err) => err.fmt(f),
Expand Down
Loading