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