1use crate::{
2 prefix_set::{PrefixSetMut, TriePrefixSetsMut},
3 Nibbles,
4};
5use alloy_primitives::{
6 keccak256,
7 map::{hash_map, B256HashMap, B256HashSet, HashMap, HashSet},
8 Address, B256, U256,
9};
10use itertools::Itertools;
11use rayon::prelude::{IntoParallelIterator, ParallelIterator};
12use reth_primitives::Account;
13use reth_trie_common::KeyHasher;
14use revm::{
15 db::{states::CacheAccount, AccountStatus, BundleAccount},
16 primitives::FlaggedStorage,
17};
18use std::borrow::Cow;
19
20#[derive(PartialEq, Eq, Clone, Default, Debug)]
22pub struct HashedPostState {
23 pub accounts: B256HashMap<Option<Account>>,
25 pub storages: B256HashMap<HashedStorage>,
27}
28
29impl HashedPostState {
30 pub fn from_bundle_state<'a, KH: KeyHasher>(
34 state: impl IntoParallelIterator<Item = (&'a Address, &'a BundleAccount)>,
35 ) -> Self {
36 let hashed = state
37 .into_par_iter()
38 .map(|(address, account)| {
39 let hashed_address = KH::hash_key(address);
40 let hashed_account = account.info.as_ref().map(Into::into);
41 let hashed_storage = HashedStorage::from_plain_storage(
42 account.status,
43 account.storage.iter().map(|(slot, value)| (slot, &value.present_value)),
44 );
45 (hashed_address, (hashed_account, hashed_storage))
46 })
47 .collect::<Vec<(B256, (Option<Account>, HashedStorage))>>();
48
49 let mut accounts = HashMap::with_capacity_and_hasher(hashed.len(), Default::default());
50 let mut storages = HashMap::with_capacity_and_hasher(hashed.len(), Default::default());
51 for (address, (account, storage)) in hashed {
52 accounts.insert(address, account);
53 storages.insert(address, storage);
54 }
55 Self { accounts, storages }
56 }
57
58 pub fn from_cache_state<'a, KH: KeyHasher>(
61 state: impl IntoParallelIterator<Item = (&'a Address, &'a CacheAccount)>,
62 ) -> Self {
63 let hashed = state
64 .into_par_iter()
65 .map(|(address, account)| {
66 let hashed_address = KH::hash_key(address);
67 let hashed_account = account.account.as_ref().map(|a| (&a.info).into());
68 let hashed_storage = HashedStorage::from_plain_storage(
69 account.status,
70 account.account.as_ref().map(|a| a.storage.iter()).into_iter().flatten(),
71 );
72 (hashed_address, (hashed_account, hashed_storage))
73 })
74 .collect::<Vec<(B256, (Option<Account>, HashedStorage))>>();
75
76 let mut accounts = HashMap::with_capacity_and_hasher(hashed.len(), Default::default());
77 let mut storages = HashMap::with_capacity_and_hasher(hashed.len(), Default::default());
78 for (address, (account, storage)) in hashed {
79 accounts.insert(address, account);
80 storages.insert(address, storage);
81 }
82 Self { accounts, storages }
83 }
84
85 pub fn from_hashed_storage(hashed_address: B256, storage: HashedStorage) -> Self {
87 Self {
88 accounts: HashMap::default(),
89 storages: HashMap::from_iter([(hashed_address, storage)]),
90 }
91 }
92
93 pub fn with_accounts(
95 mut self,
96 accounts: impl IntoIterator<Item = (B256, Option<Account>)>,
97 ) -> Self {
98 self.accounts = HashMap::from_iter(accounts);
99 self
100 }
101
102 pub fn with_storages(
104 mut self,
105 storages: impl IntoIterator<Item = (B256, HashedStorage)>,
106 ) -> Self {
107 self.storages = HashMap::from_iter(storages);
108 self
109 }
110
111 pub fn is_empty(&self) -> bool {
113 self.accounts.is_empty() && self.storages.is_empty()
114 }
115
116 pub fn construct_prefix_sets(&self) -> TriePrefixSetsMut {
120 let mut account_prefix_set = PrefixSetMut::with_capacity(self.accounts.len());
122 let mut destroyed_accounts = HashSet::default();
123 for (hashed_address, account) in &self.accounts {
124 account_prefix_set.insert(Nibbles::unpack(hashed_address));
125
126 if account.is_none() {
127 destroyed_accounts.insert(*hashed_address);
128 }
129 }
130
131 let mut storage_prefix_sets =
133 HashMap::with_capacity_and_hasher(self.storages.len(), Default::default());
134 for (hashed_address, hashed_storage) in &self.storages {
135 account_prefix_set.insert(Nibbles::unpack(hashed_address));
136 storage_prefix_sets.insert(*hashed_address, hashed_storage.construct_prefix_set());
137 }
138
139 TriePrefixSetsMut { account_prefix_set, storage_prefix_sets, destroyed_accounts }
140 }
141
142 pub fn extend(&mut self, other: Self) {
145 self.extend_inner(Cow::Owned(other));
146 }
147
148 pub fn extend_ref(&mut self, other: &Self) {
153 self.extend_inner(Cow::Borrowed(other));
154 }
155
156 fn extend_inner(&mut self, other: Cow<'_, Self>) {
157 self.accounts.extend(other.accounts.iter().map(|(&k, &v)| (k, v)));
158
159 self.storages.reserve(other.storages.len());
160 match other {
161 Cow::Borrowed(other) => {
162 self.extend_storages(other.storages.iter().map(|(k, v)| (*k, Cow::Borrowed(v))))
163 }
164 Cow::Owned(other) => {
165 self.extend_storages(other.storages.into_iter().map(|(k, v)| (k, Cow::Owned(v))))
166 }
167 }
168 }
169
170 fn extend_storages<'a>(
171 &mut self,
172 storages: impl IntoIterator<Item = (B256, Cow<'a, HashedStorage>)>,
173 ) {
174 for (hashed_address, storage) in storages {
175 match self.storages.entry(hashed_address) {
176 hash_map::Entry::Vacant(entry) => {
177 entry.insert(storage.into_owned());
178 }
179 hash_map::Entry::Occupied(mut entry) => {
180 entry.get_mut().extend(&storage);
181 }
182 }
183 }
184 }
185
186 pub fn into_sorted(self) -> HashedPostStateSorted {
188 let mut updated_accounts = Vec::new();
189 let mut destroyed_accounts = HashSet::default();
190 for (hashed_address, info) in self.accounts {
191 if let Some(info) = info {
192 updated_accounts.push((hashed_address, info));
193 } else {
194 destroyed_accounts.insert(hashed_address);
195 }
196 }
197 updated_accounts.sort_unstable_by_key(|(address, _)| *address);
198 let accounts = HashedAccountsSorted { accounts: updated_accounts, destroyed_accounts };
199
200 let storages = self
201 .storages
202 .into_iter()
203 .map(|(hashed_address, storage)| (hashed_address, storage.into_sorted()))
204 .collect();
205
206 HashedPostStateSorted { accounts, storages }
207 }
208}
209
210#[derive(PartialEq, Eq, Clone, Debug, Default)]
212pub struct HashedStorage {
213 pub wiped: bool,
215 pub storage: B256HashMap<FlaggedStorage>,
217}
218
219impl HashedStorage {
220 pub fn new(wiped: bool) -> Self {
222 Self { wiped, storage: HashMap::default() }
223 }
224
225 pub fn from_iter(wiped: bool, iter: impl IntoIterator<Item = (B256, FlaggedStorage)>) -> Self {
227 Self { wiped, storage: HashMap::from_iter(iter) }
228 }
229
230 pub fn from_plain_storage<'a>(
232 status: AccountStatus,
233 storage: impl IntoIterator<Item = (&'a U256, &'a FlaggedStorage)>,
234 ) -> Self {
235 Self::from_iter(
236 status.was_destroyed(),
237 storage.into_iter().map(|(key, value)| (keccak256(B256::from(*key)), value.clone())),
238 )
239 }
240
241 pub fn construct_prefix_set(&self) -> PrefixSetMut {
243 if self.wiped {
244 PrefixSetMut::all()
245 } else {
246 let mut prefix_set = PrefixSetMut::with_capacity(self.storage.len());
247 for hashed_slot in self.storage.keys() {
248 prefix_set.insert(Nibbles::unpack(hashed_slot));
249 }
250 prefix_set
251 }
252 }
253
254 pub fn extend(&mut self, other: &Self) {
257 if other.wiped {
258 self.wiped = true;
259 self.storage.clear();
260 }
261 self.storage.extend(other.storage.iter().map(|(&k, &v)| (k, v)));
262 }
263
264 pub fn into_sorted(self) -> HashedStorageSorted {
266 let mut non_zero_valued_slots = Vec::new();
267 let mut zero_valued_slots = HashSet::default();
268 for (hashed_slot, value) in self.storage {
269 if value.is_zero() {
270 zero_valued_slots.insert(hashed_slot);
271 } else {
272 non_zero_valued_slots.push((hashed_slot, value));
273 }
274 }
275 non_zero_valued_slots.sort_unstable_by_key(|(key, _)| *key);
276
277 HashedStorageSorted { non_zero_valued_slots, zero_valued_slots, wiped: self.wiped }
278 }
279}
280
281#[derive(PartialEq, Eq, Clone, Default, Debug)]
283pub struct HashedPostStateSorted {
284 pub(crate) accounts: HashedAccountsSorted,
286 pub(crate) storages: B256HashMap<HashedStorageSorted>,
288}
289
290impl HashedPostStateSorted {
291 pub const fn new(
293 accounts: HashedAccountsSorted,
294 storages: B256HashMap<HashedStorageSorted>,
295 ) -> Self {
296 Self { accounts, storages }
297 }
298
299 pub const fn accounts(&self) -> &HashedAccountsSorted {
301 &self.accounts
302 }
303
304 pub const fn account_storages(&self) -> &B256HashMap<HashedStorageSorted> {
306 &self.storages
307 }
308}
309
310#[derive(Clone, Eq, PartialEq, Default, Debug)]
312pub struct HashedAccountsSorted {
313 pub(crate) accounts: Vec<(B256, Account)>,
315 pub(crate) destroyed_accounts: B256HashSet,
317}
318
319impl HashedAccountsSorted {
320 pub fn accounts_sorted(&self) -> impl Iterator<Item = (B256, Option<Account>)> {
322 self.accounts
323 .iter()
324 .map(|(address, account)| (*address, Some(*account)))
325 .chain(self.destroyed_accounts.iter().map(|address| (*address, None)))
326 .sorted_by_key(|entry| *entry.0)
327 }
328}
329
330#[derive(Clone, Eq, PartialEq, Debug)]
332pub struct HashedStorageSorted {
333 pub(crate) non_zero_valued_slots: Vec<(B256, FlaggedStorage)>,
335 pub(crate) zero_valued_slots: B256HashSet,
337 pub(crate) wiped: bool,
339}
340
341impl HashedStorageSorted {
342 pub const fn is_wiped(&self) -> bool {
344 self.wiped
345 }
346
347 pub fn storage_slots_sorted(&self) -> impl Iterator<Item = (B256, FlaggedStorage)> {
349 self.non_zero_valued_slots
350 .iter()
351 .map(|(hashed_slot, value)| (*hashed_slot, *value))
352 .chain(
353 self.zero_valued_slots
354 .iter()
355 .map(|hashed_slot| (*hashed_slot, FlaggedStorage::ZERO)),
356 )
357 .sorted_by_key(|entry| *entry.0)
358 }
359}
360
361#[cfg(test)]
362mod tests {
363 use super::*;
364 use alloy_primitives::Bytes;
365 use reth_trie_common::KeccakKeyHasher;
366 use revm::{
367 db::{
368 states::{plain_account::PlainStorage, StorageSlot},
369 PlainAccount, StorageWithOriginalValues,
370 },
371 primitives::{AccountInfo, Bytecode},
372 };
373
374 #[test]
375 fn hashed_state_wiped_extension() {
376 let hashed_address = B256::default();
377 let hashed_slot = B256::with_last_byte(64);
378 let hashed_slot2 = B256::with_last_byte(65);
379
380 let original_slot_value = FlaggedStorage::new(123, true);
382 let mut hashed_state = HashedPostState::default().with_storages([(
383 hashed_address,
384 HashedStorage::from_iter(
385 false,
386 [(hashed_slot, original_slot_value), (hashed_slot2, original_slot_value)],
387 ),
388 )]);
389
390 let updated_slot_value = FlaggedStorage::new_from_tuple((321, false));
392 let extension = HashedPostState::default().with_storages([(
393 hashed_address,
394 HashedStorage::from_iter(false, [(hashed_slot, updated_slot_value)]),
395 )]);
396 hashed_state.extend(extension);
397
398 let account_storage = hashed_state.storages.get(&hashed_address);
399 assert_eq!(
400 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
401 Some(&updated_slot_value)
402 );
403 assert_eq!(
404 account_storage.and_then(|st| st.storage.get(&hashed_slot2)),
405 Some(&original_slot_value)
406 );
407 assert_eq!(account_storage.map(|st| st.wiped), Some(false));
408
409 let wiped_extension =
411 HashedPostState::default().with_storages([(hashed_address, HashedStorage::new(true))]);
412 hashed_state.extend(wiped_extension);
413
414 let account_storage = hashed_state.storages.get(&hashed_address);
415 assert_eq!(account_storage.map(|st| st.storage.is_empty()), Some(true));
416 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
417
418 hashed_state.extend(HashedPostState::default().with_storages([(
420 hashed_address,
421 HashedStorage::from_iter(false, [(hashed_slot, original_slot_value)]),
422 )]));
423 let account_storage = hashed_state.storages.get(&hashed_address);
424 assert_eq!(
425 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
426 Some(&original_slot_value)
427 );
428 assert_eq!(account_storage.and_then(|st| st.storage.get(&hashed_slot2)), None);
429 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
430
431 hashed_state.extend(HashedPostState::default().with_storages([(
433 hashed_address,
434 HashedStorage::from_iter(false, [(hashed_slot2, updated_slot_value)]),
435 )]));
436 let account_storage = hashed_state.storages.get(&hashed_address);
437 assert_eq!(
438 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
439 Some(&original_slot_value)
440 );
441 assert_eq!(
442 account_storage.and_then(|st| st.storage.get(&hashed_slot2)),
443 Some(&updated_slot_value)
444 );
445 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
446 }
447
448 #[test]
449 fn test_hashed_post_state_from_bundle_state() {
450 let address = Address::random();
452
453 let account_info = AccountInfo {
455 balance: U256::from(123),
456 nonce: 42,
457 code_hash: B256::random(),
458 code: Some(Bytecode::LegacyRaw(Bytes::from(vec![1, 2]))),
459 };
460
461 let mut storage = StorageWithOriginalValues::default();
462 storage.insert(
463 U256::from(1),
464 StorageSlot { present_value: FlaggedStorage::new_from_value(4), ..Default::default() },
465 );
466
467 let account = BundleAccount {
469 status: AccountStatus::Changed,
470 info: Some(account_info.clone()),
471 storage,
472 original_info: None,
473 };
474
475 let state = vec![(&address, &account)];
477
478 let hashed_state = HashedPostState::from_bundle_state::<KeccakKeyHasher>(state);
480
481 assert_eq!(hashed_state.accounts.len(), 1);
483 assert_eq!(hashed_state.storages.len(), 1);
484
485 assert_eq!(
487 *hashed_state.accounts.get(&keccak256(address)).unwrap(),
488 Some(account_info.into())
489 );
490 }
491
492 #[test]
493 fn test_hashed_post_state_from_cache_state() {
494 let address = Address::random();
496
497 let account_info = AccountInfo {
499 balance: U256::from(500),
500 nonce: 5,
501 code_hash: B256::random(),
502 code: None,
503 };
504
505 let mut storage = PlainStorage::default();
506 storage.insert(U256::from(1), FlaggedStorage::new_from_value(35636));
507
508 let account = CacheAccount {
510 account: Some(PlainAccount { info: account_info.clone(), storage }),
511 status: AccountStatus::Changed,
512 };
513
514 let state = vec![(&address, &account)];
516
517 let hashed_state = HashedPostState::from_cache_state::<KeccakKeyHasher>(state);
519
520 assert_eq!(hashed_state.accounts.len(), 1);
522 assert_eq!(hashed_state.storages.len(), 1);
523
524 assert_eq!(
526 *hashed_state.accounts.get(&keccak256(address)).unwrap(),
527 Some(account_info.into())
528 );
529 }
530
531 #[test]
532 fn test_hashed_post_state_with_accounts() {
533 let address_1 = Address::random();
535 let address_2 = Address::random();
536
537 let account_info_1 = AccountInfo {
538 balance: U256::from(1000),
539 nonce: 1,
540 code_hash: B256::random(),
541 code: None,
542 };
543
544 let account_1 = (keccak256(address_1), Some(account_info_1.into()));
546 let account_2 = (keccak256(address_2), None);
547
548 let hashed_state = HashedPostState::default().with_accounts(vec![account_1, account_2]);
550
551 assert_eq!(hashed_state.accounts.len(), 2);
553 assert!(hashed_state.accounts.contains_key(&keccak256(address_1)));
554 assert!(hashed_state.accounts.contains_key(&keccak256(address_2)));
555 }
556
557 #[test]
558 fn test_hashed_post_state_with_storages() {
559 let address_1 = Address::random();
561 let address_2 = Address::random();
562
563 let storage_1 = (keccak256(address_1), HashedStorage::new(false));
564 let storage_2 = (keccak256(address_2), HashedStorage::new(true));
565
566 let hashed_state = HashedPostState::default().with_storages(vec![storage_1, storage_2]);
568
569 assert_eq!(hashed_state.storages.len(), 2);
571 assert!(hashed_state.storages.contains_key(&keccak256(address_1)));
572 assert!(hashed_state.storages.contains_key(&keccak256(address_2)));
573 }
574
575 #[test]
576 fn test_hashed_post_state_is_empty() {
577 let empty_state = HashedPostState::default();
579 assert!(empty_state.is_empty());
580
581 let non_empty_state = HashedPostState::default()
583 .with_accounts(vec![(keccak256(Address::random()), Some(Account::default()))]);
584 assert!(!non_empty_state.is_empty());
585 }
586}