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