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#[derive(Debug)]
21pub struct BundleStateProvider<SP: StateProvider, EDP: ExecutionDataProvider> {
22 pub state_provider: SP,
24 pub block_execution_data_provider: EDP,
26}
27
28impl<SP: StateProvider, EDP: ExecutionDataProvider> BundleStateProvider<SP, EDP> {
29 pub const fn new(state_provider: SP, block_execution_data_provider: EDP) -> Self {
31 Self { state_provider, block_execution_data_provider }
32 }
33
34 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
49impl<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}