reth_provider/providers/
bundle_state_provider.rs

1use crate::{
2    AccountReader, BlockHashReader, ExecutionDataProvider, StateProvider, StateRootProvider,
3};
4use alloy_primitives::{map::B256HashMap, Address, BlockNumber, Bytes, B256};
5use reth_primitives::{Account, Bytecode};
6use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider};
7use reth_storage_errors::provider::ProviderResult;
8use reth_trie::{
9    updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
10    MultiProofTargets, StorageMultiProof, TrieInput,
11};
12use revm::primitives::FlaggedStorage;
13
14/// A state provider that resolves to data from either a wrapped [`crate::ExecutionOutcome`]
15/// or an underlying state provider.
16///
17/// This struct combines two sources of state data: the execution outcome and an underlying
18/// state provider. It can provide state information by leveraging both the post-block execution
19/// changes and the pre-existing state data.
20#[derive(Debug)]
21pub struct BundleStateProvider<SP: StateProvider, EDP: ExecutionDataProvider> {
22    /// The inner state provider.
23    pub state_provider: SP,
24    /// Block execution data.
25    pub block_execution_data_provider: EDP,
26}
27
28impl<SP: StateProvider, EDP: ExecutionDataProvider> BundleStateProvider<SP, EDP> {
29    /// Create new bundle state provider
30    pub const fn new(state_provider: SP, block_execution_data_provider: EDP) -> Self {
31        Self { state_provider, block_execution_data_provider }
32    }
33
34    /// Retrieve hashed storage for target address.
35    fn get_hashed_storage(&self, address: Address) -> HashedStorage {
36        let bundle_state = self.block_execution_data_provider.execution_outcome().state();
37        bundle_state
38            .account(&address)
39            .map(|account| {
40                HashedStorage::from_plain_storage(
41                    account.status,
42                    account.storage.iter().map(|(slot, value)| (slot, &value.present_value)),
43                )
44            })
45            .unwrap_or_default()
46    }
47}
48
49/* Implement StateProvider traits */
50
51impl<SP: StateProvider, EDP: ExecutionDataProvider> BlockHashReader
52    for BundleStateProvider<SP, EDP>
53{
54    fn block_hash(&self, block_number: BlockNumber) -> ProviderResult<Option<B256>> {
55        let block_hash = self.block_execution_data_provider.block_hash(block_number);
56        if block_hash.is_some() {
57            return Ok(block_hash)
58        }
59        self.state_provider.block_hash(block_number)
60    }
61
62    fn canonical_hashes_range(
63        &self,
64        _start: BlockNumber,
65        _end: BlockNumber,
66    ) -> ProviderResult<Vec<B256>> {
67        unimplemented!()
68    }
69}
70
71impl<SP: StateProvider, EDP: ExecutionDataProvider> AccountReader for BundleStateProvider<SP, EDP> {
72    fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
73        if let Some(account) =
74            self.block_execution_data_provider.execution_outcome().account(&address)
75        {
76            Ok(account)
77        } else {
78            self.state_provider.basic_account(address)
79        }
80    }
81}
82
83impl<SP: StateProvider, EDP: ExecutionDataProvider> StateRootProvider
84    for BundleStateProvider<SP, EDP>
85{
86    fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult<B256> {
87        let bundle_state = self.block_execution_data_provider.execution_outcome().state();
88        let mut state = self.hashed_post_state(bundle_state);
89        state.extend(hashed_state);
90        self.state_provider.state_root(state)
91    }
92
93    fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
94        unimplemented!()
95    }
96
97    fn state_root_with_updates(
98        &self,
99        hashed_state: HashedPostState,
100    ) -> ProviderResult<(B256, TrieUpdates)> {
101        let bundle_state = self.block_execution_data_provider.execution_outcome().state();
102        let mut state = self.hashed_post_state(bundle_state);
103        state.extend(hashed_state);
104        self.state_provider.state_root_with_updates(state)
105    }
106
107    fn state_root_from_nodes_with_updates(
108        &self,
109        mut input: TrieInput,
110    ) -> ProviderResult<(B256, TrieUpdates)> {
111        let bundle_state = self.block_execution_data_provider.execution_outcome().state();
112        input.prepend(self.hashed_post_state(bundle_state));
113        self.state_provider.state_root_from_nodes_with_updates(input)
114    }
115}
116
117impl<SP: StateProvider, EDP: ExecutionDataProvider> StorageRootProvider
118    for BundleStateProvider<SP, EDP>
119{
120    fn storage_root(
121        &self,
122        address: Address,
123        hashed_storage: HashedStorage,
124    ) -> ProviderResult<B256> {
125        let mut storage = self.get_hashed_storage(address);
126        storage.extend(&hashed_storage);
127        self.state_provider.storage_root(address, storage)
128    }
129
130    fn storage_proof(
131        &self,
132        address: Address,
133        slot: B256,
134        hashed_storage: HashedStorage,
135    ) -> ProviderResult<reth_trie::StorageProof> {
136        let mut storage = self.get_hashed_storage(address);
137        storage.extend(&hashed_storage);
138        self.state_provider.storage_proof(address, slot, storage)
139    }
140
141    fn storage_multiproof(
142        &self,
143        address: Address,
144        slots: &[B256],
145        hashed_storage: HashedStorage,
146    ) -> ProviderResult<StorageMultiProof> {
147        let mut storage = self.get_hashed_storage(address);
148        storage.extend(&hashed_storage);
149        self.state_provider.storage_multiproof(address, slots, storage)
150    }
151}
152
153impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
154    for BundleStateProvider<SP, EDP>
155{
156    fn proof(
157        &self,
158        mut input: TrieInput,
159        address: Address,
160        slots: &[B256],
161    ) -> ProviderResult<AccountProof> {
162        let bundle_state = self.block_execution_data_provider.execution_outcome().state();
163        input.prepend(self.hashed_post_state(bundle_state));
164        self.state_provider.proof(input, address, slots)
165    }
166
167    fn multiproof(
168        &self,
169        mut input: reth_trie::TrieInput,
170        targets: MultiProofTargets,
171    ) -> ProviderResult<MultiProof> {
172        let bundle_state = self.block_execution_data_provider.execution_outcome().state();
173        input.prepend(self.hashed_post_state(bundle_state));
174        self.state_provider.multiproof(input, targets)
175    }
176
177    fn witness(
178        &self,
179        mut input: TrieInput,
180        target: HashedPostState,
181    ) -> ProviderResult<B256HashMap<Bytes>> {
182        let bundle_state = self.block_execution_data_provider.execution_outcome().state();
183        input.prepend(self.hashed_post_state(bundle_state));
184        self.state_provider.witness(input, target)
185    }
186}
187
188impl<SP: StateProvider, EDP: ExecutionDataProvider> HashedPostStateProvider
189    for BundleStateProvider<SP, EDP>
190{
191    fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState {
192        self.state_provider.hashed_post_state(bundle_state)
193    }
194}
195
196impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProvider for BundleStateProvider<SP, EDP> {
197    fn storage(
198        &self,
199        account: Address,
200        storage_key: alloy_primitives::StorageKey,
201    ) -> ProviderResult<Option<FlaggedStorage>> {
202        let u256_storage_key = storage_key.into();
203        if let Some(value) = self
204            .block_execution_data_provider
205            .execution_outcome()
206            .storage(&account, u256_storage_key)
207        {
208            return Ok(Some(value))
209        }
210
211        self.state_provider.storage(account, storage_key)
212    }
213
214    fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> {
215        if let Some(bytecode) =
216            self.block_execution_data_provider.execution_outcome().bytecode(&code_hash)
217        {
218            return Ok(Some(bytecode))
219        }
220
221        self.state_provider.bytecode_by_hash(code_hash)
222    }
223}