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