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