Merge remote-tracking branch 'origin/master' into rpc-middleware
This commit is contained in:
@@ -29,7 +29,7 @@ byteorder = "0.5"
|
||||
transient-hashmap = "0.1"
|
||||
linked-hash-map = "0.3.0"
|
||||
evmjit = { path = "../evmjit", optional = true }
|
||||
clippy = { version = "0.0.96", optional = true}
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
ethash = { path = "../ethash" }
|
||||
ethcore-util = { path = "../util" }
|
||||
ethcore-io = { path = "../util/io" }
|
||||
|
||||
Submodule ethcore/res/ethereum/tests updated: d509c75936...e8f4624b7f
@@ -121,10 +121,6 @@ impl<'db> HashDB for AccountDB<'db>{
|
||||
fn remove(&mut self, _key: &H256) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_aux(&self, hash: &[u8]) -> Option<DBValue> {
|
||||
self.db.get_aux(hash)
|
||||
}
|
||||
}
|
||||
|
||||
/// DB backend wrapper for Account trie
|
||||
@@ -197,18 +193,6 @@ impl<'db> HashDB for AccountDBMut<'db>{
|
||||
let key = combine_key(&self.address_hash, key);
|
||||
self.db.remove(&key)
|
||||
}
|
||||
|
||||
fn insert_aux(&mut self, hash: Vec<u8>, value: Vec<u8>) {
|
||||
self.db.insert_aux(hash, value);
|
||||
}
|
||||
|
||||
fn get_aux(&self, hash: &[u8]) -> Option<DBValue> {
|
||||
self.db.get_aux(hash)
|
||||
}
|
||||
|
||||
fn remove_aux(&mut self, hash: &[u8]) {
|
||||
self.db.remove_aux(hash);
|
||||
}
|
||||
}
|
||||
|
||||
struct Wrapping<'db>(&'db HashDB);
|
||||
|
||||
@@ -594,9 +594,9 @@ mod tests {
|
||||
use factory::Factories;
|
||||
use state_db::StateDB;
|
||||
use views::BlockView;
|
||||
use util::Address;
|
||||
use util::{Address, TrieFactory};
|
||||
use util::hash::FixedHash;
|
||||
|
||||
use util::trie::TrieSpec;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||
@@ -637,7 +637,7 @@ mod tests {
|
||||
let genesis_header = spec.genesis_header();
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = b.close_and_lock();
|
||||
@@ -653,7 +653,7 @@ mod tests {
|
||||
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap()
|
||||
.close_and_lock().seal(engine, vec![]).unwrap();
|
||||
@@ -662,7 +662,7 @@ mod tests {
|
||||
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
|
||||
|
||||
assert_eq!(e.rlp_bytes(), orig_bytes);
|
||||
@@ -681,7 +681,7 @@ mod tests {
|
||||
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let mut uncle1_header = Header::new();
|
||||
@@ -697,7 +697,7 @@ mod tests {
|
||||
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
|
||||
|
||||
let bytes = e.rlp_bytes();
|
||||
|
||||
@@ -22,7 +22,7 @@ use std::time::{Instant};
|
||||
use time::precise_time_ns;
|
||||
|
||||
// util
|
||||
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock};
|
||||
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, Hashable};
|
||||
use util::{journaldb, TrieFactory, Trie};
|
||||
use util::trie::TrieSpec;
|
||||
use util::{U256, H256, Address, H2048, Uint, FixedHash};
|
||||
@@ -172,9 +172,10 @@ impl Client {
|
||||
false => TrieSpec::Secure,
|
||||
};
|
||||
|
||||
let trie_factory = TrieFactory::new(trie_spec);
|
||||
let journal_db = journaldb::new(db.clone(), config.pruning, ::db::COL_STATE);
|
||||
let mut state_db = StateDB::new(journal_db, config.state_cache_size);
|
||||
if state_db.journal_db().is_empty() && try!(spec.ensure_db_good(&mut state_db)) {
|
||||
if state_db.journal_db().is_empty() && try!(spec.ensure_db_good(&mut state_db, &trie_factory)) {
|
||||
let mut batch = DBTransaction::new(&db);
|
||||
try!(state_db.journal_under(&mut batch, 0, &spec.genesis_header().hash()));
|
||||
try!(db.write(batch).map_err(ClientError::Database));
|
||||
@@ -216,7 +217,7 @@ impl Client {
|
||||
|
||||
let factories = Factories {
|
||||
vm: EvmFactory::new(config.vm_type.clone(), config.jump_table_size),
|
||||
trie: TrieFactory::new(trie_spec),
|
||||
trie: trie_factory,
|
||||
accountdb: Default::default(),
|
||||
};
|
||||
|
||||
@@ -869,8 +870,8 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
|
||||
fn keep_alive(&self) {
|
||||
let should_wake = match &*self.mode.lock() {
|
||||
&Mode::Dark(..) | &Mode::Passive(..) => true,
|
||||
let should_wake = match *self.mode.lock() {
|
||||
Mode::Dark(..) | Mode::Passive(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
if should_wake {
|
||||
@@ -952,6 +953,10 @@ impl BlockChainClient for Client {
|
||||
self.state_at(id).map(|s| s.nonce(address))
|
||||
}
|
||||
|
||||
fn storage_root(&self, address: &Address, id: BlockID) -> Option<H256> {
|
||||
self.state_at(id).and_then(|s| s.storage_root(address))
|
||||
}
|
||||
|
||||
fn block_hash(&self, id: BlockID) -> Option<H256> {
|
||||
let chain = self.chain.read();
|
||||
Self::block_hash(&chain, id)
|
||||
@@ -969,7 +974,7 @@ impl BlockChainClient for Client {
|
||||
self.state_at(id).map(|s| s.storage_at(address, position))
|
||||
}
|
||||
|
||||
fn list_accounts(&self, id: BlockID) -> Option<Vec<Address>> {
|
||||
fn list_accounts(&self, id: BlockID, after: Option<&Address>, count: u64) -> Option<Vec<Address>> {
|
||||
if !self.factories.trie.is_fat() {
|
||||
trace!(target: "fatdb", "list_accounts: Not a fat DB");
|
||||
return None;
|
||||
@@ -989,18 +994,68 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
};
|
||||
|
||||
let iter = match trie.iter() {
|
||||
let mut iter = match trie.iter() {
|
||||
Ok(iter) => iter,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
if let Some(after) = after {
|
||||
if let Err(e) = iter.seek(after) {
|
||||
trace!(target: "fatdb", "list_accounts: Couldn't seek the DB: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
let accounts = iter.filter_map(|item| {
|
||||
item.ok().map(|(addr, _)| Address::from_slice(&addr))
|
||||
}).collect();
|
||||
}).take(count as usize).collect();
|
||||
|
||||
Some(accounts)
|
||||
}
|
||||
|
||||
fn list_storage(&self, id: BlockID, account: &Address, after: Option<&H256>, count: u64) -> Option<Vec<H256>> {
|
||||
if !self.factories.trie.is_fat() {
|
||||
trace!(target: "fatdb", "list_stroage: Not a fat DB");
|
||||
return None;
|
||||
}
|
||||
|
||||
let state = match self.state_at(id) {
|
||||
Some(state) => state,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let root = match state.storage_root(account) {
|
||||
Some(root) => root,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let (_, db) = state.drop();
|
||||
let account_db = self.factories.accountdb.readonly(db.as_hashdb(), account.sha3());
|
||||
let trie = match self.factories.trie.readonly(account_db.as_hashdb(), &root) {
|
||||
Ok(trie) => trie,
|
||||
_ => {
|
||||
trace!(target: "fatdb", "list_storage: Couldn't open the DB");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let mut iter = match trie.iter() {
|
||||
Ok(iter) => iter,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
if let Some(after) = after {
|
||||
if let Err(e) = iter.seek(after) {
|
||||
trace!(target: "fatdb", "list_accounts: Couldn't seek the DB: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
let keys = iter.filter_map(|item| {
|
||||
item.ok().map(|(key, _)| H256::from_slice(&key))
|
||||
}).take(count as usize).collect();
|
||||
|
||||
Some(keys)
|
||||
}
|
||||
|
||||
fn transaction(&self, id: TransactionID) -> Option<LocalizedTransaction> {
|
||||
self.transaction_address(id).and_then(|address| self.chain.read().transaction(&address))
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ impl MiningBlockChainClient for TestBlockChainClient {
|
||||
let genesis_header = self.spec.genesis_header();
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
self.spec.ensure_db_good(&mut db).unwrap();
|
||||
self.spec.ensure_db_good(&mut db, &TrieFactory::default()).unwrap();
|
||||
|
||||
let last_hashes = vec![genesis_header.hash()];
|
||||
let mut open_block = OpenBlock::new(
|
||||
@@ -385,6 +385,10 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_root(&self, _address: &Address, _id: BlockID) -> Option<H256> {
|
||||
None
|
||||
}
|
||||
|
||||
fn latest_nonce(&self, address: &Address) -> U256 {
|
||||
self.nonce(address, BlockID::Latest).unwrap()
|
||||
}
|
||||
@@ -416,10 +420,13 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
}
|
||||
}
|
||||
|
||||
fn list_accounts(&self, _id: BlockID) -> Option<Vec<Address>> {
|
||||
fn list_accounts(&self, _id: BlockID, _after: Option<&Address>, _count: u64) -> Option<Vec<Address>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn list_storage(&self, _id: BlockID, _account: &Address, _after: Option<&H256>, _count: u64) -> Option<Vec<H256>> {
|
||||
None
|
||||
}
|
||||
fn transaction(&self, _id: TransactionID) -> Option<LocalizedTransaction> {
|
||||
None // Simple default.
|
||||
}
|
||||
|
||||
@@ -68,6 +68,10 @@ pub trait BlockChainClient : Sync + Send {
|
||||
/// May not fail on BlockID::Latest.
|
||||
fn nonce(&self, address: &Address, id: BlockID) -> Option<U256>;
|
||||
|
||||
/// Attempt to get address storage root at given block.
|
||||
/// May not fail on BlockID::Latest.
|
||||
fn storage_root(&self, address: &Address, id: BlockID) -> Option<H256>;
|
||||
|
||||
/// Get address nonce at the latest block's state.
|
||||
fn latest_nonce(&self, address: &Address) -> U256 {
|
||||
self.nonce(address, BlockID::Latest)
|
||||
@@ -114,7 +118,12 @@ pub trait BlockChainClient : Sync + Send {
|
||||
}
|
||||
|
||||
/// Get a list of all accounts in the block `id`, if fat DB is in operation, otherwise `None`.
|
||||
fn list_accounts(&self, id: BlockID) -> Option<Vec<Address>>;
|
||||
/// If `after` is set the list starts with the following item.
|
||||
fn list_accounts(&self, id: BlockID, after: Option<&Address>, count: u64) -> Option<Vec<Address>>;
|
||||
|
||||
/// Get a list of all storage keys in the block `id`, if fat DB is in operation, otherwise `None`.
|
||||
/// If `after` is set the list starts with the following item.
|
||||
fn list_storage(&self, id: BlockID, account: &Address, after: Option<&H256>, count: u64) -> Option<Vec<H256>>;
|
||||
|
||||
/// Get transaction with given hash.
|
||||
fn transaction(&self, id: TransactionID) -> Option<LocalizedTransaction>;
|
||||
|
||||
@@ -124,7 +124,7 @@ impl AuthorityRound {
|
||||
}
|
||||
|
||||
fn step_proposer(&self, step: usize) -> &Address {
|
||||
let ref p = self.our_params;
|
||||
let p = &self.our_params;
|
||||
p.authorities.get(step % p.authority_n).expect("There are authority_n authorities; taking number modulo authority_n gives number in authority_n range; qed")
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ impl Engine for AuthorityRound {
|
||||
fn on_close_block(&self, _block: &mut ExecutedBlock) {}
|
||||
|
||||
fn is_sealer(&self, author: &Address) -> Option<bool> {
|
||||
let ref p = self.our_params;
|
||||
let p = &self.our_params;
|
||||
Some(p.authorities.contains(author))
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ impl Engine for AuthorityRound {
|
||||
|
||||
let step = try!(header_step(header));
|
||||
// Check if parent is from a previous step.
|
||||
if step == try!(header_step(parent)) {
|
||||
if step == try!(header_step(parent)) {
|
||||
trace!(target: "poa", "Multiple blocks proposed for step {}.", step);
|
||||
try!(Err(BlockError::DoubleVote(header.author().clone())));
|
||||
}
|
||||
@@ -315,6 +315,7 @@ impl Engine for AuthorityRound {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::*;
|
||||
use util::trie::TrieSpec;
|
||||
use env_info::EnvInfo;
|
||||
use header::Header;
|
||||
use error::{Error, BlockError};
|
||||
@@ -384,9 +385,9 @@ mod tests {
|
||||
let engine = &*spec.engine;
|
||||
let genesis_header = spec.genesis_header();
|
||||
let mut db1 = get_temp_state_db().take();
|
||||
spec.ensure_db_good(&mut db1).unwrap();
|
||||
spec.ensure_db_good(&mut db1, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let mut db2 = get_temp_state_db().take();
|
||||
spec.ensure_db_good(&mut db2).unwrap();
|
||||
spec.ensure_db_good(&mut db2, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b1 = b1.close_and_lock();
|
||||
|
||||
@@ -184,6 +184,7 @@ impl Engine for BasicAuthority {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::*;
|
||||
use util::trie::TrieSpec;
|
||||
use block::*;
|
||||
use env_info::EnvInfo;
|
||||
use error::{BlockError, Error};
|
||||
@@ -256,7 +257,7 @@ mod tests {
|
||||
let genesis_header = spec.genesis_header();
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = b.close_and_lock();
|
||||
|
||||
@@ -68,6 +68,7 @@ impl Engine for InstantSeal {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::*;
|
||||
use util::trie::TrieSpec;
|
||||
use tests::helpers::*;
|
||||
use account_provider::AccountProvider;
|
||||
use spec::Spec;
|
||||
@@ -84,7 +85,7 @@ mod tests {
|
||||
let genesis_header = spec.genesis_header();
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = b.close_and_lock();
|
||||
|
||||
@@ -422,6 +422,7 @@ impl Header {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::*;
|
||||
use util::trie::TrieSpec;
|
||||
use block::*;
|
||||
use tests::helpers::*;
|
||||
use env_info::EnvInfo;
|
||||
@@ -438,7 +439,7 @@ mod tests {
|
||||
let genesis_header = spec.genesis_header();
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = b.close();
|
||||
@@ -452,7 +453,7 @@ mod tests {
|
||||
let genesis_header = spec.genesis_header();
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let mut uncle = Header::new();
|
||||
|
||||
@@ -72,6 +72,7 @@ pub fn new_morden() -> Spec { load(include_bytes!("../../res/ethereum/morden.jso
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::*;
|
||||
use util::trie::TrieSpec;
|
||||
use state::*;
|
||||
use super::*;
|
||||
use tests::helpers::*;
|
||||
@@ -84,7 +85,7 @@ mod tests {
|
||||
let genesis_header = spec.genesis_header();
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(&mut db).unwrap();
|
||||
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let s = State::from_existing(db, genesis_header.state_root().clone(), engine.account_start_nonce(), Default::default()).unwrap();
|
||||
assert_eq!(s.balance(&"0000000000000000000000000000000000000001".into()), 1u64.into());
|
||||
assert_eq!(s.balance(&"0000000000000000000000000000000000000002".into()), 1u64.into());
|
||||
|
||||
@@ -197,19 +197,17 @@ impl<Gas: CostType> Gasometer<Gas> {
|
||||
let address = u256_to_address(stack.peek(1));
|
||||
let is_value_transfer = !stack.peek(2).is_zero();
|
||||
|
||||
if instruction == instructions::CALL {
|
||||
if (
|
||||
!schedule.no_empty && !ext.exists(&address)
|
||||
) || (
|
||||
schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address)
|
||||
) {
|
||||
gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into()));
|
||||
}
|
||||
};
|
||||
if instruction == instructions::CALL && (
|
||||
(!schedule.no_empty && !ext.exists(&address))
|
||||
||
|
||||
(schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address))
|
||||
) {
|
||||
gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into()));
|
||||
}
|
||||
|
||||
if is_value_transfer {
|
||||
gas = overflowing!(gas.overflow_add(schedule.call_value_transfer_gas.into()));
|
||||
};
|
||||
}
|
||||
|
||||
let requested = *stack.peek(0);
|
||||
|
||||
@@ -347,7 +345,7 @@ fn test_mem_gas_cost() {
|
||||
let result = gasometer.mem_gas_cost(&schedule, current_mem_size, &mem_size);
|
||||
|
||||
// then
|
||||
if let Ok(_) = result {
|
||||
if result.is_ok() {
|
||||
assert!(false, "Should fail with OutOfGas");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ impl Ext for FakeExt {
|
||||
}
|
||||
|
||||
fn exists_and_not_null(&self, address: &Address) -> bool {
|
||||
self.balances.get(address).map_or(false, |b| !b.is_zero())
|
||||
self.balances.get(address).map_or(false, |b| !b.is_zero())
|
||||
}
|
||||
|
||||
fn origin_balance(&self) -> U256 {
|
||||
@@ -103,7 +103,7 @@ impl Ext for FakeExt {
|
||||
}
|
||||
|
||||
fn balance(&self, address: &Address) -> U256 {
|
||||
*self.balances.get(address).unwrap()
|
||||
self.balances[address]
|
||||
}
|
||||
|
||||
fn blockhash(&self, number: &U256) -> H256 {
|
||||
|
||||
@@ -445,7 +445,7 @@ impl<'a> Executive<'a> {
|
||||
|
||||
trace!("exec::finalize: Refunding refund_value={}, sender={}\n", refund_value, sender);
|
||||
// Below: NoEmpty is safe since the sender must already be non-null to have sent this transaction
|
||||
self.state.add_balance(&sender, &refund_value, CleanupMode::NoEmpty);
|
||||
self.state.add_balance(&sender, &refund_value, CleanupMode::NoEmpty);
|
||||
trace!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author);
|
||||
self.state.add_balance(&self.info.author, &fees_value, substate.to_cleanup_mode(&schedule));
|
||||
|
||||
@@ -514,9 +514,11 @@ impl<'a> Executive<'a> {
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
use ethkey::{Generator, Random};
|
||||
use super::*;
|
||||
use util::*;
|
||||
use util::{H256, U256, U512, Address, Uint, FixedHash, FromHex, FromStr};
|
||||
use util::bytes::BytesRef;
|
||||
use action_params::{ActionParams, ActionValue};
|
||||
use env_info::EnvInfo;
|
||||
use evm::{Factory, VMType};
|
||||
|
||||
@@ -151,7 +151,7 @@ impl GasPriceCalibrator {
|
||||
if Instant::now() >= self.next_calibration {
|
||||
let usd_per_tx = self.options.usd_per_tx;
|
||||
trace!(target: "miner", "Getting price info");
|
||||
if let Ok(_) = PriceInfo::get(move |price: PriceInfo| {
|
||||
let price_info = PriceInfo::get(move |price: PriceInfo| {
|
||||
trace!(target: "miner", "Price info arrived: {:?}", price);
|
||||
let usd_per_eth = price.ethusd;
|
||||
let wei_per_usd: f32 = 1.0e18 / usd_per_eth;
|
||||
@@ -159,7 +159,9 @@ impl GasPriceCalibrator {
|
||||
let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx;
|
||||
info!(target: "miner", "Updated conversion rate to Ξ1 = {} ({} wei/gas)", Colour::White.bold().paint(format!("US${}", usd_per_eth)), Colour::Yellow.bold().paint(format!("{}", wei_per_gas)));
|
||||
set_price(U256::from(wei_per_gas as u64));
|
||||
}) {
|
||||
});
|
||||
|
||||
if price_info.is_ok() {
|
||||
self.next_calibration = Instant::now() + self.options.recalibration_period;
|
||||
} else {
|
||||
warn!(target: "miner", "Unable to update Ether price.");
|
||||
@@ -1139,15 +1141,16 @@ impl MinerService for Miner {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use super::super::{MinerService, PrioritizationStrategy};
|
||||
use super::*;
|
||||
use util::*;
|
||||
use block::IsBlock;
|
||||
use util::{U256, Uint, FromHex};
|
||||
use ethkey::{Generator, Random};
|
||||
use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult};
|
||||
use header::BlockNumber;
|
||||
use types::transaction::{Transaction, SignedTransaction, Action};
|
||||
use block::*;
|
||||
use spec::Spec;
|
||||
use tests::helpers::{generate_dummy_client};
|
||||
|
||||
|
||||
@@ -990,7 +990,7 @@ impl TransactionQueue {
|
||||
let mut update_last_nonce_to = None;
|
||||
{
|
||||
let by_nonce = self.future.by_address.row_mut(&address);
|
||||
if let None = by_nonce {
|
||||
if by_nonce.is_none() {
|
||||
return;
|
||||
}
|
||||
let mut by_nonce = by_nonce.expect("None is tested in early-exit condition above; qed");
|
||||
@@ -1212,12 +1212,12 @@ mod test {
|
||||
use util::table::*;
|
||||
use util::*;
|
||||
use ethkey::{Random, Generator};
|
||||
use transaction::*;
|
||||
use error::{Error, TransactionError};
|
||||
use super::*;
|
||||
use super::{TransactionSet, TransactionOrder, VerifiedTransaction};
|
||||
use miner::local_transactions::LocalTransactionsList;
|
||||
use client::TransactionImportResult;
|
||||
use transaction::{SignedTransaction, Transaction, Action};
|
||||
|
||||
fn unwrap_tx_err(err: Result<TransactionImportResult, Error>) -> TransactionError {
|
||||
match err.unwrap_err() {
|
||||
|
||||
@@ -64,13 +64,13 @@ impl PodAccount {
|
||||
}
|
||||
|
||||
/// Place additional data into given hash DB.
|
||||
pub fn insert_additional(&self, db: &mut AccountDBMut) {
|
||||
pub fn insert_additional(&self, db: &mut AccountDBMut, factory: &TrieFactory) {
|
||||
match self.code {
|
||||
Some(ref c) if !c.is_empty() => { db.insert(c); }
|
||||
_ => {}
|
||||
}
|
||||
let mut r = H256::new();
|
||||
let mut t = SecTrieDBMut::new(db, &mut r);
|
||||
let mut t = factory.create(db, &mut r);
|
||||
for (k, v) in &self.storage {
|
||||
if let Err(e) = t.insert(k, &rlp::encode(&U256::from(&**v))) {
|
||||
warn!("Encountered potential DB corruption: {}", e);
|
||||
|
||||
@@ -552,11 +552,11 @@ const POW_VERIFY_RATE: f32 = 0.02;
|
||||
pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &Engine, chain: &BlockChain, body: Option<&[u8]>, always: bool) -> Result<(), ::error::Error> {
|
||||
if always || rng.gen::<f32>() <= POW_VERIFY_RATE {
|
||||
match chain.block_header(header.parent_hash()) {
|
||||
Some(parent) => engine.verify_block_family(&header, &parent, body),
|
||||
None => engine.verify_block_seal(&header),
|
||||
Some(parent) => engine.verify_block_family(header, &parent, body),
|
||||
None => engine.verify_block_seal(header),
|
||||
}
|
||||
} else {
|
||||
engine.verify_block_basic(&header, body)
|
||||
engine.verify_block_basic(header, body)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,13 +244,13 @@ impl Spec {
|
||||
}
|
||||
|
||||
/// Ensure that the given state DB has the trie nodes in for the genesis state.
|
||||
pub fn ensure_db_good(&self, db: &mut StateDB) -> Result<bool, Box<TrieError>> {
|
||||
pub fn ensure_db_good(&self, db: &mut StateDB, factory: &TrieFactory) -> Result<bool, Box<TrieError>> {
|
||||
if !db.as_hashdb().contains(&self.state_root()) {
|
||||
trace!(target: "spec", "ensure_db_good: Fresh database? Cannot find state root {}", self.state_root());
|
||||
let mut root = H256::new();
|
||||
|
||||
{
|
||||
let mut t = SecTrieDBMut::new(db.as_hashdb_mut(), &mut root);
|
||||
let mut t = factory.create(db.as_hashdb_mut(), &mut root);
|
||||
for (address, account) in self.genesis_state.get().iter() {
|
||||
try!(t.insert(&**address, &account.rlp()));
|
||||
}
|
||||
@@ -258,7 +258,7 @@ impl Spec {
|
||||
trace!(target: "spec", "ensure_db_good: Populated sec trie; root is {}", root);
|
||||
for (address, account) in self.genesis_state.get().iter() {
|
||||
db.note_non_null_account(address);
|
||||
account.insert_additional(&mut AccountDBMut::new(db.as_hashdb_mut(), address));
|
||||
account.insert_additional(&mut AccountDBMut::new(db.as_hashdb_mut(), address), factory);
|
||||
}
|
||||
assert!(db.as_hashdb().contains(&self.state_root()));
|
||||
Ok(true)
|
||||
|
||||
@@ -314,11 +314,10 @@ impl Account {
|
||||
self.code_hash == SHA3_EMPTY
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// return the storage root associated with this account or None if it has been altered via the overlay.
|
||||
/// Return the storage root associated with this account or None if it has been altered via the overlay.
|
||||
pub fn storage_root(&self) -> Option<&H256> { if self.storage_is_clean() {Some(&self.storage_root)} else {None} }
|
||||
|
||||
/// return the storage overlay.
|
||||
/// Return the storage overlay.
|
||||
pub fn storage_changes(&self) -> &HashMap<H256, H256> { &self.storage_changes }
|
||||
|
||||
/// Increment the nonce of the account by one.
|
||||
@@ -445,11 +444,10 @@ impl fmt::Debug for Account {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use rlp::{UntrustedRlp, RlpType, View, Compressible};
|
||||
use util::*;
|
||||
use super::*;
|
||||
use account_db::*;
|
||||
use rlp::*;
|
||||
|
||||
#[test]
|
||||
fn account_compress() {
|
||||
|
||||
@@ -369,6 +369,12 @@ impl State {
|
||||
|a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce()))
|
||||
}
|
||||
|
||||
/// Get the storage root of account `a`.
|
||||
pub fn storage_root(&self, a: &Address) -> Option<H256> {
|
||||
self.ensure_cached(a, RequireCache::None, true,
|
||||
|a| a.as_ref().and_then(|account| account.storage_root().cloned()))
|
||||
}
|
||||
|
||||
/// Mutate storage of account `address` so that it is `value` for `key`.
|
||||
pub fn storage_at(&self, address: &Address, key: &H256) -> H256 {
|
||||
// Storage key search and update works like this:
|
||||
@@ -445,6 +451,7 @@ impl State {
|
||||
}
|
||||
|
||||
/// Add `incr` to the balance of account `a`.
|
||||
#[cfg_attr(feature="dev", allow(single_match))]
|
||||
pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) {
|
||||
trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a));
|
||||
let is_value_transfer = !incr.is_zero();
|
||||
|
||||
@@ -57,6 +57,7 @@ impl Substate {
|
||||
}
|
||||
|
||||
/// Get the cleanup mode object from this.
|
||||
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||
pub fn to_cleanup_mode(&mut self, schedule: &Schedule) -> CleanupMode {
|
||||
match (schedule.no_empty, schedule.kill_empty) {
|
||||
(false, _) => CleanupMode::ForceCreate,
|
||||
|
||||
@@ -397,6 +397,7 @@ impl StateDB {
|
||||
}
|
||||
|
||||
/// Get cached code based on hash.
|
||||
#[cfg_attr(feature="dev", allow(map_clone))]
|
||||
pub fn get_cached_code(&self, hash: &H256) -> Option<Arc<Vec<u8>>> {
|
||||
let mut cache = self.code_cache.lock();
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ fn should_return_registrar() {
|
||||
&db_config
|
||||
).unwrap();
|
||||
let params = client.additional_params();
|
||||
let address = params.get("registrar").unwrap();
|
||||
let address = ¶ms["registrar"];
|
||||
|
||||
assert_eq!(address.len(), 40);
|
||||
assert!(U256::from_str(address).is_ok());
|
||||
@@ -93,7 +93,7 @@ fn imports_good_block() {
|
||||
&db_config
|
||||
).unwrap();
|
||||
let good_block = get_good_dummy_block();
|
||||
if let Err(_) = client.import_block(good_block) {
|
||||
if client.import_block(good_block).is_err() {
|
||||
panic!("error importing block being good by definition");
|
||||
}
|
||||
client.flush_queue();
|
||||
@@ -203,18 +203,18 @@ fn can_collect_garbage() {
|
||||
|
||||
#[test]
|
||||
fn can_generate_gas_price_median() {
|
||||
let client_result = generate_dummy_client_with_data(3, 1, &vec_into![1, 2, 3]);
|
||||
let client_result = generate_dummy_client_with_data(3, 1, slice_into![1, 2, 3]);
|
||||
let client = client_result.reference();
|
||||
assert_eq!(Some(U256::from(2)), client.gas_price_median(3));
|
||||
|
||||
let client_result = generate_dummy_client_with_data(4, 1, &vec_into![1, 4, 3, 2]);
|
||||
let client_result = generate_dummy_client_with_data(4, 1, slice_into![1, 4, 3, 2]);
|
||||
let client = client_result.reference();
|
||||
assert_eq!(Some(U256::from(3)), client.gas_price_median(4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_generate_gas_price_histogram() {
|
||||
let client_result = generate_dummy_client_with_data(20, 1, &vec_into![6354,8593,6065,4842,7845,7002,689,4958,4250,6098,5804,4320,643,8895,2296,8589,7145,2000,2512,1408]);
|
||||
let client_result = generate_dummy_client_with_data(20, 1, slice_into![6354,8593,6065,4842,7845,7002,689,4958,4250,6098,5804,4320,643,8895,2296,8589,7145,2000,2512,1408]);
|
||||
let client = client_result.reference();
|
||||
|
||||
let hist = client.gas_price_histogram(20, 5).unwrap();
|
||||
@@ -224,7 +224,7 @@ fn can_generate_gas_price_histogram() {
|
||||
|
||||
#[test]
|
||||
fn empty_gas_price_histogram() {
|
||||
let client_result = generate_dummy_client_with_data(20, 0, &vec_into![]);
|
||||
let client_result = generate_dummy_client_with_data(20, 0, slice_into![]);
|
||||
let client = client_result.reference();
|
||||
|
||||
assert!(client.gas_price_histogram(20, 5).is_none());
|
||||
|
||||
@@ -18,6 +18,7 @@ use ethkey::KeyPair;
|
||||
use io::*;
|
||||
use client::{BlockChainClient, Client, ClientConfig};
|
||||
use util::*;
|
||||
use util::trie::TrieSpec;
|
||||
use spec::*;
|
||||
use state_db::StateDB;
|
||||
use block::{OpenBlock, Drain};
|
||||
@@ -157,7 +158,7 @@ pub fn generate_dummy_client_with_spec_and_data<F>(get_test_spec: F, block_numbe
|
||||
|
||||
let mut db_result = get_temp_state_db();
|
||||
let mut db = db_result.take();
|
||||
test_spec.ensure_db_good(&mut db).unwrap();
|
||||
test_spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
|
||||
let genesis_header = test_spec.genesis_header();
|
||||
|
||||
let mut rolling_timestamp = 40;
|
||||
@@ -262,7 +263,7 @@ pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<
|
||||
).unwrap();
|
||||
|
||||
for block in &blocks {
|
||||
if let Err(_) = client.import_block(block.clone()) {
|
||||
if client.import_block(block.clone()).is_err() {
|
||||
panic!("panic importing block which is well-formed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,16 @@
|
||||
pub use std::time::Duration;
|
||||
use client::Mode as ClientMode;
|
||||
|
||||
/// IPC-capable shadow-type for client::config::Mode
|
||||
/// IPC-capable shadow-type for `client::config::Mode`
|
||||
#[derive(Clone, Binary, Debug)]
|
||||
pub enum Mode {
|
||||
/// Same as ClientMode::Off.
|
||||
/// Same as `ClientMode::Off`.
|
||||
Off,
|
||||
/// Same as ClientMode::Dark; values in seconds.
|
||||
/// Same as `ClientMode::Dark`; values in seconds.
|
||||
Dark(u64),
|
||||
/// Same as ClientMode::Passive; values in seconds.
|
||||
/// Same as `ClientMode::Passive`; values in seconds.
|
||||
Passive(u64, u64),
|
||||
/// Same as ClientMode::Active.
|
||||
/// Same as `ClientMode::Active`.
|
||||
Active,
|
||||
}
|
||||
|
||||
@@ -52,4 +52,4 @@ impl From<Mode> for ClientMode {
|
||||
Mode::Active => ClientMode::Active,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ pub struct Transaction {
|
||||
impl Transaction {
|
||||
/// Append object with a without signature into RLP stream
|
||||
pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option<u8>) {
|
||||
s.begin_list(if let None = network_id { 6 } else { 9 });
|
||||
s.begin_list(if network_id.is_none() { 6 } else { 9 });
|
||||
s.append(&self.nonce);
|
||||
s.append(&self.gas_price);
|
||||
s.append(&self.gas);
|
||||
@@ -210,7 +210,7 @@ pub struct SignedTransaction {
|
||||
/// Plain Transaction.
|
||||
unsigned: Transaction,
|
||||
/// The V field of the signature; the LS bit described which half of the curve our point falls
|
||||
/// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
|
||||
/// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
|
||||
v: u8,
|
||||
/// The R field of the signature; helps describe the point on the curve.
|
||||
r: U256,
|
||||
@@ -304,7 +304,7 @@ impl SignedTransaction {
|
||||
/// 0 if `v` would have been 27 under "Electrum" notation, 1 if 28 or 4 if invalid.
|
||||
pub fn standard_v(&self) -> u8 { match self.v { v if v == 27 || v == 28 || v > 36 => (v - 1) % 2, _ => 4 } }
|
||||
|
||||
/// The network ID, or `None` if this is a global transaction.
|
||||
/// The network ID, or `None` if this is a global transaction.
|
||||
pub fn network_id(&self) -> Option<u8> {
|
||||
match self.v {
|
||||
v if v > 36 => Some((v - 35) / 2),
|
||||
@@ -461,7 +461,7 @@ fn should_agree_with_vitalik() {
|
||||
let signed: SignedTransaction = decode(&FromHex::from_hex(tx_data).unwrap());
|
||||
signed.check_low_s().unwrap();
|
||||
assert_eq!(signed.sender().unwrap(), address.into());
|
||||
flushln!("networkid: {:?}", signed.network_id());
|
||||
flushln!("networkid: {:?}", signed.network_id());
|
||||
};
|
||||
|
||||
test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce")
|
||||
@@ -474,4 +474,4 @@ fn should_agree_with_vitalik() {
|
||||
test_vector("f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xd37922162ab7cea97c97a87551ed02c9a38b7332")
|
||||
test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x9bddad43f934d313c2b79ca28a432dd2b7281029")
|
||||
test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x3c24d7329e92f84f08556ceb6df1cdb0104ca49f")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use header::{BlockNumber, Header};
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use transaction::SignedTransaction;
|
||||
use views::BlockView;
|
||||
use time::get_time;
|
||||
|
||||
/// Preprocessed block data gathered in `verify_block_unordered` call
|
||||
pub struct PreverifiedBlock {
|
||||
@@ -209,6 +210,10 @@ pub fn verify_header_params(header: &Header, engine: &Engine) -> Result<(), Erro
|
||||
if header.number() != 0 && header.extra_data().len() > maximum_extra_data_size {
|
||||
return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: Some(maximum_extra_data_size), found: header.extra_data().len() })));
|
||||
}
|
||||
let max_time = get_time().sec as u64 + 30;
|
||||
if header.timestamp() > max_time {
|
||||
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: header.timestamp() })))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -258,6 +263,7 @@ mod tests {
|
||||
use tests::helpers::*;
|
||||
use types::log_entry::{LogEntry, LocalizedLogEntry};
|
||||
use rlp::View;
|
||||
use time::get_time;
|
||||
|
||||
fn check_ok(result: Result<(), Error>) {
|
||||
result.unwrap_or_else(|e| panic!("Block verification failed: {:?}", e));
|
||||
@@ -271,6 +277,14 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_fail_timestamp(result: Result<(), Error>) {
|
||||
match result {
|
||||
Err(Error::Block(BlockError::InvalidTimestamp(_))) => (),
|
||||
Err(other) => panic!("Block verification failed.\nExpected: InvalidTimestamp\nGot: {:?}", other),
|
||||
Ok(_) => panic!("Block verification failed.\nExpected: InvalidTimestamp\nGot: Ok"),
|
||||
}
|
||||
}
|
||||
|
||||
struct TestBlockChain {
|
||||
blocks: HashMap<H256, Bytes>,
|
||||
numbers: HashMap<BlockNumber, H256>,
|
||||
@@ -515,6 +529,14 @@ mod tests {
|
||||
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc),
|
||||
InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp() + 1), found: header.timestamp() }));
|
||||
|
||||
header = good.clone();
|
||||
header.set_timestamp(2450000000);
|
||||
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
|
||||
|
||||
header = good.clone();
|
||||
header.set_timestamp(get_time().sec as u64 + 40);
|
||||
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
|
||||
|
||||
header = good.clone();
|
||||
header.set_number(9);
|
||||
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc),
|
||||
|
||||
Reference in New Issue
Block a user