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:
@@ -15,12 +15,13 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! DB backend wrapper for Account trie
|
||||
use std::collections::HashMap;
|
||||
use hash::{KECCAK_NULL_RLP, keccak};
|
||||
use ethereum_types::H256;
|
||||
use hash::{KECCAK_NULL_RLP, keccak};
|
||||
use hashdb::{HashDB, AsHashDB};
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use kvdb::DBValue;
|
||||
use hashdb::HashDB;
|
||||
use rlp::NULL_RLP;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[cfg(test)]
|
||||
use ethereum_types::Address;
|
||||
@@ -44,7 +45,7 @@ fn combine_key<'a>(address_hash: &'a H256, key: &'a H256) -> H256 {
|
||||
/// A factory for different kinds of account dbs.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Factory {
|
||||
/// Mangle hashes based on address.
|
||||
/// Mangle hashes based on address. This is the default.
|
||||
Mangled,
|
||||
/// Don't mangle hashes.
|
||||
Plain,
|
||||
@@ -57,7 +58,7 @@ impl Default for Factory {
|
||||
impl Factory {
|
||||
/// Create a read-only accountdb.
|
||||
/// This will panic when write operations are called.
|
||||
pub fn readonly<'db>(&self, db: &'db HashDB, address_hash: H256) -> Box<HashDB + 'db> {
|
||||
pub fn readonly<'db>(&self, db: &'db HashDB<KeccakHasher>, address_hash: H256) -> Box<HashDB<KeccakHasher> + 'db> {
|
||||
match *self {
|
||||
Factory::Mangled => Box::new(AccountDB::from_hash(db, address_hash)),
|
||||
Factory::Plain => Box::new(Wrapping(db)),
|
||||
@@ -65,7 +66,7 @@ impl Factory {
|
||||
}
|
||||
|
||||
/// Create a new mutable hashdb.
|
||||
pub fn create<'db>(&self, db: &'db mut HashDB, address_hash: H256) -> Box<HashDB + 'db> {
|
||||
pub fn create<'db>(&self, db: &'db mut HashDB<KeccakHasher>, address_hash: H256) -> Box<HashDB<KeccakHasher> + 'db> {
|
||||
match *self {
|
||||
Factory::Mangled => Box::new(AccountDBMut::from_hash(db, address_hash)),
|
||||
Factory::Plain => Box::new(WrappingMut(db)),
|
||||
@@ -77,19 +78,19 @@ impl Factory {
|
||||
/// DB backend wrapper for Account trie
|
||||
/// Transforms trie node keys for the database
|
||||
pub struct AccountDB<'db> {
|
||||
db: &'db HashDB,
|
||||
db: &'db HashDB<KeccakHasher>,
|
||||
address_hash: H256,
|
||||
}
|
||||
|
||||
impl<'db> AccountDB<'db> {
|
||||
/// Create a new AccountDB from an address.
|
||||
#[cfg(test)]
|
||||
pub fn new(db: &'db HashDB, address: &Address) -> Self {
|
||||
pub fn new(db: &'db HashDB<KeccakHasher>, address: &Address) -> Self {
|
||||
Self::from_hash(db, keccak(address))
|
||||
}
|
||||
|
||||
/// Create a new AcountDB from an address' hash.
|
||||
pub fn from_hash(db: &'db HashDB, address_hash: H256) -> Self {
|
||||
pub fn from_hash(db: &'db HashDB<KeccakHasher>, address_hash: H256) -> Self {
|
||||
AccountDB {
|
||||
db: db,
|
||||
address_hash: address_hash,
|
||||
@@ -97,7 +98,12 @@ impl<'db> AccountDB<'db> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> HashDB for AccountDB<'db>{
|
||||
impl<'db> AsHashDB<KeccakHasher> for AccountDB<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher> for AccountDB<'db> {
|
||||
fn keys(&self) -> HashMap<H256, i32> {
|
||||
unimplemented!()
|
||||
}
|
||||
@@ -131,19 +137,19 @@ impl<'db> HashDB for AccountDB<'db>{
|
||||
|
||||
/// DB backend wrapper for Account trie
|
||||
pub struct AccountDBMut<'db> {
|
||||
db: &'db mut HashDB,
|
||||
db: &'db mut HashDB<KeccakHasher>,
|
||||
address_hash: H256,
|
||||
}
|
||||
|
||||
impl<'db> AccountDBMut<'db> {
|
||||
/// Create a new AccountDB from an address.
|
||||
#[cfg(test)]
|
||||
pub fn new(db: &'db mut HashDB, address: &Address) -> Self {
|
||||
pub fn new(db: &'db mut HashDB<KeccakHasher>, address: &Address) -> Self {
|
||||
Self::from_hash(db, keccak(address))
|
||||
}
|
||||
|
||||
/// Create a new AcountDB from an address' hash.
|
||||
pub fn from_hash(db: &'db mut HashDB, address_hash: H256) -> Self {
|
||||
pub fn from_hash(db: &'db mut HashDB<KeccakHasher>, address_hash: H256) -> Self {
|
||||
AccountDBMut {
|
||||
db: db,
|
||||
address_hash: address_hash,
|
||||
@@ -156,7 +162,7 @@ impl<'db> AccountDBMut<'db> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> HashDB for AccountDBMut<'db>{
|
||||
impl<'db> HashDB<KeccakHasher> for AccountDBMut<'db>{
|
||||
fn keys(&self) -> HashMap<H256, i32> {
|
||||
unimplemented!()
|
||||
}
|
||||
@@ -202,9 +208,19 @@ impl<'db> HashDB for AccountDBMut<'db>{
|
||||
}
|
||||
}
|
||||
|
||||
struct Wrapping<'db>(&'db HashDB);
|
||||
impl<'db> AsHashDB<KeccakHasher> for AccountDBMut<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB for Wrapping<'db> {
|
||||
struct Wrapping<'db>(&'db HashDB<KeccakHasher>);
|
||||
|
||||
impl<'db> AsHashDB<KeccakHasher> for Wrapping<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher> for Wrapping<'db> {
|
||||
fn keys(&self) -> HashMap<H256, i32> {
|
||||
unimplemented!()
|
||||
}
|
||||
@@ -236,9 +252,13 @@ impl<'db> HashDB for Wrapping<'db> {
|
||||
}
|
||||
}
|
||||
|
||||
struct WrappingMut<'db>(&'db mut HashDB);
|
||||
struct WrappingMut<'db>(&'db mut HashDB<KeccakHasher>);
|
||||
impl<'db> AsHashDB<KeccakHasher> for WrappingMut<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB for WrappingMut<'db>{
|
||||
impl<'db> HashDB<KeccakHasher> for WrappingMut<'db>{
|
||||
fn keys(&self) -> HashMap<H256, i32> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@@ -17,28 +17,27 @@
|
||||
//! Blockchain block.
|
||||
|
||||
use std::cmp;
|
||||
use std::sync::Arc;
|
||||
use std::collections::HashSet;
|
||||
use hash::{keccak, KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP};
|
||||
use triehash::ordered_trie_root;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rlp::{Rlp, RlpStream, Encodable, Decodable, DecoderError, encode_list};
|
||||
use ethereum_types::{H256, U256, Address, Bloom};
|
||||
use bytes::Bytes;
|
||||
use unexpected::{Mismatch, OutOfBounds};
|
||||
|
||||
use vm::{EnvInfo, LastHashes};
|
||||
use engines::EthEngine;
|
||||
use error::{Error, BlockError};
|
||||
use ethereum_types::{H256, U256, Address, Bloom};
|
||||
use factory::Factories;
|
||||
use hash::{keccak, KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP};
|
||||
use header::{Header, ExtendedHeader};
|
||||
use receipt::{Receipt, TransactionOutcome};
|
||||
use state::State;
|
||||
use rlp::{Rlp, RlpStream, Encodable, Decodable, DecoderError, encode_list};
|
||||
use state_db::StateDB;
|
||||
use state::State;
|
||||
use trace::Tracing;
|
||||
use transaction::{UnverifiedTransaction, SignedTransaction, Error as TransactionError};
|
||||
use triehash::ordered_trie_root;
|
||||
use unexpected::{Mismatch, OutOfBounds};
|
||||
use verification::PreverifiedBlock;
|
||||
use views::BlockView;
|
||||
use vm::{EnvInfo, LastHashes};
|
||||
|
||||
/// A block, encoded as it is on the block chain.
|
||||
#[derive(Default, Debug, Clone, PartialEq)]
|
||||
|
||||
@@ -17,37 +17,38 @@
|
||||
//! Blockchain database.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::{mem, io};
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::{mem, io};
|
||||
use itertools::Itertools;
|
||||
use blooms_db;
|
||||
use heapsize::HeapSizeOf;
|
||||
use ethereum_types::{H256, Bloom, BloomRef, U256};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use bytes::Bytes;
|
||||
use rlp::RlpStream;
|
||||
use rlp_compress::{compress, decompress, blocks_swapper};
|
||||
use header::*;
|
||||
use transaction::*;
|
||||
use views::{BlockView, HeaderView};
|
||||
use log_entry::{LogEntry, LocalizedLogEntry};
|
||||
use receipt::Receipt;
|
||||
|
||||
use ansi_term::Colour;
|
||||
use blockchain::{CacheSize, ImportRoute, Config};
|
||||
use blockchain::best_block::{BestBlock, BestAncientBlock};
|
||||
use blockchain::block_info::{BlockInfo, BlockLocation, BranchBecomingCanonChainData};
|
||||
use blockchain::extras::{BlockReceipts, BlockDetails, TransactionAddress, EPOCH_KEY_PREFIX, EpochTransitions};
|
||||
use blockchain::update::{ExtrasUpdate, ExtrasInsert};
|
||||
use blooms_db;
|
||||
use bytes::Bytes;
|
||||
use cache_manager::CacheManager;
|
||||
use db::{self, Writable, Readable, CacheUpdatePolicy};
|
||||
use encoded;
|
||||
use engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition};
|
||||
use engines::ForkChoice;
|
||||
use ethereum_types::{H256, Bloom, BloomRef, U256};
|
||||
use header::*;
|
||||
use heapsize::HeapSizeOf;
|
||||
use itertools::Itertools;
|
||||
use kvdb::{DBTransaction, KeyValueDB};
|
||||
use log_entry::{LogEntry, LocalizedLogEntry};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use rayon::prelude::*;
|
||||
use receipt::Receipt;
|
||||
use rlp_compress::{compress, decompress, blocks_swapper};
|
||||
use rlp::RlpStream;
|
||||
use transaction::*;
|
||||
use types::blockchain_info::BlockChainInfo;
|
||||
use types::tree_route::TreeRoute;
|
||||
use blockchain::update::{ExtrasUpdate, ExtrasInsert};
|
||||
use blockchain::{CacheSize, ImportRoute, Config};
|
||||
use db::{self, Writable, Readable, CacheUpdatePolicy};
|
||||
use cache_manager::CacheManager;
|
||||
use encoded;
|
||||
use engines::ForkChoice;
|
||||
use engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition};
|
||||
use rayon::prelude::*;
|
||||
use ansi_term::Colour;
|
||||
use kvdb::{DBTransaction, KeyValueDB};
|
||||
use views::{BlockView, HeaderView};
|
||||
|
||||
/// Database backing `BlockChain`.
|
||||
pub trait BlockChainDB: Send + Sync {
|
||||
|
||||
@@ -16,18 +16,18 @@
|
||||
|
||||
//! Blockchain DB extras.
|
||||
|
||||
use std::ops;
|
||||
use std::io::Write;
|
||||
use std::ops;
|
||||
|
||||
use db::Key;
|
||||
use engines::epoch::{Transition as EpochTransition};
|
||||
use ethereum_types::{H256, H264, U256};
|
||||
use header::BlockNumber;
|
||||
use heapsize::HeapSizeOf;
|
||||
use kvdb::PREFIX_LEN as DB_PREFIX_LEN;
|
||||
use receipt::Receipt;
|
||||
use rlp;
|
||||
|
||||
use heapsize::HeapSizeOf;
|
||||
use ethereum_types::{H256, H264, U256};
|
||||
use kvdb::PREFIX_LEN as DB_PREFIX_LEN;
|
||||
|
||||
/// Represents index of extra data in database
|
||||
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
|
||||
pub enum ExtrasIndex {
|
||||
@@ -252,6 +252,7 @@ pub struct EpochTransitions {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rlp::*;
|
||||
|
||||
use super::BlockReceipts;
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1713,7 +1713,7 @@ impl BlockChainClient for Client {
|
||||
|
||||
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");
|
||||
trace!(target: "fatdb", "list_storage: Not a fat DB");
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::fmt::{Display, Formatter, Error as FmtError};
|
||||
use util_error::UtilError;
|
||||
use trie::TrieError;
|
||||
use ethtrie::TrieError;
|
||||
|
||||
/// Client configuration errors.
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -25,12 +25,13 @@ use {state, state_db, client, executive, trace, transaction, db, spec, pod_state
|
||||
use factory::Factories;
|
||||
use evm::{VMType, FinalizationResult};
|
||||
use vm::{self, ActionParams};
|
||||
use ethtrie;
|
||||
|
||||
/// EVM test Error.
|
||||
#[derive(Debug)]
|
||||
pub enum EvmTestError {
|
||||
/// Trie integrity error.
|
||||
Trie(trie::TrieError),
|
||||
Trie(Box<ethtrie::TrieError>),
|
||||
/// EVM error.
|
||||
Evm(vm::Error),
|
||||
/// Initialization error.
|
||||
|
||||
@@ -52,7 +52,6 @@ use miner::{self, Miner, MinerService};
|
||||
use spec::Spec;
|
||||
use types::basic_account::BasicAccount;
|
||||
use types::pruning_info::PruningInfo;
|
||||
|
||||
use verification::queue::QueueInfo;
|
||||
use block::{OpenBlock, SealedBlock, ClosedBlock};
|
||||
use executive::Executed;
|
||||
@@ -62,7 +61,7 @@ use state_db::StateDB;
|
||||
use header::Header;
|
||||
use encoded;
|
||||
use engines::EthEngine;
|
||||
use trie;
|
||||
use ethtrie;
|
||||
use state::StateInfo;
|
||||
use views::BlockView;
|
||||
|
||||
@@ -581,10 +580,10 @@ impl Call for TestBlockChainClient {
|
||||
}
|
||||
|
||||
impl StateInfo for () {
|
||||
fn nonce(&self, _address: &Address) -> trie::Result<U256> { unimplemented!() }
|
||||
fn balance(&self, _address: &Address) -> trie::Result<U256> { unimplemented!() }
|
||||
fn storage_at(&self, _address: &Address, _key: &H256) -> trie::Result<H256> { unimplemented!() }
|
||||
fn code(&self, _address: &Address) -> trie::Result<Option<Arc<Bytes>>> { unimplemented!() }
|
||||
fn nonce(&self, _address: &Address) -> ethtrie::Result<U256> { unimplemented!() }
|
||||
fn balance(&self, _address: &Address) -> ethtrie::Result<U256> { unimplemented!() }
|
||||
fn storage_at(&self, _address: &Address, _key: &H256) -> ethtrie::Result<H256> { unimplemented!() }
|
||||
fn code(&self, _address: &Address) -> ethtrie::Result<Option<Arc<Bytes>>> { unimplemented!() }
|
||||
}
|
||||
|
||||
impl StateClient for TestBlockChainClient {
|
||||
|
||||
@@ -34,12 +34,9 @@ use ethjson;
|
||||
use machine::{AuxiliaryData, Call, EthereumMachine};
|
||||
use hash::keccak;
|
||||
use header::{Header, BlockNumber, ExtendedHeader};
|
||||
|
||||
use super::signer::EngineSigner;
|
||||
use super::validator_set::{ValidatorSet, SimpleList, new_validator_set};
|
||||
|
||||
use self::finality::RollingFinality;
|
||||
|
||||
use ethkey::{self, Password, Signature};
|
||||
use io::{IoContext, IoHandler, TimerToken, IoService};
|
||||
use itertools::{self, Itertools};
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
|
||||
//! Tendermint message handling.
|
||||
|
||||
use std::cmp;
|
||||
use hash::keccak;
|
||||
use ethereum_types::{H256, H520, Address};
|
||||
use bytes::Bytes;
|
||||
use super::{Height, View, BlockHash, Step};
|
||||
use error::Error;
|
||||
use ethereum_types::{H256, H520, Address};
|
||||
use ethkey::{recover, public_to_address};
|
||||
use hash::keccak;
|
||||
use header::Header;
|
||||
use rlp::{Rlp, RlpStream, Encodable, Decodable, DecoderError};
|
||||
use ethkey::{recover, public_to_address};
|
||||
use std::cmp;
|
||||
use super::{Height, View, BlockHash, Step};
|
||||
use super::super::vote_collector::Message;
|
||||
|
||||
/// Message transmitted between consensus participants.
|
||||
|
||||
@@ -145,7 +145,7 @@ impl <F> super::EpochVerifier<EthereumMachine> for EpochVerifier<F>
|
||||
fn check_finality_proof(&self, proof: &[u8]) -> Option<Vec<H256>> {
|
||||
match ::rlp::decode(proof) {
|
||||
Ok(header) => self.verify_light(&header).ok().map(|_| vec![header.hash()]),
|
||||
Err(_) => None // REVIEW: log perhaps? Not sure what the policy is.
|
||||
Err(_) => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,27 +16,23 @@
|
||||
|
||||
/// Validator set maintained in a contract, updated using `getValidators` method.
|
||||
|
||||
use std::sync::{Weak, Arc};
|
||||
use hash::keccak;
|
||||
|
||||
use ethereum_types::{H256, U256, Address, Bloom};
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use bytes::Bytes;
|
||||
use memory_cache::MemoryLruCache;
|
||||
use unexpected::Mismatch;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use kvdb::DBValue;
|
||||
|
||||
use client::EngineClient;
|
||||
use machine::{AuxiliaryData, Call, EthereumMachine, AuxiliaryRequest};
|
||||
use ethereum_types::{H256, U256, Address, Bloom};
|
||||
use hash::keccak;
|
||||
use header::Header;
|
||||
use ids::BlockId;
|
||||
use kvdb::DBValue;
|
||||
use log_entry::LogEntry;
|
||||
use machine::{AuxiliaryData, Call, EthereumMachine, AuxiliaryRequest};
|
||||
use memory_cache::MemoryLruCache;
|
||||
use parking_lot::RwLock;
|
||||
use receipt::Receipt;
|
||||
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use std::sync::{Weak, Arc};
|
||||
use super::{SystemCall, ValidatorSet};
|
||||
use super::simple_list::SimpleList;
|
||||
use unexpected::Mismatch;
|
||||
|
||||
use_contract!(validator_set, "ValidatorSet", "res/contracts/validator_set.json");
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ use ethereum_types::{H256, U256, Address, Bloom};
|
||||
use util_error::{self, UtilError};
|
||||
use snappy::InvalidInput;
|
||||
use unexpected::{Mismatch, OutOfBounds};
|
||||
use trie::TrieError;
|
||||
use ethtrie::TrieError;
|
||||
use io::*;
|
||||
use header::BlockNumber;
|
||||
use client::Error as ClientError;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use ethereum_types::{U256, U512, Address};
|
||||
use bytes::Bytes;
|
||||
use trie;
|
||||
use ethtrie;
|
||||
use vm;
|
||||
use trace::{VMTrace, FlatTrace};
|
||||
use log_entry::LogEntry;
|
||||
@@ -117,9 +117,14 @@ pub enum ExecutionError {
|
||||
TransactionMalformed(String),
|
||||
}
|
||||
|
||||
impl From<Box<trie::TrieError>> for ExecutionError {
|
||||
fn from(err: Box<trie::TrieError>) -> Self {
|
||||
ExecutionError::Internal(format!("{}", err))
|
||||
impl From<Box<ethtrie::TrieError>> for ExecutionError {
|
||||
fn from(err: Box<ethtrie::TrieError>) -> Self {
|
||||
ExecutionError::Internal(format!("{:?}", err))
|
||||
}
|
||||
}
|
||||
impl From<ethtrie::TrieError> for ExecutionError {
|
||||
fn from(err: ethtrie::TrieError) -> Self {
|
||||
ExecutionError::Internal(format!("{:?}", err))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use trie::TrieFactory;
|
||||
use ethtrie::RlpCodec;
|
||||
use account_db::Factory as AccountFactory;
|
||||
use evm::{Factory as EvmFactory, VMType};
|
||||
use vm::{Vm, ActionParams, Schedule};
|
||||
use wasm::WasmInterpreter;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
|
||||
const WASM_MAGIC_NUMBER: &'static [u8; 4] = b"\0asm";
|
||||
|
||||
@@ -54,7 +56,7 @@ pub struct Factories {
|
||||
/// factory for evm.
|
||||
pub vm: VmFactory,
|
||||
/// factory for tries.
|
||||
pub trie: TrieFactory,
|
||||
pub trie: TrieFactory<KeccakHasher, RlpCodec>,
|
||||
/// factory for account databases.
|
||||
pub accountdb: AccountFactory,
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ use ethjson;
|
||||
use trace::{Tracer, NoopTracer};
|
||||
use trace::{VMTracer, NoopVMTracer};
|
||||
use bytes::{Bytes, BytesRef};
|
||||
use trie;
|
||||
use ethtrie;
|
||||
use rlp::RlpStream;
|
||||
use hash::keccak;
|
||||
use machine::EthereumMachine as Machine;
|
||||
@@ -93,7 +93,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
|
||||
address: Address,
|
||||
tracer: &'a mut T,
|
||||
vm_tracer: &'a mut V,
|
||||
) -> trie::Result<Self> {
|
||||
) -> ethtrie::Result<Self> {
|
||||
let static_call = false;
|
||||
Ok(TestExt {
|
||||
nonce: state.nonce(&address)?,
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
use ethjson;
|
||||
use trie::{TrieFactory, TrieSpec};
|
||||
use ethtrie::RlpCodec;
|
||||
use ethereum_types::H256;
|
||||
use memorydb::MemoryDB;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
|
||||
use super::HookType;
|
||||
|
||||
@@ -28,13 +30,13 @@ pub use self::secure::run_test_file as run_secure_test_file;
|
||||
|
||||
fn test_trie<H: FnMut(&str, HookType)>(json: &[u8], trie: TrieSpec, start_stop_hook: &mut H) -> Vec<String> {
|
||||
let tests = ethjson::trie::Test::load(json).unwrap();
|
||||
let factory = TrieFactory::new(trie);
|
||||
let factory = TrieFactory::<_, RlpCodec>::new(trie);
|
||||
let mut result = vec![];
|
||||
|
||||
for (name, test) in tests.into_iter() {
|
||||
start_stop_hook(&name, HookType::OnStart);
|
||||
|
||||
let mut memdb = MemoryDB::new();
|
||||
let mut memdb = MemoryDB::<KeccakHasher>::new();
|
||||
let mut root = H256::default();
|
||||
let mut t = factory.create(&mut memdb, &mut root);
|
||||
|
||||
|
||||
@@ -91,9 +91,11 @@ extern crate rayon;
|
||||
extern crate rlp;
|
||||
extern crate rlp_compress;
|
||||
extern crate keccak_hash as hash;
|
||||
extern crate keccak_hasher;
|
||||
extern crate heapsize;
|
||||
extern crate memorydb;
|
||||
extern crate patricia_trie as trie;
|
||||
extern crate patricia_trie_ethereum as ethtrie;
|
||||
extern crate triehash;
|
||||
extern crate ansi_term;
|
||||
extern crate unexpected;
|
||||
|
||||
@@ -20,9 +20,11 @@ use itertools::Itertools;
|
||||
use hash::{keccak};
|
||||
use ethereum_types::{H256, U256};
|
||||
use hashdb::HashDB;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use triehash::sec_trie_root;
|
||||
use bytes::Bytes;
|
||||
use trie::TrieFactory;
|
||||
use ethtrie::RlpCodec;
|
||||
use state::Account;
|
||||
use ethjson;
|
||||
use types::account_diff::*;
|
||||
@@ -65,7 +67,7 @@ impl PodAccount {
|
||||
}
|
||||
|
||||
/// Place additional data into given hash DB.
|
||||
pub fn insert_additional(&self, db: &mut HashDB, factory: &TrieFactory) {
|
||||
pub fn insert_additional(&self, db: &mut HashDB<KeccakHasher>, factory: &TrieFactory<KeccakHasher, RlpCodec>) {
|
||||
match self.code {
|
||||
Some(ref c) if !c.is_empty() => { db.insert(c); }
|
||||
_ => {}
|
||||
|
||||
@@ -18,16 +18,15 @@
|
||||
|
||||
use account_db::{AccountDB, AccountDBMut};
|
||||
use basic_account::BasicAccount;
|
||||
use snapshot::Error;
|
||||
use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP};
|
||||
|
||||
use ethereum_types::{H256, U256};
|
||||
use hashdb::HashDB;
|
||||
use bytes::Bytes;
|
||||
use trie::{TrieDB, Trie};
|
||||
use ethereum_types::{H256, U256};
|
||||
use ethtrie::{TrieDB, TrieDBMut};
|
||||
use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP};
|
||||
use hashdb::HashDB;
|
||||
use rlp::{RlpStream, Rlp};
|
||||
|
||||
use snapshot::Error;
|
||||
use std::collections::HashSet;
|
||||
use trie::{Trie, TrieMut};
|
||||
|
||||
// An empty account -- these were replaced with RLP null data for a space optimization in v1.
|
||||
const ACC_EMPTY: BasicAccount = BasicAccount {
|
||||
@@ -151,7 +150,6 @@ pub fn from_fat_rlp(
|
||||
rlp: Rlp,
|
||||
mut storage_root: H256,
|
||||
) -> Result<(BasicAccount, Option<Bytes>), Error> {
|
||||
use trie::{TrieDBMut, TrieMut};
|
||||
|
||||
// check for special case of empty account.
|
||||
if rlp.is_empty() {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
use block::Block;
|
||||
use header::Header;
|
||||
use hash::keccak;
|
||||
|
||||
use views::BlockView;
|
||||
use rlp::{DecoderError, RlpStream, Rlp};
|
||||
use ethereum_types::H256;
|
||||
|
||||
@@ -38,6 +38,7 @@ use ethereum_types::{H256, U256};
|
||||
use kvdb::KeyValueDB;
|
||||
use bytes::Bytes;
|
||||
|
||||
|
||||
/// Snapshot creation and restoration for PoA chains.
|
||||
/// Chunk format:
|
||||
///
|
||||
|
||||
@@ -21,7 +21,7 @@ use std::fmt;
|
||||
use ids::BlockId;
|
||||
|
||||
use ethereum_types::H256;
|
||||
use trie::TrieError;
|
||||
use ethtrie::TrieError;
|
||||
use rlp::DecoderError;
|
||||
|
||||
/// Snapshot-related errors.
|
||||
|
||||
@@ -32,13 +32,15 @@ use ids::BlockId;
|
||||
|
||||
use ethereum_types::{H256, U256};
|
||||
use hashdb::HashDB;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use kvdb::DBValue;
|
||||
use snappy;
|
||||
use bytes::Bytes;
|
||||
use parking_lot::Mutex;
|
||||
use journaldb::{self, Algorithm, JournalDB};
|
||||
use kvdb::KeyValueDB;
|
||||
use trie::{TrieDB, TrieDBMut, Trie, TrieMut};
|
||||
use trie::{Trie, TrieMut};
|
||||
use ethtrie::{TrieDB, TrieDBMut};
|
||||
use rlp::{RlpStream, Rlp};
|
||||
use bloom_journal::Bloom;
|
||||
|
||||
@@ -126,7 +128,7 @@ pub fn take_snapshot<W: SnapshotWriter + Send>(
|
||||
engine: &EthEngine,
|
||||
chain: &BlockChain,
|
||||
block_at: H256,
|
||||
state_db: &HashDB,
|
||||
state_db: &HashDB<KeccakHasher>,
|
||||
writer: W,
|
||||
p: &Progress
|
||||
) -> Result<(), Error> {
|
||||
@@ -264,7 +266,7 @@ impl<'a> StateChunker<'a> {
|
||||
///
|
||||
/// Returns a list of hashes of chunks created, or any error it may
|
||||
/// have encountered.
|
||||
pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex<SnapshotWriter + 'a>, progress: &'a Progress) -> Result<Vec<H256>, Error> {
|
||||
pub fn chunk_state<'a>(db: &HashDB<KeccakHasher>, root: &H256, writer: &Mutex<SnapshotWriter + 'a>, progress: &'a Progress) -> Result<Vec<H256>, Error> {
|
||||
let account_trie = TrieDB::new(db, &root)?;
|
||||
|
||||
let mut chunker = StateChunker {
|
||||
@@ -414,7 +416,7 @@ struct RebuiltStatus {
|
||||
// rebuild a set of accounts and their storage.
|
||||
// returns a status detailing newly-loaded code and accounts missing code.
|
||||
fn rebuild_accounts(
|
||||
db: &mut HashDB,
|
||||
db: &mut HashDB<KeccakHasher>,
|
||||
account_fat_rlps: Rlp,
|
||||
out_chunk: &mut [(H256, Bytes)],
|
||||
known_code: &HashMap<H256, H256>,
|
||||
|
||||
@@ -36,8 +36,10 @@ use rand::Rng;
|
||||
use kvdb::DBValue;
|
||||
use ethereum_types::H256;
|
||||
use hashdb::HashDB;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use journaldb;
|
||||
use trie::{SecTrieDBMut, TrieMut, TrieDB, TrieDBMut, Trie};
|
||||
use trie::{TrieMut, Trie};
|
||||
use ethtrie::{SecTrieDBMut, TrieDB, TrieDBMut};
|
||||
use self::trie_standardmap::{Alphabet, StandardMap, ValueMode};
|
||||
|
||||
// the proportion of accounts we will alter each tick.
|
||||
@@ -60,7 +62,7 @@ impl StateProducer {
|
||||
|
||||
/// Tick the state producer. This alters the state, writing new data into
|
||||
/// the database.
|
||||
pub fn tick<R: Rng>(&mut self, rng: &mut R, db: &mut HashDB) {
|
||||
pub fn tick<R: Rng>(&mut self, rng: &mut R, db: &mut HashDB<KeccakHasher>) {
|
||||
// modify existing accounts.
|
||||
let mut accounts_to_modify: Vec<_> = {
|
||||
let trie = TrieDB::new(&*db, &self.state_root).unwrap();
|
||||
@@ -129,7 +131,7 @@ pub fn fill_storage(mut db: AccountDBMut, root: &mut H256, seed: &mut H256) {
|
||||
}
|
||||
|
||||
/// Compare two state dbs.
|
||||
pub fn compare_dbs(one: &HashDB, two: &HashDB) {
|
||||
pub fn compare_dbs(one: &HashDB<KeccakHasher>, two: &HashDB<KeccakHasher>) {
|
||||
let keys = one.keys();
|
||||
|
||||
for key in keys.keys() {
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -16,22 +16,23 @@
|
||||
|
||||
//! State database abstraction. For more info, see the doc for `StateDB`
|
||||
|
||||
use std::collections::{VecDeque, HashSet};
|
||||
use std::sync::Arc;
|
||||
use lru_cache::LruCache;
|
||||
use memory_cache::MemoryLruCache;
|
||||
use bloom_journal::{Bloom, BloomJournal};
|
||||
use byteorder::{LittleEndian, ByteOrder};
|
||||
use db::COL_ACCOUNT_BLOOM;
|
||||
use ethereum_types::{H256, Address};
|
||||
use hash::keccak;
|
||||
use hashdb::HashDB;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use header::BlockNumber;
|
||||
use journaldb::JournalDB;
|
||||
use kvdb::{KeyValueDB, DBTransaction};
|
||||
use ethereum_types::{H256, Address};
|
||||
use hashdb::HashDB;
|
||||
use state::{self, Account};
|
||||
use header::BlockNumber;
|
||||
use hash::keccak;
|
||||
use lru_cache::LruCache;
|
||||
use memory_cache::MemoryLruCache;
|
||||
use parking_lot::Mutex;
|
||||
use state::{self, Account};
|
||||
use std::collections::{VecDeque, HashSet};
|
||||
use std::sync::Arc;
|
||||
use util_error::UtilError;
|
||||
use bloom_journal::{Bloom, BloomJournal};
|
||||
use db::COL_ACCOUNT_BLOOM;
|
||||
use byteorder::{LittleEndian, ByteOrder};
|
||||
|
||||
/// Value used to initialize bloom bitmap size.
|
||||
///
|
||||
@@ -310,12 +311,12 @@ impl StateDB {
|
||||
}
|
||||
|
||||
/// Conversion method to interpret self as `HashDB` reference
|
||||
pub fn as_hashdb(&self) -> &HashDB {
|
||||
pub fn as_hashdb(&self) -> &HashDB<KeccakHasher> {
|
||||
self.db.as_hashdb()
|
||||
}
|
||||
|
||||
/// Conversion method to interpret self as mutable `HashDB` reference
|
||||
pub fn as_hashdb_mut(&mut self) -> &mut HashDB {
|
||||
pub fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> {
|
||||
self.db.as_hashdb_mut()
|
||||
}
|
||||
|
||||
@@ -410,11 +411,9 @@ impl StateDB {
|
||||
}
|
||||
|
||||
impl state::Backend for StateDB {
|
||||
fn as_hashdb(&self) -> &HashDB {
|
||||
self.db.as_hashdb()
|
||||
}
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self.db.as_hashdb() }
|
||||
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB {
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> {
|
||||
self.db.as_hashdb_mut()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user