Skip to main content

ethrex_vm/
db.rs

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