Merge branch 'master' into client-provider
This commit is contained in:
@@ -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};
|
||||
@@ -173,9 +173,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));
|
||||
@@ -217,7 +218,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(),
|
||||
};
|
||||
|
||||
@@ -870,8 +871,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 {
|
||||
@@ -953,6 +954,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)
|
||||
@@ -970,7 +975,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;
|
||||
@@ -990,18 +995,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))
|
||||
}
|
||||
|
||||
@@ -334,7 +334,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(
|
||||
@@ -386,6 +386,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()
|
||||
}
|
||||
@@ -417,10 +421,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.
|
||||
}
|
||||
|
||||
@@ -69,6 +69,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)
|
||||
@@ -115,7 +119,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>;
|
||||
|
||||
Reference in New Issue
Block a user