reth_provider/providers/
bundle_state_provider.rs

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