1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use crate::EvmError;
use dyn_clone::DynClone;
use ethrex_common::{
Address, H256, U256,
types::{AccountState, ChainConfig, Code, CodeMetadata},
};
pub trait VmDatabase: Send + Sync + DynClone {
fn get_account_state(&self, address: Address) -> Result<Option<AccountState>, EvmError>;
fn get_storage_slot(&self, address: Address, key: H256) -> Result<Option<U256>, EvmError>;
fn get_block_hash(&self, block_number: u64) -> Result<H256, EvmError>;
fn get_chain_config(&self) -> Result<ChainConfig, EvmError>;
fn get_account_code(&self, code_hash: H256) -> Result<Code, EvmError>;
fn get_code_metadata(&self, code_hash: H256) -> Result<CodeMetadata, EvmError>;
/// Capacity of this backend's bytecode cache, in [`Code::size`] bytes, which bounds
/// how much bytecode a block warm reads speculatively. Default is the floor for a
/// backend holding no such cache.
fn code_cache_budget_bytes(&self) -> u64 {
64 * 1024 * 1024
}
/// Batch account-state lookup. Default impl loops `get_account_state`.
/// Backends that can amortize per-key cost (e.g. rocksdb `multi_get_cf` on
/// the flat key-value table) should override this.
fn get_account_states_batch(
&self,
addresses: &[Address],
) -> Result<Vec<Option<AccountState>>, EvmError> {
addresses
.iter()
.map(|a| self.get_account_state(*a))
.collect()
}
/// Batch bytecode lookup, aligned to `code_hashes`. `None` means the hash is absent
/// from the database, which callers warming a cache treat as nothing to warm rather
/// than as failure. Default impl loops `get_account_code`; backends that can amortize
/// per-key cost (e.g. rocksdb `multi_get_cf` on the account-codes table) override it.
fn get_account_codes_batch(&self, code_hashes: &[H256]) -> Result<Vec<Option<Code>>, EvmError> {
code_hashes
.iter()
.map(|h| self.get_account_code(*h).map(Some))
.collect()
}
/// Batch storage-slot lookup. Default impl loops `get_storage_slot`.
/// Backends that can amortize per-key cost (e.g. rocksdb `multi_get_cf` on
/// the flat key-value table) should override this.
fn get_storage_slots_batch(
&self,
keys: &[(Address, H256)],
) -> Result<Vec<Option<U256>>, EvmError> {
keys.iter()
.map(|&(addr, key)| self.get_storage_slot(addr, key))
.collect()
}
}
dyn_clone::clone_trait_object!(VmDatabase);
pub type DynVmDatabase = Box<dyn VmDatabase + Send + Sync + 'static>;