Make HashDB generic (#8739)
The `patricia_trie` crate is generic over the hasher (by way of HashDB) and node encoding scheme. Adds a new `patricia_trie_ethereum` crate with concrete impls for Keccak/RLP.
This commit is contained in:
@@ -23,10 +23,11 @@ use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak};
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use error::Error;
|
||||
use hashdb::HashDB;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use kvdb::DBValue;
|
||||
use bytes::{Bytes, ToPretty};
|
||||
use trie;
|
||||
use trie::{SecTrieDB, Trie, TrieFactory, TrieError};
|
||||
use trie::{Trie, Recorder};
|
||||
use ethtrie::{TrieFactory, TrieDB, SecTrieDB, Result as TrieResult};
|
||||
use pod_account::*;
|
||||
use rlp::{RlpStream, encode};
|
||||
use lru_cache::LruCache;
|
||||
@@ -199,7 +200,7 @@ impl Account {
|
||||
|
||||
/// Get (and cache) the contents of the trie's storage at `key`.
|
||||
/// Takes modified storage into account.
|
||||
pub fn storage_at(&self, db: &HashDB, key: &H256) -> trie::Result<H256> {
|
||||
pub fn storage_at(&self, db: &HashDB<KeccakHasher>, key: &H256) -> TrieResult<H256> {
|
||||
if let Some(value) = self.cached_storage_at(key) {
|
||||
return Ok(value);
|
||||
}
|
||||
@@ -278,7 +279,7 @@ impl Account {
|
||||
}
|
||||
|
||||
/// Provide a database to get `code_hash`. Should not be called if it is a contract without code.
|
||||
pub fn cache_code(&mut self, db: &HashDB) -> Option<Arc<Bytes>> {
|
||||
pub fn cache_code(&mut self, db: &HashDB<KeccakHasher>) -> Option<Arc<Bytes>> {
|
||||
// TODO: fill out self.code_cache;
|
||||
trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
||||
|
||||
@@ -307,7 +308,7 @@ impl Account {
|
||||
}
|
||||
|
||||
/// Provide a database to get `code_size`. Should not be called if it is a contract without code.
|
||||
pub fn cache_code_size(&mut self, db: &HashDB) -> bool {
|
||||
pub fn cache_code_size(&mut self, db: &HashDB<KeccakHasher>) -> bool {
|
||||
// TODO: fill out self.code_cache;
|
||||
trace!("Account::cache_code_size: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
||||
self.code_size.is_some() ||
|
||||
@@ -374,7 +375,7 @@ impl Account {
|
||||
}
|
||||
|
||||
/// Commit the `storage_changes` to the backing DB and update `storage_root`.
|
||||
pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut HashDB) -> trie::Result<()> {
|
||||
pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut HashDB<KeccakHasher>) -> TrieResult<()> {
|
||||
let mut t = trie_factory.from_existing(db, &mut self.storage_root)?;
|
||||
for (k, v) in self.storage_changes.drain() {
|
||||
// cast key and value to trait type,
|
||||
@@ -390,7 +391,7 @@ impl Account {
|
||||
}
|
||||
|
||||
/// Commit any unsaved code. `code_hash` will always return the hash of the `code_cache` after this.
|
||||
pub fn commit_code(&mut self, db: &mut HashDB) {
|
||||
pub fn commit_code(&mut self, db: &mut HashDB<KeccakHasher>) {
|
||||
trace!("Commiting code of {:?} - {:?}, {:?}", self, self.code_filth == Filth::Dirty, self.code_cache.is_empty());
|
||||
match (self.code_filth == Filth::Dirty, self.code_cache.is_empty()) {
|
||||
(true, true) => {
|
||||
@@ -472,10 +473,7 @@ impl Account {
|
||||
/// trie.
|
||||
/// `storage_key` is the hash of the desired storage key, meaning
|
||||
/// this will only work correctly under a secure trie.
|
||||
pub fn prove_storage(&self, db: &HashDB, storage_key: H256) -> Result<(Vec<Bytes>, H256), Box<TrieError>> {
|
||||
use trie::{Trie, TrieDB};
|
||||
use trie::recorder::Recorder;
|
||||
|
||||
pub fn prove_storage(&self, db: &HashDB<KeccakHasher>, storage_key: H256) -> TrieResult<(Vec<Bytes>, H256)> {
|
||||
let mut recorder = Recorder::new();
|
||||
|
||||
let trie = TrieDB::new(db, &self.storage_root)?;
|
||||
|
||||
@@ -29,14 +29,15 @@ use parking_lot::Mutex;
|
||||
use ethereum_types::{Address, H256};
|
||||
use memorydb::MemoryDB;
|
||||
use hashdb::{AsHashDB, HashDB, DBValue};
|
||||
use keccak_hasher::KeccakHasher;
|
||||
|
||||
/// State backend. See module docs for more details.
|
||||
pub trait Backend: Send {
|
||||
/// Treat the backend as a read-only hashdb.
|
||||
fn as_hashdb(&self) -> &HashDB;
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher>;
|
||||
|
||||
/// Treat the backend as a writeable hashdb.
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB;
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher>;
|
||||
|
||||
/// Add an account entry to the cache.
|
||||
fn add_to_account_cache(&mut self, addr: Address, data: Option<Account>, modified: bool);
|
||||
@@ -75,18 +76,18 @@ pub trait Backend: Send {
|
||||
// TODO: when account lookup moved into backends, this won't rely as tenuously on intended
|
||||
// usage.
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct ProofCheck(MemoryDB);
|
||||
pub struct ProofCheck(MemoryDB<KeccakHasher>);
|
||||
|
||||
impl ProofCheck {
|
||||
/// Create a new `ProofCheck` backend from the given state items.
|
||||
pub fn new(proof: &[DBValue]) -> Self {
|
||||
let mut db = MemoryDB::new();
|
||||
let mut db = MemoryDB::<KeccakHasher>::new();
|
||||
for item in proof { db.insert(item); }
|
||||
ProofCheck(db)
|
||||
}
|
||||
}
|
||||
|
||||
impl HashDB for ProofCheck {
|
||||
impl HashDB<KeccakHasher> for ProofCheck {
|
||||
fn keys(&self) -> HashMap<H256, i32> { self.0.keys() }
|
||||
fn get(&self, key: &H256) -> Option<DBValue> {
|
||||
self.0.get(key)
|
||||
@@ -107,9 +108,14 @@ impl HashDB for ProofCheck {
|
||||
fn remove(&mut self, _key: &H256) { }
|
||||
}
|
||||
|
||||
impl AsHashDB<KeccakHasher> for ProofCheck {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
}
|
||||
|
||||
impl Backend for ProofCheck {
|
||||
fn as_hashdb(&self) -> &HashDB { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB { self }
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
fn add_to_account_cache(&mut self, _addr: Address, _data: Option<Account>, _modified: bool) {}
|
||||
fn cache_code(&self, _hash: H256, _code: Arc<Vec<u8>>) {}
|
||||
fn get_cached_account(&self, _addr: &Address) -> Option<Option<Account>> { None }
|
||||
@@ -128,13 +134,18 @@ impl Backend for ProofCheck {
|
||||
/// The proof-of-execution can be extracted with `extract_proof`.
|
||||
///
|
||||
/// This doesn't cache anything or rely on the canonical state caches.
|
||||
pub struct Proving<H: AsHashDB> {
|
||||
pub struct Proving<H: AsHashDB<KeccakHasher>> {
|
||||
base: H, // state we're proving values from.
|
||||
changed: MemoryDB, // changed state via insertions.
|
||||
changed: MemoryDB<KeccakHasher>, // changed state via insertions.
|
||||
proof: Mutex<HashSet<DBValue>>,
|
||||
}
|
||||
|
||||
impl<H: AsHashDB + Send + Sync> HashDB for Proving<H> {
|
||||
impl<AH: AsHashDB<KeccakHasher> + Send + Sync> AsHashDB<KeccakHasher> for Proving<AH> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
}
|
||||
|
||||
impl<H: AsHashDB<KeccakHasher> + Send + Sync> HashDB<KeccakHasher> for Proving<H> {
|
||||
fn keys(&self) -> HashMap<H256, i32> {
|
||||
let mut keys = self.base.as_hashdb().keys();
|
||||
keys.extend(self.changed.keys());
|
||||
@@ -171,14 +182,10 @@ impl<H: AsHashDB + Send + Sync> HashDB for Proving<H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: AsHashDB + Send + Sync> Backend for Proving<H> {
|
||||
fn as_hashdb(&self) -> &HashDB {
|
||||
self
|
||||
}
|
||||
impl<H: AsHashDB<KeccakHasher> + Send + Sync> Backend for Proving<H> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB {
|
||||
self
|
||||
}
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
|
||||
fn add_to_account_cache(&mut self, _: Address, _: Option<Account>, _: bool) { }
|
||||
|
||||
@@ -197,13 +204,13 @@ impl<H: AsHashDB + Send + Sync> Backend for Proving<H> {
|
||||
fn is_known_null(&self, _: &Address) -> bool { false }
|
||||
}
|
||||
|
||||
impl<H: AsHashDB> Proving<H> {
|
||||
impl<H: AsHashDB<KeccakHasher>> Proving<H> {
|
||||
/// Create a new `Proving` over a base database.
|
||||
/// This will store all values ever fetched from that base.
|
||||
pub fn new(base: H) -> Self {
|
||||
Proving {
|
||||
base: base,
|
||||
changed: MemoryDB::new(),
|
||||
changed: MemoryDB::<KeccakHasher>::new(),
|
||||
proof: Mutex::new(HashSet::new()),
|
||||
}
|
||||
}
|
||||
@@ -215,7 +222,7 @@ impl<H: AsHashDB> Proving<H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: AsHashDB + Clone> Clone for Proving<H> {
|
||||
impl<H: AsHashDB<KeccakHasher> + Clone> Clone for Proving<H> {
|
||||
fn clone(&self) -> Self {
|
||||
Proving {
|
||||
base: self.base.clone(),
|
||||
@@ -229,12 +236,12 @@ impl<H: AsHashDB + Clone> Clone for Proving<H> {
|
||||
/// it. Doesn't cache anything.
|
||||
pub struct Basic<H>(pub H);
|
||||
|
||||
impl<H: AsHashDB + Send + Sync> Backend for Basic<H> {
|
||||
fn as_hashdb(&self) -> &HashDB {
|
||||
impl<H: AsHashDB<KeccakHasher> + Send + Sync> Backend for Basic<H> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> {
|
||||
self.0.as_hashdb()
|
||||
}
|
||||
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB {
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> {
|
||||
self.0.as_hashdb_mut()
|
||||
}
|
||||
|
||||
|
||||
@@ -44,12 +44,12 @@ use factory::VmFactory;
|
||||
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use hashdb::{HashDB, AsHashDB};
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use kvdb::DBValue;
|
||||
use bytes::Bytes;
|
||||
|
||||
use trie;
|
||||
use trie::{Trie, TrieError, TrieDB};
|
||||
use trie::recorder::Recorder;
|
||||
use trie::{Trie, TrieError, Recorder};
|
||||
use ethtrie::{TrieDB, Result as TrieResult};
|
||||
|
||||
mod account;
|
||||
mod substate;
|
||||
@@ -225,7 +225,7 @@ pub fn check_proof(
|
||||
/// Prove a transaction on the given state.
|
||||
/// Returns `None` when the transacion could not be proved,
|
||||
/// and a proof otherwise.
|
||||
pub fn prove_transaction<H: AsHashDB + Send + Sync>(
|
||||
pub fn prove_transaction<H: AsHashDB<KeccakHasher> + Send + Sync>(
|
||||
db: H,
|
||||
root: H256,
|
||||
transaction: &SignedTransaction,
|
||||
@@ -336,23 +336,23 @@ pub enum CleanupMode<'a> {
|
||||
/// Provides subset of `State` methods to query state information
|
||||
pub trait StateInfo {
|
||||
/// Get the nonce of account `a`.
|
||||
fn nonce(&self, a: &Address) -> trie::Result<U256>;
|
||||
fn nonce(&self, a: &Address) -> TrieResult<U256>;
|
||||
|
||||
/// Get the balance of account `a`.
|
||||
fn balance(&self, a: &Address) -> trie::Result<U256>;
|
||||
fn balance(&self, a: &Address) -> TrieResult<U256>;
|
||||
|
||||
/// Mutate storage of account `address` so that it is `value` for `key`.
|
||||
fn storage_at(&self, address: &Address, key: &H256) -> trie::Result<H256>;
|
||||
fn storage_at(&self, address: &Address, key: &H256) -> TrieResult<H256>;
|
||||
|
||||
/// Get accounts' code.
|
||||
fn code(&self, a: &Address) -> trie::Result<Option<Arc<Bytes>>>;
|
||||
fn code(&self, a: &Address) -> TrieResult<Option<Arc<Bytes>>>;
|
||||
}
|
||||
|
||||
impl<B: Backend> StateInfo for State<B> {
|
||||
fn nonce(&self, a: &Address) -> trie::Result<U256> { State::nonce(self, a) }
|
||||
fn balance(&self, a: &Address) -> trie::Result<U256> { State::balance(self, a) }
|
||||
fn storage_at(&self, address: &Address, key: &H256) -> trie::Result<H256> { State::storage_at(self, address, key) }
|
||||
fn code(&self, address: &Address) -> trie::Result<Option<Arc<Bytes>>> { State::code(self, address) }
|
||||
fn nonce(&self, a: &Address) -> TrieResult<U256> { State::nonce(self, a) }
|
||||
fn balance(&self, a: &Address) -> TrieResult<U256> { State::balance(self, a) }
|
||||
fn storage_at(&self, address: &Address, key: &H256) -> TrieResult<H256> { State::storage_at(self, address, key) }
|
||||
fn code(&self, address: &Address) -> TrieResult<Option<Arc<Bytes>>> { State::code(self, address) }
|
||||
}
|
||||
|
||||
const SEC_TRIE_DB_UNWRAP_STR: &'static str = "A state can only be created with valid root. Creating a SecTrieDB with a valid root will not fail. \
|
||||
@@ -379,9 +379,9 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Creates new state with existing state root
|
||||
pub fn from_existing(db: B, root: H256, account_start_nonce: U256, factories: Factories) -> Result<State<B>, TrieError> {
|
||||
pub fn from_existing(db: B, root: H256, account_start_nonce: U256, factories: Factories) -> TrieResult<State<B>> {
|
||||
if !db.as_hashdb().contains(&root) {
|
||||
return Err(TrieError::InvalidStateRoot(root));
|
||||
return Err(Box::new(TrieError::InvalidStateRoot(root)));
|
||||
}
|
||||
|
||||
let state = State {
|
||||
@@ -481,7 +481,7 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Destroy the current object and return single account data.
|
||||
pub fn into_account(self, account: &Address) -> trie::Result<(Option<Arc<Bytes>>, HashMap<H256, H256>)> {
|
||||
pub fn into_account(self, account: &Address) -> TrieResult<(Option<Arc<Bytes>>, HashMap<H256, H256>)> {
|
||||
// TODO: deconstruct without cloning.
|
||||
let account = self.require(account, true)?;
|
||||
Ok((account.code().clone(), account.storage_changes().clone()))
|
||||
@@ -504,43 +504,43 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Determine whether an account exists.
|
||||
pub fn exists(&self, a: &Address) -> trie::Result<bool> {
|
||||
pub fn exists(&self, a: &Address) -> TrieResult<bool> {
|
||||
// Bloom filter does not contain empty accounts, so it is important here to
|
||||
// check if account exists in the database directly before EIP-161 is in effect.
|
||||
self.ensure_cached(a, RequireCache::None, false, |a| a.is_some())
|
||||
}
|
||||
|
||||
/// Determine whether an account exists and if not empty.
|
||||
pub fn exists_and_not_null(&self, a: &Address) -> trie::Result<bool> {
|
||||
pub fn exists_and_not_null(&self, a: &Address) -> TrieResult<bool> {
|
||||
self.ensure_cached(a, RequireCache::None, false, |a| a.map_or(false, |a| !a.is_null()))
|
||||
}
|
||||
|
||||
/// Determine whether an account exists and has code or non-zero nonce.
|
||||
pub fn exists_and_has_code_or_nonce(&self, a: &Address) -> trie::Result<bool> {
|
||||
pub fn exists_and_has_code_or_nonce(&self, a: &Address) -> TrieResult<bool> {
|
||||
self.ensure_cached(a, RequireCache::CodeSize, false,
|
||||
|a| a.map_or(false, |a| a.code_hash() != KECCAK_EMPTY || *a.nonce() != self.account_start_nonce))
|
||||
}
|
||||
|
||||
/// Get the balance of account `a`.
|
||||
pub fn balance(&self, a: &Address) -> trie::Result<U256> {
|
||||
pub fn balance(&self, a: &Address) -> TrieResult<U256> {
|
||||
self.ensure_cached(a, RequireCache::None, true,
|
||||
|a| a.as_ref().map_or(U256::zero(), |account| *account.balance()))
|
||||
}
|
||||
|
||||
/// Get the nonce of account `a`.
|
||||
pub fn nonce(&self, a: &Address) -> trie::Result<U256> {
|
||||
pub fn nonce(&self, a: &Address) -> TrieResult<U256> {
|
||||
self.ensure_cached(a, RequireCache::None, true,
|
||||
|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) -> trie::Result<Option<H256>> {
|
||||
pub fn storage_root(&self, a: &Address) -> TrieResult<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) -> trie::Result<H256> {
|
||||
pub fn storage_at(&self, address: &Address, key: &H256) -> TrieResult<H256> {
|
||||
// Storage key search and update works like this:
|
||||
// 1. If there's an entry for the account in the local cache check for the key and return it if found.
|
||||
// 2. If there's an entry for the account in the global cache check for the key or load it into that account.
|
||||
@@ -602,25 +602,25 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Get accounts' code.
|
||||
pub fn code(&self, a: &Address) -> trie::Result<Option<Arc<Bytes>>> {
|
||||
pub fn code(&self, a: &Address) -> TrieResult<Option<Arc<Bytes>>> {
|
||||
self.ensure_cached(a, RequireCache::Code, true,
|
||||
|a| a.as_ref().map_or(None, |a| a.code().clone()))
|
||||
}
|
||||
|
||||
/// Get an account's code hash.
|
||||
pub fn code_hash(&self, a: &Address) -> trie::Result<H256> {
|
||||
pub fn code_hash(&self, a: &Address) -> TrieResult<H256> {
|
||||
self.ensure_cached(a, RequireCache::None, true,
|
||||
|a| a.as_ref().map_or(KECCAK_EMPTY, |a| a.code_hash()))
|
||||
}
|
||||
|
||||
/// Get accounts' code size.
|
||||
pub fn code_size(&self, a: &Address) -> trie::Result<Option<usize>> {
|
||||
pub fn code_size(&self, a: &Address) -> TrieResult<Option<usize>> {
|
||||
self.ensure_cached(a, RequireCache::CodeSize, true,
|
||||
|a| a.as_ref().and_then(|a| a.code_size()))
|
||||
}
|
||||
|
||||
/// Add `incr` to the balance of account `a`.
|
||||
pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) -> trie::Result<()> {
|
||||
pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) -> TrieResult<()> {
|
||||
trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a)?);
|
||||
let is_value_transfer = !incr.is_zero();
|
||||
if is_value_transfer || (cleanup_mode == CleanupMode::ForceCreate && !self.exists(a)?) {
|
||||
@@ -635,7 +635,7 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Subtract `decr` from the balance of account `a`.
|
||||
pub fn sub_balance(&mut self, a: &Address, decr: &U256, cleanup_mode: &mut CleanupMode) -> trie::Result<()> {
|
||||
pub fn sub_balance(&mut self, a: &Address, decr: &U256, cleanup_mode: &mut CleanupMode) -> TrieResult<()> {
|
||||
trace!(target: "state", "sub_balance({}, {}): {}", a, decr, self.balance(a)?);
|
||||
if !decr.is_zero() || !self.exists(a)? {
|
||||
self.require(a, false)?.sub_balance(decr);
|
||||
@@ -647,19 +647,19 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Subtracts `by` from the balance of `from` and adds it to that of `to`.
|
||||
pub fn transfer_balance(&mut self, from: &Address, to: &Address, by: &U256, mut cleanup_mode: CleanupMode) -> trie::Result<()> {
|
||||
pub fn transfer_balance(&mut self, from: &Address, to: &Address, by: &U256, mut cleanup_mode: CleanupMode) -> TrieResult<()> {
|
||||
self.sub_balance(from, by, &mut cleanup_mode)?;
|
||||
self.add_balance(to, by, cleanup_mode)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Increment the nonce of account `a` by 1.
|
||||
pub fn inc_nonce(&mut self, a: &Address) -> trie::Result<()> {
|
||||
pub fn inc_nonce(&mut self, a: &Address) -> TrieResult<()> {
|
||||
self.require(a, false).map(|mut x| x.inc_nonce())
|
||||
}
|
||||
|
||||
/// Mutate storage of account `a` so that it is `value` for `key`.
|
||||
pub fn set_storage(&mut self, a: &Address, key: H256, value: H256) -> trie::Result<()> {
|
||||
pub fn set_storage(&mut self, a: &Address, key: H256, value: H256) -> TrieResult<()> {
|
||||
trace!(target: "state", "set_storage({}:{:x} to {:x})", a, key, value);
|
||||
if self.storage_at(a, &key)? != value {
|
||||
self.require(a, false)?.set_storage(key, value)
|
||||
@@ -670,13 +670,13 @@ impl<B: Backend> State<B> {
|
||||
|
||||
/// Initialise the code of account `a` so that it is `code`.
|
||||
/// NOTE: Account should have been created with `new_contract`.
|
||||
pub fn init_code(&mut self, a: &Address, code: Bytes) -> trie::Result<()> {
|
||||
pub fn init_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> {
|
||||
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{})?.init_code(code);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset the code of account `a` so that it is `code`.
|
||||
pub fn reset_code(&mut self, a: &Address, code: Bytes) -> trie::Result<()> {
|
||||
pub fn reset_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> {
|
||||
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{})?.reset_code(code);
|
||||
Ok(())
|
||||
}
|
||||
@@ -753,7 +753,7 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
}
|
||||
|
||||
fn touch(&mut self, a: &Address) -> trie::Result<()> {
|
||||
fn touch(&mut self, a: &Address) -> TrieResult<()> {
|
||||
self.require(a, false)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -809,7 +809,7 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Remove any touched empty or dust accounts.
|
||||
pub fn kill_garbage(&mut self, touched: &HashSet<Address>, remove_empty_touched: bool, min_balance: &Option<U256>, kill_contracts: bool) -> trie::Result<()> {
|
||||
pub fn kill_garbage(&mut self, touched: &HashSet<Address>, remove_empty_touched: bool, min_balance: &Option<U256>, kill_contracts: bool) -> TrieResult<()> {
|
||||
let to_kill: HashSet<_> = {
|
||||
self.cache.borrow().iter().filter_map(|(address, ref entry)|
|
||||
if touched.contains(address) && // Check all touched accounts
|
||||
@@ -850,7 +850,7 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Populate a PodAccount map from this state, with another state as the account and storage query.
|
||||
pub fn to_pod_diff<X: Backend>(&mut self, query: &State<X>) -> trie::Result<PodState> {
|
||||
pub fn to_pod_diff<X: Backend>(&mut self, query: &State<X>) -> TrieResult<PodState> {
|
||||
assert!(self.checkpoints.borrow().is_empty());
|
||||
|
||||
// Merge PodAccount::to_pod for cache of self and `query`.
|
||||
@@ -858,7 +858,7 @@ impl<B: Backend> State<B> {
|
||||
.chain(query.cache.borrow().keys().cloned())
|
||||
.collect::<BTreeSet<_>>();
|
||||
|
||||
Ok(PodState::from(all_addresses.into_iter().fold(Ok(BTreeMap::new()), |m: trie::Result<_>, address| {
|
||||
Ok(PodState::from(all_addresses.into_iter().fold(Ok(BTreeMap::new()), |m: TrieResult<_>, address| {
|
||||
let mut m = m?;
|
||||
|
||||
let account = self.ensure_cached(&address, RequireCache::Code, true, |acc| {
|
||||
@@ -886,7 +886,7 @@ impl<B: Backend> State<B> {
|
||||
})?;
|
||||
|
||||
if let Some((balance, nonce, storage_keys, code)) = account {
|
||||
let storage = storage_keys.into_iter().fold(Ok(BTreeMap::new()), |s: trie::Result<_>, key| {
|
||||
let storage = storage_keys.into_iter().fold(Ok(BTreeMap::new()), |s: TrieResult<_>, key| {
|
||||
let mut s = s?;
|
||||
|
||||
s.insert(key, self.storage_at(&address, &key)?);
|
||||
@@ -904,14 +904,14 @@ impl<B: Backend> State<B> {
|
||||
|
||||
/// Returns a `StateDiff` describing the difference from `orig` to `self`.
|
||||
/// Consumes self.
|
||||
pub fn diff_from<X: Backend>(&self, mut orig: State<X>) -> trie::Result<StateDiff> {
|
||||
pub fn diff_from<X: Backend>(&self, mut orig: State<X>) -> TrieResult<StateDiff> {
|
||||
let pod_state_post = self.to_pod();
|
||||
let pod_state_pre = orig.to_pod_diff(self)?;
|
||||
Ok(pod_state::diff_pod(&pod_state_pre, &pod_state_post))
|
||||
}
|
||||
|
||||
// load required account data from the databases.
|
||||
fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB) {
|
||||
fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB<KeccakHasher>) {
|
||||
if let RequireCache::None = require {
|
||||
return;
|
||||
}
|
||||
@@ -943,7 +943,7 @@ impl<B: Backend> State<B> {
|
||||
/// Check caches for required data
|
||||
/// First searches for account in the local, then the shared cache.
|
||||
/// Populates local cache if nothing found.
|
||||
fn ensure_cached<F, U>(&self, a: &Address, require: RequireCache, check_null: bool, f: F) -> trie::Result<U>
|
||||
fn ensure_cached<F, U>(&self, a: &Address, require: RequireCache, check_null: bool, f: F) -> TrieResult<U>
|
||||
where F: Fn(Option<&Account>) -> U {
|
||||
// check local cache first
|
||||
if let Some(ref mut maybe_acc) = self.cache.borrow_mut().get_mut(a) {
|
||||
@@ -984,13 +984,13 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too.
|
||||
fn require<'a>(&'a self, a: &Address, require_code: bool) -> trie::Result<RefMut<'a, Account>> {
|
||||
fn require<'a>(&'a self, a: &Address, require_code: bool) -> TrieResult<RefMut<'a, Account>> {
|
||||
self.require_or_from(a, require_code, || Account::new_basic(0u8.into(), self.account_start_nonce), |_|{})
|
||||
}
|
||||
|
||||
/// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too.
|
||||
/// If it doesn't exist, make account equal the evaluation of `default`.
|
||||
fn require_or_from<'a, F, G>(&'a self, a: &Address, require_code: bool, default: F, not_default: G) -> trie::Result<RefMut<'a, Account>>
|
||||
fn require_or_from<'a, F, G>(&'a self, a: &Address, require_code: bool, default: F, not_default: G) -> TrieResult<RefMut<'a, Account>>
|
||||
where F: FnOnce() -> Account, G: FnOnce(&mut Account),
|
||||
{
|
||||
let contains_key = self.cache.borrow().contains_key(a);
|
||||
@@ -1037,7 +1037,7 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Replace account code and storage. Creates account if it does not exist.
|
||||
pub fn patch_account(&self, a: &Address, code: Arc<Bytes>, storage: HashMap<H256, H256>) -> trie::Result<()> {
|
||||
pub fn patch_account(&self, a: &Address, code: Arc<Bytes>, storage: HashMap<H256, H256>) -> TrieResult<()> {
|
||||
Ok(self.require(a, false)?.reset_code_and_storage(code, storage))
|
||||
}
|
||||
}
|
||||
@@ -1049,7 +1049,7 @@ impl<B: Backend> State<B> {
|
||||
/// If the account doesn't exist in the trie, prove that and return defaults.
|
||||
/// Requires a secure trie to be used for accurate results.
|
||||
/// `account_key` == keccak(address)
|
||||
pub fn prove_account(&self, account_key: H256) -> trie::Result<(Vec<Bytes>, BasicAccount)> {
|
||||
pub fn prove_account(&self, account_key: H256) -> TrieResult<(Vec<Bytes>, BasicAccount)> {
|
||||
let mut recorder = Recorder::new();
|
||||
let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?;
|
||||
let maybe_account: Option<BasicAccount> = {
|
||||
@@ -1074,7 +1074,7 @@ impl<B: Backend> State<B> {
|
||||
/// Requires a secure trie to be used for correctness.
|
||||
/// `account_key` == keccak(address)
|
||||
/// `storage_key` == keccak(key)
|
||||
pub fn prove_storage(&self, account_key: H256, storage_key: H256) -> trie::Result<(Vec<Bytes>, H256)> {
|
||||
pub fn prove_storage(&self, account_key: H256, storage_key: H256) -> TrieResult<(Vec<Bytes>, H256)> {
|
||||
// TODO: probably could look into cache somehow but it's keyed by
|
||||
// address, not keccak(address).
|
||||
let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?;
|
||||
|
||||
Reference in New Issue
Block a user