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::{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/// State provider over latest state that takes tx reference.
27///
28/// Wraps a [`DBProvider`] to get access to database.
29#[derive(Debug)]
30pub struct LatestStateProviderRef<'b, Provider>(&'b Provider);
31
32impl<'b, Provider: DBProvider> LatestStateProviderRef<'b, Provider> {
33    /// Create new state provider
34    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    /// Get basic account information.
45    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    /// Get block hash by number.
52    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    /// Get storage.
171    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    /// Get account code by its hash
186    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/// State provider for the latest state.
198#[derive(Debug)]
199pub struct LatestStateProvider<Provider>(Provider);
200
201impl<Provider: DBProvider + StateCommitmentProvider> LatestStateProvider<Provider> {
202    /// Create new state provider
203    pub const fn new(db: Provider) -> Self {
204        Self(db)
205    }
206
207    /// Returns a new provider that takes the `TX` as reference
208    #[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
218// Delegates all provider impls to [LatestStateProviderRef]
219delegate_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}