1use super::{HashedCursor, HashedCursorFactory, HashedStorageCursor};
2use crate::forward_cursor::ForwardInMemoryCursor;
3use alloy_primitives::{map::B256Set, B256, U256};
4use reth_primitives_traits::Account;
5use reth_storage_errors::db::DatabaseError;
6use reth_trie_common::{HashedAccountsSorted, HashedPostStateSorted, HashedStorageSorted};
7
8#[derive(Clone, Debug)]
10pub struct HashedPostStateCursorFactory<CF, T> {
11 cursor_factory: CF,
12 post_state: T,
13}
14
15impl<CF, T> HashedPostStateCursorFactory<CF, T> {
16 pub const fn new(cursor_factory: CF, post_state: T) -> Self {
18 Self { cursor_factory, post_state }
19 }
20}
21
22impl<'overlay, CF, T> HashedCursorFactory for HashedPostStateCursorFactory<CF, &'overlay T>
23where
24 CF: HashedCursorFactory,
25 T: AsRef<HashedPostStateSorted>,
26{
27 type AccountCursor<'cursor>
28 = HashedPostStateAccountCursor<'overlay, CF::AccountCursor<'cursor>>
29 where
30 Self: 'cursor;
31 type StorageCursor<'cursor>
32 = HashedPostStateStorageCursor<'overlay, CF::StorageCursor<'cursor>>
33 where
34 Self: 'cursor;
35
36 fn hashed_account_cursor(&self) -> Result<Self::AccountCursor<'_>, DatabaseError> {
37 let cursor = self.cursor_factory.hashed_account_cursor()?;
38 Ok(HashedPostStateAccountCursor::new(cursor, &self.post_state.as_ref().accounts))
39 }
40
41 fn hashed_storage_cursor(
42 &self,
43 hashed_address: B256,
44 ) -> Result<Self::StorageCursor<'_>, DatabaseError> {
45 let cursor = self.cursor_factory.hashed_storage_cursor(hashed_address)?;
46 Ok(HashedPostStateStorageCursor::new(
47 cursor,
48 self.post_state.as_ref().storages.get(&hashed_address),
49 ))
50 }
51}
52
53#[derive(Debug)]
56pub struct HashedPostStateAccountCursor<'a, C> {
57 cursor: C,
59 post_state_cursor: ForwardInMemoryCursor<'a, B256, Account>,
61 destroyed_accounts: &'a B256Set,
63 last_account: Option<B256>,
66}
67
68impl<'a, C> HashedPostStateAccountCursor<'a, C>
69where
70 C: HashedCursor<Value = Account>,
71{
72 pub fn new(cursor: C, post_state_accounts: &'a HashedAccountsSorted) -> Self {
74 let post_state_cursor = ForwardInMemoryCursor::new(&post_state_accounts.accounts);
75 let destroyed_accounts = &post_state_accounts.destroyed_accounts;
76 Self { cursor, post_state_cursor, destroyed_accounts, last_account: None }
77 }
78
79 fn is_account_cleared(&self, account: &B256) -> bool {
85 self.destroyed_accounts.contains(account)
86 }
87
88 fn seek_inner(&mut self, key: B256) -> Result<Option<(B256, Account)>, DatabaseError> {
89 let post_state_entry = self.post_state_cursor.seek(&key);
92
93 if post_state_entry.is_some_and(|entry| entry.0 == key) {
96 return Ok(post_state_entry)
97 }
98
99 let mut db_entry = self.cursor.seek(key)?;
102 while db_entry.as_ref().is_some_and(|(address, _)| self.is_account_cleared(address)) {
103 db_entry = self.cursor.next()?;
104 }
105
106 Ok(Self::compare_entries(post_state_entry, db_entry))
108 }
109
110 fn next_inner(&mut self, last_account: B256) -> Result<Option<(B256, Account)>, DatabaseError> {
111 let post_state_entry = self.post_state_cursor.first_after(&last_account);
113
114 let mut db_entry = self.cursor.seek(last_account)?;
116 while db_entry.as_ref().is_some_and(|(address, _)| {
117 address <= &last_account || self.is_account_cleared(address)
118 }) {
119 db_entry = self.cursor.next()?;
120 }
121
122 Ok(Self::compare_entries(post_state_entry, db_entry))
124 }
125
126 fn compare_entries(
131 post_state_item: Option<(B256, Account)>,
132 db_item: Option<(B256, Account)>,
133 ) -> Option<(B256, Account)> {
134 if let Some((post_state_entry, db_entry)) = post_state_item.zip(db_item) {
135 Some(if post_state_entry.0 <= db_entry.0 { post_state_entry } else { db_entry })
138 } else {
139 db_item.or(post_state_item)
141 }
142 }
143}
144
145impl<C> HashedCursor for HashedPostStateAccountCursor<'_, C>
146where
147 C: HashedCursor<Value = Account>,
148{
149 type Value = Account;
150
151 fn seek(&mut self, key: B256) -> Result<Option<(B256, Self::Value)>, DatabaseError> {
160 let entry = self.seek_inner(key)?;
162 self.last_account = entry.as_ref().map(|entry| entry.0);
163 Ok(entry)
164 }
165
166 fn next(&mut self) -> Result<Option<(B256, Self::Value)>, DatabaseError> {
174 let next = match self.last_account {
175 Some(account) => {
176 let entry = self.next_inner(account)?;
177 self.last_account = entry.as_ref().map(|entry| entry.0);
178 entry
179 }
180 None => None,
182 };
183 Ok(next)
184 }
185}
186
187#[derive(Debug)]
190pub struct HashedPostStateStorageCursor<'a, C> {
191 cursor: C,
193 post_state_cursor: Option<ForwardInMemoryCursor<'a, B256, U256>>,
195 cleared_slots: Option<&'a B256Set>,
197 storage_wiped: bool,
199 last_slot: Option<B256>,
202}
203
204impl<'a, C> HashedPostStateStorageCursor<'a, C>
205where
206 C: HashedStorageCursor<Value = U256>,
207{
208 pub fn new(cursor: C, post_state_storage: Option<&'a HashedStorageSorted>) -> Self {
210 let post_state_cursor =
211 post_state_storage.map(|s| ForwardInMemoryCursor::new(&s.non_zero_valued_slots));
212 let cleared_slots = post_state_storage.map(|s| &s.zero_valued_slots);
213 let storage_wiped = post_state_storage.is_some_and(|s| s.wiped);
214 Self { cursor, post_state_cursor, cleared_slots, storage_wiped, last_slot: None }
215 }
216
217 fn is_slot_zero_valued(&self, slot: &B256) -> bool {
220 self.cleared_slots.is_some_and(|s| s.contains(slot))
221 }
222
223 fn seek_inner(&mut self, subkey: B256) -> Result<Option<(B256, U256)>, DatabaseError> {
225 let post_state_entry = self.post_state_cursor.as_mut().and_then(|c| c.seek(&subkey));
227
228 if self.storage_wiped || post_state_entry.is_some_and(|entry| entry.0 == subkey) {
231 return Ok(post_state_entry)
232 }
233
234 let mut db_entry = self.cursor.seek(subkey)?;
237 while db_entry.as_ref().is_some_and(|entry| self.is_slot_zero_valued(&entry.0)) {
238 db_entry = self.cursor.next()?;
239 }
240
241 Ok(Self::compare_entries(post_state_entry, db_entry))
243 }
244
245 fn next_inner(&mut self, last_slot: B256) -> Result<Option<(B256, U256)>, DatabaseError> {
247 let post_state_entry =
249 self.post_state_cursor.as_mut().and_then(|c| c.first_after(&last_slot));
250
251 if self.storage_wiped {
253 return Ok(post_state_entry)
254 }
255
256 let mut db_entry = self.cursor.seek(last_slot)?;
259 while db_entry
260 .as_ref()
261 .is_some_and(|entry| entry.0 == last_slot || self.is_slot_zero_valued(&entry.0))
262 {
263 db_entry = self.cursor.next()?;
264 }
265
266 Ok(Self::compare_entries(post_state_entry, db_entry))
268 }
269
270 fn compare_entries(
275 post_state_item: Option<(B256, U256)>,
276 db_item: Option<(B256, U256)>,
277 ) -> Option<(B256, U256)> {
278 if let Some((post_state_entry, db_entry)) = post_state_item.zip(db_item) {
279 Some(if post_state_entry.0 <= db_entry.0 { post_state_entry } else { db_entry })
282 } else {
283 db_item.or(post_state_item)
285 }
286 }
287}
288
289impl<C> HashedCursor for HashedPostStateStorageCursor<'_, C>
290where
291 C: HashedStorageCursor<Value = U256>,
292{
293 type Value = U256;
294
295 fn seek(&mut self, subkey: B256) -> Result<Option<(B256, Self::Value)>, DatabaseError> {
297 let entry = self.seek_inner(subkey)?;
298 self.last_slot = entry.as_ref().map(|entry| entry.0);
299 Ok(entry)
300 }
301
302 fn next(&mut self) -> Result<Option<(B256, Self::Value)>, DatabaseError> {
304 let next = match self.last_slot {
305 Some(last_slot) => {
306 let entry = self.next_inner(last_slot)?;
307 self.last_slot = entry.as_ref().map(|entry| entry.0);
308 entry
309 }
310 None => None,
312 };
313 Ok(next)
314 }
315}
316
317impl<C> HashedStorageCursor for HashedPostStateStorageCursor<'_, C>
318where
319 C: HashedStorageCursor<Value = U256>,
320{
321 fn is_storage_empty(&mut self) -> Result<bool, DatabaseError> {
326 let is_empty = match &self.post_state_cursor {
327 Some(cursor) => {
328 self.storage_wiped &&
330 cursor.is_empty()
332 }
333 None => self.cursor.is_storage_empty()?,
334 };
335 Ok(is_empty)
336 }
337}