1use std::sync::Arc;
6
7use alloy_primitives::{Address, BlockNumber, Bytes, StorageKey, StorageValue, B256, U256};
8use reth_chain_state::BlockState;
9use reth_primitives_traits::{Account, Bytecode, NodePrimitives};
10use reth_storage_api::{
11 errors::provider::ProviderResult, AccountReader, BlockHashReader, BytecodeReader,
12 HashedPostStateProvider, StateProofProvider, StateProvider, StateProviderBox,
13 StateRootProvider, StorageRootProvider,
14};
15use reth_trie::{
16 updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
17 MultiProofTargets, StorageMultiProof, TrieInput,
18};
19use revm_database::BundleState;
20use rustc_hash::{FxHashMap, FxHashSet};
21
22#[derive(Default, Clone)]
30pub struct CoalescedOverlay {
31 slots: FxHashMap<(Address, B256), U256>,
34 wiped: FxHashSet<Address>,
37}
38
39impl CoalescedOverlay {
40 pub fn from_chain<N: NodePrimitives>(head: &BlockState<N>) -> Self {
45 let mut overlay = Self::default();
46 let blocks: Vec<&BlockState<N>> = head.chain().collect();
49 for block_state in blocks.into_iter().rev() {
50 overlay.extend_with_block(&block_state.block_ref().execution_output.state);
51 }
52 overlay
53 }
54
55 pub fn extend_with_block(&mut self, bundle: &BundleState) {
59 for (addr, account) in bundle.state.iter() {
60 if account.status.is_storage_known() {
61 self.wiped.insert(*addr);
62 self.slots.retain(|(a, _), _| a != addr);
63 }
64 for (slot_u256, slot_entry) in account.storage.iter() {
65 let key = B256::from(*slot_u256);
66 self.slots.insert((*addr, key), slot_entry.present_value);
67 }
68 }
69 }
70
71 pub fn is_empty(&self) -> bool {
72 self.slots.is_empty() && self.wiped.is_empty()
73 }
74
75 fn lookup(&self, address: Address, key: B256) -> Option<Option<U256>> {
76 if let Some(&val) = self.slots.get(&(address, key)) {
77 return Some(Some(val));
78 }
79 if self.wiped.contains(&address) {
80 return Some(Some(U256::ZERO));
81 }
82 None
83 }
84}
85
86pub struct CoalescedStateProvider {
90 inner: StateProviderBox,
91 overlay: Arc<CoalescedOverlay>,
92}
93
94impl CoalescedStateProvider {
95 pub fn new(inner: StateProviderBox, overlay: Arc<CoalescedOverlay>) -> Self {
96 Self { inner, overlay }
97 }
98
99 pub fn boxed(self) -> StateProviderBox {
100 Box::new(self)
101 }
102}
103
104impl BlockHashReader for CoalescedStateProvider {
105 fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>> {
106 self.inner.block_hash(number)
107 }
108
109 fn canonical_hashes_range(
110 &self,
111 start: BlockNumber,
112 end: BlockNumber,
113 ) -> ProviderResult<Vec<B256>> {
114 self.inner.canonical_hashes_range(start, end)
115 }
116}
117
118impl AccountReader for CoalescedStateProvider {
119 fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
120 self.inner.basic_account(address)
121 }
122}
123
124impl BytecodeReader for CoalescedStateProvider {
125 fn bytecode_by_hash(&self, code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
126 self.inner.bytecode_by_hash(code_hash)
127 }
128}
129
130impl StateRootProvider for CoalescedStateProvider {
131 fn state_root(&self, state: HashedPostState) -> ProviderResult<B256> {
132 self.inner.state_root(state)
133 }
134
135 fn state_root_from_nodes(&self, input: TrieInput) -> ProviderResult<B256> {
136 self.inner.state_root_from_nodes(input)
137 }
138
139 fn state_root_with_updates(
140 &self,
141 state: HashedPostState,
142 ) -> ProviderResult<(B256, TrieUpdates)> {
143 self.inner.state_root_with_updates(state)
144 }
145
146 fn state_root_from_nodes_with_updates(
147 &self,
148 input: TrieInput,
149 ) -> ProviderResult<(B256, TrieUpdates)> {
150 self.inner.state_root_from_nodes_with_updates(input)
151 }
152}
153
154impl StorageRootProvider for CoalescedStateProvider {
155 fn storage_root(&self, address: Address, storage: HashedStorage) -> ProviderResult<B256> {
156 self.inner.storage_root(address, storage)
157 }
158
159 fn storage_proof(
160 &self,
161 address: Address,
162 slot: B256,
163 storage: HashedStorage,
164 ) -> ProviderResult<reth_trie::StorageProof> {
165 self.inner.storage_proof(address, slot, storage)
166 }
167
168 fn storage_multiproof(
169 &self,
170 address: Address,
171 slots: &[B256],
172 storage: HashedStorage,
173 ) -> ProviderResult<StorageMultiProof> {
174 self.inner.storage_multiproof(address, slots, storage)
175 }
176}
177
178impl StateProofProvider for CoalescedStateProvider {
179 fn proof(
180 &self,
181 input: TrieInput,
182 address: Address,
183 slots: &[B256],
184 ) -> ProviderResult<AccountProof> {
185 self.inner.proof(input, address, slots)
186 }
187
188 fn multiproof(
189 &self,
190 input: TrieInput,
191 targets: MultiProofTargets,
192 ) -> ProviderResult<MultiProof> {
193 self.inner.multiproof(input, targets)
194 }
195
196 fn witness(&self, input: TrieInput, target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
197 self.inner.witness(input, target)
198 }
199}
200
201impl HashedPostStateProvider for CoalescedStateProvider {
202 fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
203 self.inner.hashed_post_state(bundle_state)
204 }
205}
206
207impl StateProvider for CoalescedStateProvider {
208 fn storage(
209 &self,
210 address: Address,
211 storage_key: StorageKey,
212 ) -> ProviderResult<Option<StorageValue>> {
213 if let Some(val) = self.overlay.lookup(address, storage_key) {
214 return Ok(val);
215 }
216 self.inner.storage(address, storage_key)
217 }
218}