reth_revm/
database.rs

1use crate::primitives::alloy_primitives::{BlockNumber, StorageKey};
2use alloy_primitives::{Address, B256, U256};
3use core::ops::{Deref, DerefMut};
4use reth_primitives::Account;
5use reth_storage_errors::provider::{ProviderError, ProviderResult};
6use revm::{
7    db::DatabaseRef,
8    primitives::{AccountInfo, Bytecode, FlaggedStorage},
9    Database,
10};
11
12/// A helper trait responsible for providing state necessary for EVM execution.
13///
14/// This serves as the data layer for [`Database`].
15pub trait EvmStateProvider: Send + Sync {
16    /// Get basic account information.
17    ///
18    /// Returns [`None`] if the account doesn't exist.
19    fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>>;
20
21    /// Get the hash of the block with the given number. Returns [`None`] if no block with this
22    /// number exists.
23    fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>>;
24
25    /// Get account code by hash.
26    fn bytecode_by_hash(
27        &self,
28        code_hash: B256,
29    ) -> ProviderResult<Option<reth_primitives::Bytecode>>;
30
31    /// Get storage of the given account.
32    fn storage(
33        &self,
34        account: Address,
35        storage_key: StorageKey,
36    ) -> ProviderResult<Option<FlaggedStorage>>;
37}
38
39// Blanket implementation of EvmStateProvider for any type that implements StateProvider.
40impl<T: reth_storage_api::StateProvider> EvmStateProvider for T {
41    fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
42        <T as reth_storage_api::AccountReader>::basic_account(self, address)
43    }
44
45    fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>> {
46        <T as reth_storage_api::BlockHashReader>::block_hash(self, number)
47    }
48
49    fn bytecode_by_hash(
50        &self,
51        code_hash: B256,
52    ) -> ProviderResult<Option<reth_primitives::Bytecode>> {
53        <T as reth_storage_api::StateProvider>::bytecode_by_hash(self, code_hash)
54    }
55
56    fn storage(
57        &self,
58        account: Address,
59        storage_key: StorageKey,
60    ) -> ProviderResult<Option<FlaggedStorage>> {
61        <T as reth_storage_api::StateProvider>::storage(self, account, storage_key)
62    }
63}
64
65/// A [Database] and [`DatabaseRef`] implementation that uses [`EvmStateProvider`] as the underlying
66/// data source.
67#[derive(Debug, Clone)]
68pub struct StateProviderDatabase<DB>(pub DB);
69
70impl<DB> StateProviderDatabase<DB> {
71    /// Create new State with generic `StateProvider`.
72    pub const fn new(db: DB) -> Self {
73        Self(db)
74    }
75
76    /// Consume State and return inner `StateProvider`.
77    pub fn into_inner(self) -> DB {
78        self.0
79    }
80}
81
82impl<DB> AsRef<DB> for StateProviderDatabase<DB> {
83    fn as_ref(&self) -> &DB {
84        self
85    }
86}
87
88impl<DB> Deref for StateProviderDatabase<DB> {
89    type Target = DB;
90
91    fn deref(&self) -> &Self::Target {
92        &self.0
93    }
94}
95
96impl<DB> DerefMut for StateProviderDatabase<DB> {
97    fn deref_mut(&mut self) -> &mut Self::Target {
98        &mut self.0
99    }
100}
101
102impl<DB: EvmStateProvider> Database for StateProviderDatabase<DB> {
103    type Error = ProviderError;
104
105    /// Retrieves basic account information for a given address.
106    ///
107    /// Returns `Ok` with `Some(AccountInfo)` if the account exists,
108    /// `None` if it doesn't, or an error if encountered.
109    fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
110        self.basic_ref(address)
111    }
112
113    /// Retrieves the bytecode associated with a given code hash.
114    ///
115    /// Returns `Ok` with the bytecode if found, or the default bytecode otherwise.
116    fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
117        self.code_by_hash_ref(code_hash)
118    }
119
120    /// Retrieves the storage value at a specific index for a given address.
121    ///
122    /// Returns `Ok` with the storage value, or the default value if not found.
123    fn storage(&mut self, address: Address, index: U256) -> Result<FlaggedStorage, Self::Error> {
124        self.storage_ref(address, index)
125    }
126
127    /// Retrieves the block hash for a given block number.
128    ///
129    /// Returns `Ok` with the block hash if found, or the default hash otherwise.
130    /// Note: It safely casts the `number` to `u64`.
131    fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
132        self.block_hash_ref(number)
133    }
134}
135
136impl<DB: EvmStateProvider> DatabaseRef for StateProviderDatabase<DB> {
137    type Error = <Self as Database>::Error;
138
139    /// Retrieves basic account information for a given address.
140    ///
141    /// Returns `Ok` with `Some(AccountInfo)` if the account exists,
142    /// `None` if it doesn't, or an error if encountered.
143    fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
144        Ok(self.basic_account(address)?.map(Into::into))
145    }
146
147    /// Retrieves the bytecode associated with a given code hash.
148    ///
149    /// Returns `Ok` with the bytecode if found, or the default bytecode otherwise.
150    fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
151        Ok(self.bytecode_by_hash(code_hash)?.unwrap_or_default().0)
152    }
153
154    /// Retrieves the storage value at a specific index for a given address.
155    ///
156    /// Returns `Ok` with the storage value, or the default value if not found.
157    fn storage_ref(&self, address: Address, index: U256) -> Result<FlaggedStorage, Self::Error> {
158        Ok(self.0.storage(address, B256::new(index.to_be_bytes()))?.unwrap_or_default())
159    }
160
161    /// Retrieves the block hash for a given block number.
162    ///
163    /// Returns `Ok` with the block hash if found, or the default hash otherwise.
164    fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
165        // Get the block hash or default hash with an attempt to convert U256 block number to u64
166        Ok(self.0.block_hash(number)?.unwrap_or_default())
167    }
168}