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