reth_provider/providers/state/
latest.rs
1use crate::{
2 providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader,
3 HashedPostStateProvider, StateProvider, StateRootProvider,
4};
5use alloy_primitives::{Address, BlockNumber, Bytes, StorageKey, StorageValue, B256};
6use reth_db_api::{cursor::DbDupCursorRO, tables, transaction::DbTx};
7use reth_primitives_traits::{Account, Bytecode};
8use reth_storage_api::{
9 DBProvider, StateCommitmentProvider, StateProofProvider, StorageRootProvider,
10};
11use reth_storage_errors::provider::{ProviderError, ProviderResult};
12use reth_trie::{
13 proof::{Proof, StorageProof},
14 updates::TrieUpdates,
15 witness::TrieWitness,
16 AccountProof, HashedPostState, HashedStorage, MultiProof, MultiProofTargets, StateRoot,
17 StorageMultiProof, StorageRoot, TrieInput,
18};
19use reth_trie_db::{
20 DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot,
21 DatabaseTrieWitness, StateCommitment,
22};
23
24#[derive(Debug)]
28pub struct LatestStateProviderRef<'b, Provider>(&'b Provider);
29
30impl<'b, Provider: DBProvider> LatestStateProviderRef<'b, Provider> {
31 pub const fn new(provider: &'b Provider) -> Self {
33 Self(provider)
34 }
35
36 fn tx(&self) -> &Provider::Tx {
37 self.0.tx_ref()
38 }
39}
40
41impl<Provider: DBProvider> AccountReader for LatestStateProviderRef<'_, Provider> {
42 fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
44 self.tx().get_by_encoded_key::<tables::PlainAccountState>(address).map_err(Into::into)
45 }
46}
47
48impl<Provider: BlockHashReader> BlockHashReader for LatestStateProviderRef<'_, Provider> {
49 fn block_hash(&self, number: u64) -> ProviderResult<Option<B256>> {
51 self.0.block_hash(number)
52 }
53
54 fn canonical_hashes_range(
55 &self,
56 start: BlockNumber,
57 end: BlockNumber,
58 ) -> ProviderResult<Vec<B256>> {
59 self.0.canonical_hashes_range(start, end)
60 }
61}
62
63impl<Provider: DBProvider + StateCommitmentProvider> StateRootProvider
64 for LatestStateProviderRef<'_, Provider>
65{
66 fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult<B256> {
67 StateRoot::overlay_root(self.tx(), hashed_state)
68 .map_err(|err| ProviderError::Database(err.into()))
69 }
70
71 fn state_root_from_nodes(&self, input: TrieInput) -> ProviderResult<B256> {
72 StateRoot::overlay_root_from_nodes(self.tx(), input)
73 .map_err(|err| ProviderError::Database(err.into()))
74 }
75
76 fn state_root_with_updates(
77 &self,
78 hashed_state: HashedPostState,
79 ) -> ProviderResult<(B256, TrieUpdates)> {
80 StateRoot::overlay_root_with_updates(self.tx(), hashed_state)
81 .map_err(|err| ProviderError::Database(err.into()))
82 }
83
84 fn state_root_from_nodes_with_updates(
85 &self,
86 input: TrieInput,
87 ) -> ProviderResult<(B256, TrieUpdates)> {
88 StateRoot::overlay_root_from_nodes_with_updates(self.tx(), input)
89 .map_err(|err| ProviderError::Database(err.into()))
90 }
91}
92
93impl<Provider: DBProvider + StateCommitmentProvider> StorageRootProvider
94 for LatestStateProviderRef<'_, Provider>
95{
96 fn storage_root(
97 &self,
98 address: Address,
99 hashed_storage: HashedStorage,
100 ) -> ProviderResult<B256> {
101 StorageRoot::overlay_root(self.tx(), address, hashed_storage)
102 .map_err(|err| ProviderError::Database(err.into()))
103 }
104
105 fn storage_proof(
106 &self,
107 address: Address,
108 slot: B256,
109 hashed_storage: HashedStorage,
110 ) -> ProviderResult<reth_trie::StorageProof> {
111 StorageProof::overlay_storage_proof(self.tx(), address, slot, hashed_storage)
112 .map_err(ProviderError::from)
113 }
114
115 fn storage_multiproof(
116 &self,
117 address: Address,
118 slots: &[B256],
119 hashed_storage: HashedStorage,
120 ) -> ProviderResult<StorageMultiProof> {
121 StorageProof::overlay_storage_multiproof(self.tx(), address, slots, hashed_storage)
122 .map_err(ProviderError::from)
123 }
124}
125
126impl<Provider: DBProvider + StateCommitmentProvider> StateProofProvider
127 for LatestStateProviderRef<'_, Provider>
128{
129 fn proof(
130 &self,
131 input: TrieInput,
132 address: Address,
133 slots: &[B256],
134 ) -> ProviderResult<AccountProof> {
135 Proof::overlay_account_proof(self.tx(), input, address, slots).map_err(ProviderError::from)
136 }
137
138 fn multiproof(
139 &self,
140 input: TrieInput,
141 targets: MultiProofTargets,
142 ) -> ProviderResult<MultiProof> {
143 Proof::overlay_multiproof(self.tx(), input, targets).map_err(ProviderError::from)
144 }
145
146 fn witness(&self, input: TrieInput, target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
147 TrieWitness::overlay_witness(self.tx(), input, target)
148 .map_err(ProviderError::from)
149 .map(|hm| hm.into_values().collect())
150 }
151}
152
153impl<Provider: DBProvider + StateCommitmentProvider> HashedPostStateProvider
154 for LatestStateProviderRef<'_, Provider>
155{
156 fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> HashedPostState {
157 HashedPostState::from_bundle_state::<
158 <Provider::StateCommitment as StateCommitment>::KeyHasher,
159 >(bundle_state.state())
160 }
161}
162
163impl<Provider: DBProvider + BlockHashReader + StateCommitmentProvider> StateProvider
164 for LatestStateProviderRef<'_, Provider>
165{
166 fn storage(
168 &self,
169 account: Address,
170 storage_key: StorageKey,
171 ) -> ProviderResult<Option<StorageValue>> {
172 let mut cursor = self.tx().cursor_dup_read::<tables::PlainStorageState>()?;
173 if let Some(entry) = cursor.seek_by_key_subkey(account, storage_key)? {
174 if entry.key == storage_key {
175 return Ok(Some(entry.value))
176 }
177 }
178 Ok(None)
179 }
180
181 fn bytecode_by_hash(&self, code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
183 self.tx().get_by_encoded_key::<tables::Bytecodes>(code_hash).map_err(Into::into)
184 }
185}
186
187impl<Provider: StateCommitmentProvider> StateCommitmentProvider
188 for LatestStateProviderRef<'_, Provider>
189{
190 type StateCommitment = Provider::StateCommitment;
191}
192
193#[derive(Debug)]
195pub struct LatestStateProvider<Provider>(Provider);
196
197impl<Provider: DBProvider + StateCommitmentProvider> LatestStateProvider<Provider> {
198 pub const fn new(db: Provider) -> Self {
200 Self(db)
201 }
202
203 #[inline(always)]
205 const fn as_ref(&self) -> LatestStateProviderRef<'_, Provider> {
206 LatestStateProviderRef::new(&self.0)
207 }
208}
209
210impl<Provider: StateCommitmentProvider> StateCommitmentProvider for LatestStateProvider<Provider> {
211 type StateCommitment = Provider::StateCommitment;
212}
213
214delegate_provider_impls!(LatestStateProvider<Provider> where [Provider: DBProvider + BlockHashReader + StateCommitmentProvider]);
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220
221 const fn assert_state_provider<T: StateProvider>() {}
222 #[expect(dead_code)]
223 const fn assert_latest_state_provider<
224 T: DBProvider + BlockHashReader + StateCommitmentProvider,
225 >() {
226 assert_state_provider::<LatestStateProvider<T>>();
227 }
228}