reth_rpc_eth_types/cache/
db.rs

1//! Helper types to workaround 'higher-ranked lifetime error'
2//! <https://github.com/rust-lang/rust/issues/100013> in default implementation of
3//! `reth_rpc_eth_api::helpers::Call`.
4
5use alloy_primitives::{Address, B256, U256};
6use reth_errors::ProviderResult;
7use reth_revm::{database::StateProviderDatabase, DatabaseRef};
8use reth_storage_api::{BytecodeReader, HashedPostStateProvider, StateProvider};
9use reth_trie::{HashedStorage, MultiProofTargets};
10use revm::{
11    database::{BundleState, CacheDB},
12    primitives::HashMap,
13    state::{AccountInfo, Bytecode},
14    Database, DatabaseCommit,
15};
16
17/// Helper alias type for the state's [`CacheDB`]
18pub type StateCacheDb<'a> = CacheDB<StateProviderDatabase<StateProviderTraitObjWrapper<'a>>>;
19
20/// Hack to get around 'higher-ranked lifetime error', see
21/// <https://github.com/rust-lang/rust/issues/100013>
22#[expect(missing_debug_implementations)]
23pub struct StateProviderTraitObjWrapper<'a>(pub &'a dyn StateProvider);
24
25impl reth_storage_api::StateRootProvider for StateProviderTraitObjWrapper<'_> {
26    fn state_root(
27        &self,
28        hashed_state: reth_trie::HashedPostState,
29    ) -> reth_errors::ProviderResult<B256> {
30        self.0.state_root(hashed_state)
31    }
32
33    fn state_root_from_nodes(
34        &self,
35        input: reth_trie::TrieInput,
36    ) -> reth_errors::ProviderResult<B256> {
37        self.0.state_root_from_nodes(input)
38    }
39
40    fn state_root_with_updates(
41        &self,
42        hashed_state: reth_trie::HashedPostState,
43    ) -> reth_errors::ProviderResult<(B256, reth_trie::updates::TrieUpdates)> {
44        self.0.state_root_with_updates(hashed_state)
45    }
46
47    fn state_root_from_nodes_with_updates(
48        &self,
49        input: reth_trie::TrieInput,
50    ) -> reth_errors::ProviderResult<(B256, reth_trie::updates::TrieUpdates)> {
51        self.0.state_root_from_nodes_with_updates(input)
52    }
53}
54
55impl reth_storage_api::StorageRootProvider for StateProviderTraitObjWrapper<'_> {
56    fn storage_root(
57        &self,
58        address: Address,
59        hashed_storage: HashedStorage,
60    ) -> ProviderResult<B256> {
61        self.0.storage_root(address, hashed_storage)
62    }
63
64    fn storage_proof(
65        &self,
66        address: Address,
67        slot: B256,
68        hashed_storage: HashedStorage,
69    ) -> ProviderResult<reth_trie::StorageProof> {
70        self.0.storage_proof(address, slot, hashed_storage)
71    }
72
73    fn storage_multiproof(
74        &self,
75        address: Address,
76        slots: &[B256],
77        hashed_storage: HashedStorage,
78    ) -> ProviderResult<reth_trie::StorageMultiProof> {
79        self.0.storage_multiproof(address, slots, hashed_storage)
80    }
81}
82
83impl reth_storage_api::StateProofProvider for StateProviderTraitObjWrapper<'_> {
84    fn proof(
85        &self,
86        input: reth_trie::TrieInput,
87        address: Address,
88        slots: &[B256],
89    ) -> reth_errors::ProviderResult<reth_trie::AccountProof> {
90        self.0.proof(input, address, slots)
91    }
92
93    fn multiproof(
94        &self,
95        input: reth_trie::TrieInput,
96        targets: MultiProofTargets,
97    ) -> ProviderResult<reth_trie::MultiProof> {
98        self.0.multiproof(input, targets)
99    }
100
101    fn witness(
102        &self,
103        input: reth_trie::TrieInput,
104        target: reth_trie::HashedPostState,
105    ) -> reth_errors::ProviderResult<Vec<alloy_primitives::Bytes>> {
106        self.0.witness(input, target)
107    }
108}
109
110impl reth_storage_api::AccountReader for StateProviderTraitObjWrapper<'_> {
111    fn basic_account(
112        &self,
113        address: &Address,
114    ) -> reth_errors::ProviderResult<Option<reth_primitives_traits::Account>> {
115        self.0.basic_account(address)
116    }
117}
118
119impl reth_storage_api::BlockHashReader for StateProviderTraitObjWrapper<'_> {
120    fn block_hash(
121        &self,
122        block_number: alloy_primitives::BlockNumber,
123    ) -> reth_errors::ProviderResult<Option<B256>> {
124        self.0.block_hash(block_number)
125    }
126
127    fn convert_block_hash(
128        &self,
129        hash_or_number: alloy_rpc_types_eth::BlockHashOrNumber,
130    ) -> reth_errors::ProviderResult<Option<B256>> {
131        self.0.convert_block_hash(hash_or_number)
132    }
133
134    fn canonical_hashes_range(
135        &self,
136        start: alloy_primitives::BlockNumber,
137        end: alloy_primitives::BlockNumber,
138    ) -> reth_errors::ProviderResult<Vec<B256>> {
139        self.0.canonical_hashes_range(start, end)
140    }
141}
142
143impl HashedPostStateProvider for StateProviderTraitObjWrapper<'_> {
144    fn hashed_post_state(&self, bundle_state: &BundleState) -> reth_trie::HashedPostState {
145        self.0.hashed_post_state(bundle_state)
146    }
147}
148
149impl StateProvider for StateProviderTraitObjWrapper<'_> {
150    fn storage(
151        &self,
152        account: Address,
153        storage_key: alloy_primitives::StorageKey,
154    ) -> reth_errors::ProviderResult<Option<alloy_primitives::StorageValue>> {
155        self.0.storage(account, storage_key)
156    }
157
158    fn account_code(
159        &self,
160        addr: &Address,
161    ) -> reth_errors::ProviderResult<Option<reth_primitives_traits::Bytecode>> {
162        self.0.account_code(addr)
163    }
164
165    fn account_balance(&self, addr: &Address) -> reth_errors::ProviderResult<Option<U256>> {
166        self.0.account_balance(addr)
167    }
168
169    fn account_nonce(&self, addr: &Address) -> reth_errors::ProviderResult<Option<u64>> {
170        self.0.account_nonce(addr)
171    }
172}
173
174impl BytecodeReader for StateProviderTraitObjWrapper<'_> {
175    fn bytecode_by_hash(
176        &self,
177        code_hash: &B256,
178    ) -> reth_errors::ProviderResult<Option<reth_primitives_traits::Bytecode>> {
179        self.0.bytecode_by_hash(code_hash)
180    }
181}
182
183/// Hack to get around 'higher-ranked lifetime error', see
184/// <https://github.com/rust-lang/rust/issues/100013>
185pub struct StateCacheDbRefMutWrapper<'a, 'b>(pub &'b mut StateCacheDb<'a>);
186
187impl<'a, 'b> core::fmt::Debug for StateCacheDbRefMutWrapper<'a, 'b> {
188    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
189        f.debug_struct("StateCacheDbRefMutWrapper").finish_non_exhaustive()
190    }
191}
192
193impl<'a> Database for StateCacheDbRefMutWrapper<'a, '_> {
194    type Error = <StateCacheDb<'a> as Database>::Error;
195    fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
196        self.0.basic(address)
197    }
198
199    fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
200        self.0.code_by_hash(code_hash)
201    }
202
203    fn storage(&mut self, address: Address, index: U256) -> Result<U256, Self::Error> {
204        self.0.storage(address, index)
205    }
206
207    fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
208        self.0.block_hash(number)
209    }
210}
211
212impl<'a> DatabaseRef for StateCacheDbRefMutWrapper<'a, '_> {
213    type Error = <StateCacheDb<'a> as Database>::Error;
214
215    fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
216        self.0.basic_ref(address)
217    }
218
219    fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
220        self.0.code_by_hash_ref(code_hash)
221    }
222
223    fn storage_ref(&self, address: Address, index: U256) -> Result<U256, Self::Error> {
224        self.0.storage_ref(address, index)
225    }
226
227    fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
228        self.0.block_hash_ref(number)
229    }
230}
231
232impl DatabaseCommit for StateCacheDbRefMutWrapper<'_, '_> {
233    fn commit(&mut self, changes: HashMap<Address, revm::state::Account>) {
234        self.0.commit(changes)
235    }
236}