use crate::primitives::alloy_primitives::{BlockNumber, StorageKey, StorageValue}; use core::ops::{Deref, DerefMut}; use reth_primitives::{Account, Address, B256, U256}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use revm::{ db::DatabaseRef, primitives::{AccountInfo, Bytecode}, Database, }; /// A helper trait responsible for providing that necessary state for the EVM execution. /// /// This servers as the data layer for [Database]. pub trait EvmStateProvider: Send + Sync { /// Get basic account information. /// /// Returns `None` if the account doesn't exist. fn basic_account(&self, address: Address) -> ProviderResult>; /// Get the hash of the block with the given number. Returns `None` if no block with this number /// exists. fn block_hash(&self, number: BlockNumber) -> ProviderResult>; /// Get account code by its hash fn bytecode_by_hash( &self, code_hash: B256, ) -> ProviderResult>; /// Get storage of given account. fn storage( &self, account: Address, storage_key: StorageKey, ) -> ProviderResult>; } // Blanket implementation of EvmStateProvider for any type that implements StateProvider. impl EvmStateProvider for T { fn basic_account(&self, address: Address) -> ProviderResult> { ::basic_account(self, address) } fn block_hash(&self, number: BlockNumber) -> ProviderResult> { ::block_hash(self, number) } fn bytecode_by_hash( &self, code_hash: B256, ) -> ProviderResult> { ::bytecode_by_hash(self, code_hash) } fn storage( &self, account: Address, storage_key: StorageKey, ) -> ProviderResult> { ::storage(self, account, storage_key) } } /// A [Database] and [`DatabaseRef`] implementation that uses [`EvmStateProvider`] as the underlying /// data source. #[derive(Debug, Clone)] pub struct StateProviderDatabase(pub DB); impl StateProviderDatabase { /// Create new State with generic `StateProvider`. pub const fn new(db: DB) -> Self { Self(db) } /// Consume State and return inner `StateProvider`. pub fn into_inner(self) -> DB { self.0 } } impl Deref for StateProviderDatabase { type Target = DB; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for StateProviderDatabase { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl Database for StateProviderDatabase { type Error = ProviderError; /// Retrieves basic account information for a given address. /// /// Returns `Ok` with `Some(AccountInfo)` if the account exists, /// `None` if it doesn't, or an error if encountered. fn basic(&mut self, address: Address) -> Result, Self::Error> { DatabaseRef::basic_ref(self, address) } /// Retrieves the bytecode associated with a given code hash. /// /// Returns `Ok` with the bytecode if found, or the default bytecode otherwise. fn code_by_hash(&mut self, code_hash: B256) -> Result { DatabaseRef::code_by_hash_ref(self, code_hash) } /// Retrieves the storage value at a specific index for a given address. /// /// Returns `Ok` with the storage value, or the default value if not found. fn storage(&mut self, address: Address, index: U256) -> Result { DatabaseRef::storage_ref(self, address, index) } /// Retrieves the block hash for a given block number. /// /// Returns `Ok` with the block hash if found, or the default hash otherwise. /// Note: It safely casts the `number` to `u64`. fn block_hash(&mut self, number: u64) -> Result { DatabaseRef::block_hash_ref(self, number) } } impl DatabaseRef for StateProviderDatabase { type Error = ::Error; /// Retrieves basic account information for a given address. /// /// Returns `Ok` with `Some(AccountInfo)` if the account exists, /// `None` if it doesn't, or an error if encountered. fn basic_ref(&self, address: Address) -> Result, Self::Error> { Ok(self.basic_account(address)?.map(Into::into)) } /// Retrieves the bytecode associated with a given code hash. /// /// Returns `Ok` with the bytecode if found, or the default bytecode otherwise. fn code_by_hash_ref(&self, code_hash: B256) -> Result { Ok(self.bytecode_by_hash(code_hash)?.unwrap_or_default().0) } /// Retrieves the storage value at a specific index for a given address. /// /// Returns `Ok` with the storage value, or the default value if not found. fn storage_ref(&self, address: Address, index: U256) -> Result { Ok(self.0.storage(address, B256::new(index.to_be_bytes()))?.unwrap_or_default()) } /// Retrieves the block hash for a given block number. /// /// Returns `Ok` with the block hash if found, or the default hash otherwise. fn block_hash_ref(&self, number: u64) -> Result { // Get the block hash or default hash with an attempt to convert U256 block number to u64 Ok(self.0.block_hash(number)?.unwrap_or_default()) } }