1use core::ops::Not;
2
3use crate::{
4 added_removed_keys::MultiAddedRemovedKeys,
5 prefix_set::{PrefixSetMut, TriePrefixSetsMut},
6 utils::{extend_sorted_vec, kway_merge_sorted},
7 KeyHasher, MultiProofTargets, Nibbles,
8};
9use alloc::{borrow::Cow, vec::Vec};
10use alloy_primitives::{
11 keccak256,
12 map::{hash_map, B256Map, HashMap, HashSet},
13 Address, B256, U256,
14};
15use itertools::Itertools;
16#[cfg(feature = "rayon")]
17pub use rayon::*;
18use reth_primitives_traits::Account;
19
20#[cfg(feature = "rayon")]
21use rayon::prelude::{FromParallelIterator, IntoParallelIterator, ParallelIterator};
22
23use revm_database::{AccountStatus, BundleAccount};
24
25#[derive(PartialEq, Eq, Clone, Default, Debug)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub struct HashedPostState {
30 pub accounts: B256Map<Option<Account>>,
32 pub storages: B256Map<HashedStorage>,
34}
35
36impl HashedPostState {
37 pub fn with_capacity(capacity: usize) -> Self {
39 Self {
40 accounts: B256Map::with_capacity_and_hasher(capacity, Default::default()),
41 storages: B256Map::with_capacity_and_hasher(capacity, Default::default()),
42 }
43 }
44
45 #[inline]
49 #[cfg(feature = "rayon")]
50 pub fn from_bundle_state<'a, KH: KeyHasher>(
51 state: impl IntoParallelIterator<Item = (&'a Address, &'a BundleAccount)>,
52 ) -> Self {
53 state
54 .into_par_iter()
55 .map(|(address, account)| {
56 let hashed_address = KH::hash_key(address);
57 let hashed_account = account.info.as_ref().map(Into::into);
58 let hashed_storage = HashedStorage::from_plain_storage(
59 account.status,
60 account.storage.iter().map(|(slot, value)| (slot, &value.present_value)),
61 );
62
63 (
64 hashed_address,
65 hashed_account,
66 (!hashed_storage.is_empty()).then_some(hashed_storage),
67 )
68 })
69 .collect()
70 }
71
72 #[cfg(not(feature = "rayon"))]
76 pub fn from_bundle_state<'a, KH: KeyHasher>(
77 state: impl IntoIterator<Item = (&'a Address, &'a BundleAccount)>,
78 ) -> Self {
79 state
80 .into_iter()
81 .map(|(address, account)| {
82 let hashed_address = KH::hash_key(address);
83 let hashed_account = account.info.as_ref().map(Into::into);
84 let hashed_storage = HashedStorage::from_plain_storage(
85 account.status,
86 account.storage.iter().map(|(slot, value)| (slot, &value.present_value)),
87 );
88
89 (
90 hashed_address,
91 hashed_account,
92 (!hashed_storage.is_empty()).then_some(hashed_storage),
93 )
94 })
95 .collect()
96 }
97
98 pub fn from_hashed_storage(hashed_address: B256, storage: HashedStorage) -> Self {
100 Self {
101 accounts: HashMap::default(),
102 storages: HashMap::from_iter([(hashed_address, storage)]),
103 }
104 }
105
106 pub fn with_accounts(
108 mut self,
109 accounts: impl IntoIterator<Item = (B256, Option<Account>)>,
110 ) -> Self {
111 self.accounts = HashMap::from_iter(accounts);
112 self
113 }
114
115 pub fn with_storages(
117 mut self,
118 storages: impl IntoIterator<Item = (B256, HashedStorage)>,
119 ) -> Self {
120 self.storages = HashMap::from_iter(storages);
121 self
122 }
123
124 pub fn is_empty(&self) -> bool {
126 self.accounts.is_empty() && self.storages.is_empty()
127 }
128
129 pub fn construct_prefix_sets(&self) -> TriePrefixSetsMut {
133 let mut account_prefix_set = PrefixSetMut::with_capacity(self.accounts.len());
135 let mut destroyed_accounts = HashSet::default();
136 for (hashed_address, account) in &self.accounts {
137 account_prefix_set.insert(Nibbles::unpack(hashed_address));
138
139 if account.is_none() {
140 destroyed_accounts.insert(*hashed_address);
141 }
142 }
143
144 let mut storage_prefix_sets =
146 HashMap::with_capacity_and_hasher(self.storages.len(), Default::default());
147 for (hashed_address, hashed_storage) in &self.storages {
148 account_prefix_set.insert(Nibbles::unpack(hashed_address));
149 storage_prefix_sets.insert(*hashed_address, hashed_storage.construct_prefix_set());
150 }
151
152 TriePrefixSetsMut { account_prefix_set, storage_prefix_sets, destroyed_accounts }
153 }
154
155 pub fn multi_proof_targets(&self) -> MultiProofTargets {
157 let mut targets = MultiProofTargets::with_capacity(self.accounts.len());
159 for hashed_address in self.accounts.keys() {
160 targets.insert(*hashed_address, Default::default());
161 }
162 for (hashed_address, storage) in &self.storages {
163 targets.entry(*hashed_address).or_default().extend(storage.storage.keys().copied());
164 }
165 targets
166 }
167
168 pub fn multi_proof_targets_difference(
174 &self,
175 excluded: &MultiProofTargets,
176 ) -> MultiProofTargets {
177 let mut targets = MultiProofTargets::default();
178 for hashed_address in self.accounts.keys() {
179 if !excluded.contains_key(hashed_address) {
180 targets.insert(*hashed_address, Default::default());
181 }
182 }
183 for (hashed_address, storage) in &self.storages {
184 let maybe_excluded_storage = excluded.get(hashed_address);
185 let mut hashed_slots_targets = storage
186 .storage
187 .keys()
188 .filter(|slot| !maybe_excluded_storage.is_some_and(|f| f.contains(*slot)))
189 .peekable();
190 if hashed_slots_targets.peek().is_some() {
191 targets.entry(*hashed_address).or_default().extend(hashed_slots_targets);
192 }
193 }
194 targets
195 }
196
197 pub fn partition_by_targets(
204 mut self,
205 targets: &MultiProofTargets,
206 added_removed_keys: &MultiAddedRemovedKeys,
207 ) -> (Self, Self) {
208 let mut state_updates_not_in_targets = Self::default();
209
210 self.storages.retain(|&address, storage| {
211 let storage_added_removed_keys = added_removed_keys.get_storage(&address);
212
213 let (retain, storage_not_in_targets) = match targets.get(&address) {
214 Some(storage_in_targets) => {
215 let mut storage_not_in_targets = HashedStorage::default();
216 storage.storage.retain(|&slot, value| {
217 if storage_in_targets.contains(&slot) &&
218 !storage_added_removed_keys.is_some_and(|k| k.is_removed(&slot))
219 {
220 return true
221 }
222
223 storage_not_in_targets.storage.insert(slot, *value);
224 false
225 });
226
227 let retain = !storage.storage.is_empty();
231
232 if !retain {
236 storage_not_in_targets.wiped = storage.wiped;
237 }
238
239 (
240 retain,
241 storage_not_in_targets.is_empty().not().then_some(storage_not_in_targets),
242 )
243 }
244 None => (false, Some(core::mem::take(storage))),
245 };
246
247 if let Some(storage_not_in_targets) = storage_not_in_targets {
248 state_updates_not_in_targets.storages.insert(address, storage_not_in_targets);
249 }
250
251 retain
252 });
253 self.accounts.retain(|&address, account| {
254 if targets.contains_key(&address) {
255 return true
256 }
257
258 state_updates_not_in_targets.accounts.insert(address, *account);
259 false
260 });
261
262 (self, state_updates_not_in_targets)
263 }
264
265 pub fn chunks(self, size: usize) -> ChunkedHashedPostState {
269 ChunkedHashedPostState::new(self, size)
270 }
271
272 pub fn chunking_length(&self) -> usize {
274 self.accounts.len() +
275 self.storages
276 .values()
277 .map(|storage| if storage.wiped { 1 } else { 0 } + storage.storage.len())
278 .sum::<usize>()
279 }
280
281 pub fn extend(&mut self, other: Self) {
284 self.extend_inner(Cow::Owned(other));
285 }
286
287 pub fn extend_ref(&mut self, other: &Self) {
292 self.extend_inner(Cow::Borrowed(other));
293 }
294
295 fn extend_inner(&mut self, other: Cow<'_, Self>) {
296 self.accounts.extend(other.accounts.iter().map(|(&k, &v)| (k, v)));
297
298 self.storages.reserve(other.storages.len());
299 match other {
300 Cow::Borrowed(other) => {
301 self.extend_storages(other.storages.iter().map(|(k, v)| (*k, Cow::Borrowed(v))))
302 }
303 Cow::Owned(other) => {
304 self.extend_storages(other.storages.into_iter().map(|(k, v)| (k, Cow::Owned(v))))
305 }
306 }
307 }
308
309 fn extend_storages<'a>(
310 &mut self,
311 storages: impl IntoIterator<Item = (B256, Cow<'a, HashedStorage>)>,
312 ) {
313 for (hashed_address, storage) in storages {
314 match self.storages.entry(hashed_address) {
315 hash_map::Entry::Vacant(entry) => {
316 entry.insert(storage.into_owned());
317 }
318 hash_map::Entry::Occupied(mut entry) => {
319 entry.get_mut().extend(&storage);
320 }
321 }
322 }
323 }
324
325 pub fn extend_from_sorted(&mut self, sorted: &HashedPostStateSorted) {
329 self.accounts.reserve(sorted.accounts.len());
331
332 for (address, account) in &sorted.accounts {
334 self.accounts.insert(*address, *account);
335 }
336
337 self.storages.reserve(sorted.storages.len());
339
340 for (hashed_address, sorted_storage) in &sorted.storages {
342 match self.storages.entry(*hashed_address) {
343 hash_map::Entry::Vacant(entry) => {
344 let mut new_storage = HashedStorage::new(false);
345 new_storage.extend_from_sorted(sorted_storage);
346 entry.insert(new_storage);
347 }
348 hash_map::Entry::Occupied(mut entry) => {
349 entry.get_mut().extend_from_sorted(sorted_storage);
350 }
351 }
352 }
353 }
354
355 pub fn into_sorted(self) -> HashedPostStateSorted {
357 let mut accounts: Vec<_> = self.accounts.into_iter().collect();
358 accounts.sort_unstable_by_key(|(address, _)| *address);
359
360 let storages = self
361 .storages
362 .into_iter()
363 .map(|(hashed_address, storage)| (hashed_address, storage.into_sorted()))
364 .collect();
365
366 HashedPostStateSorted { accounts, storages }
367 }
368
369 pub fn clone_into_sorted(&self) -> HashedPostStateSorted {
372 let mut accounts: Vec<_> = self.accounts.iter().map(|(&k, &v)| (k, v)).collect();
373 accounts.sort_unstable_by_key(|(address, _)| *address);
374
375 let storages = self
376 .storages
377 .iter()
378 .map(|(&hashed_address, storage)| (hashed_address, storage.clone_into_sorted()))
379 .collect();
380
381 HashedPostStateSorted { accounts, storages }
382 }
383
384 pub fn clear(&mut self) {
386 self.accounts.clear();
387 self.storages.clear();
388 }
389}
390
391impl FromIterator<(B256, Option<Account>, Option<HashedStorage>)> for HashedPostState {
392 fn from_iter<T: IntoIterator<Item = (B256, Option<Account>, Option<HashedStorage>)>>(
408 iter: T,
409 ) -> Self {
410 let iter = iter.into_iter();
411 let (lower, _) = iter.size_hint();
412 let mut hashed_state = Self::with_capacity(lower);
413
414 for (hashed_address, info, hashed_storage) in iter {
415 hashed_state.accounts.insert(hashed_address, info);
416 if let Some(storage) = hashed_storage {
417 hashed_state.storages.insert(hashed_address, storage);
418 }
419 }
420
421 hashed_state
422 }
423}
424
425#[cfg(feature = "rayon")]
426impl FromParallelIterator<(B256, Option<Account>, Option<HashedStorage>)> for HashedPostState {
427 fn from_par_iter<I>(par_iter: I) -> Self
439 where
440 I: IntoParallelIterator<Item = (B256, Option<Account>, Option<HashedStorage>)>,
441 {
442 let vec: Vec<_> = par_iter.into_par_iter().collect();
443 vec.into_iter().collect()
444 }
445}
446
447#[derive(PartialEq, Eq, Clone, Debug, Default)]
449#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
450pub struct HashedStorage {
451 pub wiped: bool,
453 pub storage: B256Map<U256>,
455}
456
457impl HashedStorage {
458 pub fn new(wiped: bool) -> Self {
460 Self { wiped, storage: HashMap::default() }
461 }
462
463 pub fn is_empty(&self) -> bool {
465 !self.wiped && self.storage.is_empty()
466 }
467
468 pub fn from_iter(wiped: bool, iter: impl IntoIterator<Item = (B256, U256)>) -> Self {
470 Self { wiped, storage: HashMap::from_iter(iter) }
471 }
472
473 pub fn from_plain_storage<'a>(
475 status: AccountStatus,
476 storage: impl IntoIterator<Item = (&'a U256, &'a U256)>,
477 ) -> Self {
478 Self::from_iter(
479 status.was_destroyed(),
480 storage.into_iter().map(|(key, value)| (keccak256(B256::from(*key)), *value)),
481 )
482 }
483
484 pub fn construct_prefix_set(&self) -> PrefixSetMut {
486 if self.wiped {
487 PrefixSetMut::all()
488 } else {
489 let mut prefix_set = PrefixSetMut::with_capacity(self.storage.len());
490 for hashed_slot in self.storage.keys() {
491 prefix_set.insert(Nibbles::unpack(hashed_slot));
492 }
493 prefix_set
494 }
495 }
496
497 pub fn extend(&mut self, other: &Self) {
500 if other.wiped {
501 self.wiped = true;
502 self.storage.clear();
503 }
504 self.storage.extend(other.storage.iter().map(|(&k, &v)| (k, v)));
505 }
506
507 pub fn extend_from_sorted(&mut self, sorted: &HashedStorageSorted) {
511 if sorted.wiped {
512 self.wiped = true;
513 self.storage.clear();
514 }
515
516 self.storage.reserve(sorted.storage_slots.len());
518
519 for (slot, value) in &sorted.storage_slots {
521 self.storage.insert(*slot, *value);
522 }
523 }
524
525 pub fn into_sorted(self) -> HashedStorageSorted {
527 let mut storage_slots: Vec<_> = self.storage.into_iter().collect();
528 storage_slots.sort_unstable_by_key(|(key, _)| *key);
529
530 HashedStorageSorted { storage_slots, wiped: self.wiped }
531 }
532
533 pub fn clone_into_sorted(&self) -> HashedStorageSorted {
536 let mut storage_slots: Vec<_> = self.storage.iter().map(|(&k, &v)| (k, v)).collect();
537 storage_slots.sort_unstable_by_key(|(key, _)| *key);
538
539 HashedStorageSorted { storage_slots, wiped: self.wiped }
540 }
541}
542
543#[derive(PartialEq, Eq, Clone, Default, Debug)]
545#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
546pub struct HashedPostStateSorted {
547 pub accounts: Vec<(B256, Option<Account>)>,
549 pub storages: B256Map<HashedStorageSorted>,
551}
552
553impl HashedPostStateSorted {
554 pub const fn new(
556 accounts: Vec<(B256, Option<Account>)>,
557 storages: B256Map<HashedStorageSorted>,
558 ) -> Self {
559 Self { accounts, storages }
560 }
561
562 pub const fn accounts(&self) -> &Vec<(B256, Option<Account>)> {
564 &self.accounts
565 }
566
567 pub const fn account_storages(&self) -> &B256Map<HashedStorageSorted> {
569 &self.storages
570 }
571
572 pub fn is_empty(&self) -> bool {
574 self.accounts.is_empty() && self.storages.is_empty()
575 }
576
577 pub fn total_len(&self) -> usize {
579 self.accounts.len() + self.storages.values().map(|s| s.len()).sum::<usize>()
580 }
581
582 pub fn construct_prefix_sets(&self) -> TriePrefixSetsMut {
587 let mut account_prefix_set = PrefixSetMut::with_capacity(self.accounts.len());
588 let mut destroyed_accounts = HashSet::default();
589 for (hashed_address, account) in &self.accounts {
590 account_prefix_set.insert(Nibbles::unpack(hashed_address));
591 if account.is_none() {
592 destroyed_accounts.insert(*hashed_address);
593 }
594 }
595
596 let mut storage_prefix_sets =
597 B256Map::with_capacity_and_hasher(self.storages.len(), Default::default());
598 for (hashed_address, hashed_storage) in &self.storages {
599 account_prefix_set.insert(Nibbles::unpack(hashed_address));
601
602 let prefix_set = if hashed_storage.wiped {
603 PrefixSetMut::all()
604 } else {
605 let mut prefix_set =
606 PrefixSetMut::with_capacity(hashed_storage.storage_slots.len());
607 prefix_set.extend_keys(
608 hashed_storage
609 .storage_slots
610 .iter()
611 .map(|(hashed_slot, _)| Nibbles::unpack(hashed_slot)),
612 );
613 prefix_set
614 };
615
616 storage_prefix_sets.insert(*hashed_address, prefix_set);
617 }
618
619 TriePrefixSetsMut { account_prefix_set, storage_prefix_sets, destroyed_accounts }
620 }
621
622 pub fn extend_ref_and_sort(&mut self, other: &Self) {
627 extend_sorted_vec(&mut self.accounts, &other.accounts);
629
630 for (hashed_address, other_storage) in &other.storages {
632 self.storages
633 .entry(*hashed_address)
634 .and_modify(|existing| existing.extend_ref(other_storage))
635 .or_insert_with(|| other_storage.clone());
636 }
637 }
638
639 pub fn merge_batch<T: AsRef<Self> + From<Self>>(iter: impl IntoIterator<Item = T>) -> T {
644 const THRESHOLD: usize = 30;
645
646 let items: alloc::vec::Vec<_> = iter.into_iter().collect();
647 let k = items.len();
648
649 if k == 0 {
650 return Self::default().into();
651 }
652 if k == 1 {
653 return items.into_iter().next().expect("k == 1");
654 }
655
656 if k < THRESHOLD {
657 let mut iter = items.iter().rev();
659 let mut acc = iter.next().expect("k > 0").as_ref().clone();
660 for next in iter {
661 acc.extend_ref_and_sort(next.as_ref());
662 }
663 return acc.into();
664 }
665
666 let accounts = kway_merge_sorted(items.iter().map(|i| i.as_ref().accounts.as_slice()));
668
669 struct StorageAcc<'a> {
670 wiped: bool,
671 sealed: bool,
672 slices: Vec<&'a [(B256, U256)]>,
673 }
674
675 let mut acc: B256Map<StorageAcc<'_>> = B256Map::default();
676
677 for item in &items {
678 for (addr, storage) in &item.as_ref().storages {
679 let entry = acc.entry(*addr).or_insert_with(|| StorageAcc {
680 wiped: false,
681 sealed: false,
682 slices: Vec::new(),
683 });
684
685 if entry.sealed {
686 continue;
687 }
688
689 entry.slices.push(storage.storage_slots.as_slice());
690 if storage.wiped {
691 entry.wiped = true;
692 entry.sealed = true;
693 }
694 }
695 }
696
697 let storages = acc
698 .into_iter()
699 .map(|(addr, entry)| {
700 let storage_slots = kway_merge_sorted(entry.slices);
701 (addr, HashedStorageSorted { wiped: entry.wiped, storage_slots })
702 })
703 .collect();
704
705 Self { accounts, storages }.into()
706 }
707
708 pub fn clear(&mut self) {
710 self.accounts.clear();
711 self.storages.clear();
712 }
713}
714
715impl AsRef<Self> for HashedPostStateSorted {
716 fn as_ref(&self) -> &Self {
717 self
718 }
719}
720
721#[derive(Clone, Eq, PartialEq, Debug, Default)]
723#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
724pub struct HashedStorageSorted {
725 pub storage_slots: Vec<(B256, U256)>,
727 pub wiped: bool,
729}
730
731impl HashedStorageSorted {
732 pub const fn is_wiped(&self) -> bool {
734 self.wiped
735 }
736
737 pub fn storage_slots_ref(&self) -> &[(B256, U256)] {
739 &self.storage_slots
740 }
741
742 pub const fn len(&self) -> usize {
744 self.storage_slots.len()
745 }
746
747 pub const fn is_empty(&self) -> bool {
749 self.storage_slots.is_empty()
750 }
751
752 pub fn extend_ref(&mut self, other: &Self) {
757 if other.wiped {
758 self.wiped = true;
760 self.storage_slots.clear();
761 self.storage_slots.extend(other.storage_slots.iter().copied());
762 return;
763 }
764
765 extend_sorted_vec(&mut self.storage_slots, &other.storage_slots);
767 }
768
769 pub fn merge_batch<'a>(updates: impl IntoIterator<Item = &'a Self>) -> Self {
772 let updates: Vec<_> = updates.into_iter().collect();
773 if updates.is_empty() {
774 return Self::default();
775 }
776
777 let wipe_idx = updates.iter().position(|u| u.wiped);
778 let relevant = wipe_idx.map_or(&updates[..], |idx| &updates[..=idx]);
779 let storage_slots = kway_merge_sorted(relevant.iter().map(|u| u.storage_slots.as_slice()));
780
781 Self { wiped: wipe_idx.is_some(), storage_slots }
782 }
783}
784
785impl From<HashedStorageSorted> for HashedStorage {
786 fn from(sorted: HashedStorageSorted) -> Self {
787 let mut storage = B256Map::default();
788
789 for (slot, value) in sorted.storage_slots {
791 storage.insert(slot, value);
792 }
793
794 Self { wiped: sorted.wiped, storage }
795 }
796}
797
798impl From<HashedPostStateSorted> for HashedPostState {
799 fn from(sorted: HashedPostStateSorted) -> Self {
800 let mut accounts =
801 B256Map::with_capacity_and_hasher(sorted.accounts.len(), Default::default());
802
803 for (address, account) in sorted.accounts {
805 accounts.insert(address, account);
806 }
807
808 let storages = sorted
810 .storages
811 .into_iter()
812 .map(|(address, storage)| (address, storage.into()))
813 .collect();
814
815 Self { accounts, storages }
816 }
817}
818
819#[derive(Debug)]
827pub struct ChunkedHashedPostState {
828 flattened: alloc::vec::IntoIter<(B256, FlattenedHashedPostStateItem)>,
829 size: usize,
830}
831
832#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
835enum FlattenedStateOrder {
836 StorageWipe,
837 StorageUpdate(B256),
838 Account,
839}
840
841#[derive(Debug)]
842enum FlattenedHashedPostStateItem {
843 Account(Option<Account>),
844 StorageWipe,
845 StorageUpdate { slot: B256, value: U256 },
846}
847
848impl FlattenedHashedPostStateItem {
849 const fn order(&self) -> FlattenedStateOrder {
850 match self {
851 Self::StorageWipe => FlattenedStateOrder::StorageWipe,
852 Self::StorageUpdate { slot, .. } => FlattenedStateOrder::StorageUpdate(*slot),
853 Self::Account(_) => FlattenedStateOrder::Account,
854 }
855 }
856}
857
858impl ChunkedHashedPostState {
859 fn new(hashed_post_state: HashedPostState, size: usize) -> Self {
860 let flattened = hashed_post_state
861 .storages
862 .into_iter()
863 .flat_map(|(address, storage)| {
864 storage
865 .wiped
866 .then_some((address, FlattenedHashedPostStateItem::StorageWipe))
867 .into_iter()
868 .chain(storage.storage.into_iter().map(move |(slot, value)| {
869 (address, FlattenedHashedPostStateItem::StorageUpdate { slot, value })
870 }))
871 })
872 .chain(hashed_post_state.accounts.into_iter().map(|(address, account)| {
873 (address, FlattenedHashedPostStateItem::Account(account))
874 }))
875 .sorted_unstable_by_key(|(address, item)| (*address, item.order()));
880
881 Self { flattened, size }
882 }
883}
884
885impl Iterator for ChunkedHashedPostState {
886 type Item = HashedPostState;
887
888 fn next(&mut self) -> Option<Self::Item> {
889 let mut chunk = HashedPostState::default();
890
891 let mut current_size = 0;
892 while current_size < self.size {
893 let Some((address, item)) = self.flattened.next() else { break };
894
895 match item {
896 FlattenedHashedPostStateItem::Account(account) => {
897 chunk.accounts.insert(address, account);
898 }
899 FlattenedHashedPostStateItem::StorageWipe => {
900 chunk.storages.entry(address).or_default().wiped = true;
901 }
902 FlattenedHashedPostStateItem::StorageUpdate { slot, value } => {
903 chunk.storages.entry(address).or_default().storage.insert(slot, value);
904 }
905 }
906
907 current_size += 1;
908 }
909
910 if chunk.is_empty() {
911 None
912 } else {
913 Some(chunk)
914 }
915 }
916}
917
918#[cfg(test)]
919mod tests {
920 use super::*;
921 use crate::KeccakKeyHasher;
922 use alloy_primitives::Bytes;
923 use revm_database::{states::StorageSlot, StorageWithOriginalValues};
924 use revm_state::{AccountInfo, Bytecode};
925
926 #[test]
927 fn hashed_state_wiped_extension() {
928 let hashed_address = B256::default();
929 let hashed_slot = B256::with_last_byte(64);
930 let hashed_slot2 = B256::with_last_byte(65);
931
932 let original_slot_value = U256::from(123);
934 let mut hashed_state = HashedPostState::default().with_storages([(
935 hashed_address,
936 HashedStorage::from_iter(
937 false,
938 [(hashed_slot, original_slot_value), (hashed_slot2, original_slot_value)],
939 ),
940 )]);
941
942 let updated_slot_value = U256::from(321);
944 let extension = HashedPostState::default().with_storages([(
945 hashed_address,
946 HashedStorage::from_iter(false, [(hashed_slot, updated_slot_value)]),
947 )]);
948 hashed_state.extend(extension);
949
950 let account_storage = hashed_state.storages.get(&hashed_address);
951 assert_eq!(
952 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
953 Some(&updated_slot_value)
954 );
955 assert_eq!(
956 account_storage.and_then(|st| st.storage.get(&hashed_slot2)),
957 Some(&original_slot_value)
958 );
959 assert_eq!(account_storage.map(|st| st.wiped), Some(false));
960
961 let wiped_extension =
963 HashedPostState::default().with_storages([(hashed_address, HashedStorage::new(true))]);
964 hashed_state.extend(wiped_extension);
965
966 let account_storage = hashed_state.storages.get(&hashed_address);
967 assert_eq!(account_storage.map(|st| st.storage.is_empty()), Some(true));
968 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
969
970 hashed_state.extend(HashedPostState::default().with_storages([(
972 hashed_address,
973 HashedStorage::from_iter(false, [(hashed_slot, original_slot_value)]),
974 )]));
975 let account_storage = hashed_state.storages.get(&hashed_address);
976 assert_eq!(
977 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
978 Some(&original_slot_value)
979 );
980 assert_eq!(account_storage.and_then(|st| st.storage.get(&hashed_slot2)), None);
981 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
982
983 hashed_state.extend(HashedPostState::default().with_storages([(
985 hashed_address,
986 HashedStorage::from_iter(false, [(hashed_slot2, updated_slot_value)]),
987 )]));
988 let account_storage = hashed_state.storages.get(&hashed_address);
989 assert_eq!(
990 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
991 Some(&original_slot_value)
992 );
993 assert_eq!(
994 account_storage.and_then(|st| st.storage.get(&hashed_slot2)),
995 Some(&updated_slot_value)
996 );
997 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
998 }
999
1000 #[test]
1001 fn test_hashed_post_state_from_bundle_state() {
1002 let address = Address::random();
1004
1005 let account_info = AccountInfo {
1007 balance: U256::from(123),
1008 nonce: 42,
1009 code_hash: B256::random(),
1010 code: Some(Bytecode::new_raw(Bytes::from(vec![1, 2]))),
1011 account_id: None,
1012 };
1013
1014 let mut storage = StorageWithOriginalValues::default();
1015 storage.insert(
1016 U256::from(1),
1017 StorageSlot { present_value: U256::from(4), ..Default::default() },
1018 );
1019
1020 let account = BundleAccount {
1022 status: AccountStatus::Changed,
1023 info: Some(account_info.clone()),
1024 storage,
1025 original_info: None,
1026 };
1027
1028 let state = vec![(&address, &account)];
1030
1031 let hashed_state = HashedPostState::from_bundle_state::<KeccakKeyHasher>(state);
1033
1034 assert_eq!(hashed_state.accounts.len(), 1);
1036 assert_eq!(hashed_state.storages.len(), 1);
1037
1038 assert_eq!(
1040 *hashed_state.accounts.get(&keccak256(address)).unwrap(),
1041 Some(account_info.into())
1042 );
1043 }
1044
1045 #[test]
1046 fn test_hashed_post_state_with_accounts() {
1047 let address_1 = Address::random();
1049 let address_2 = Address::random();
1050
1051 let account_info_1 = AccountInfo {
1052 balance: U256::from(1000),
1053 nonce: 1,
1054 code_hash: B256::random(),
1055 code: None,
1056 account_id: None,
1057 };
1058
1059 let account_1 = (keccak256(address_1), Some(account_info_1.into()));
1061 let account_2 = (keccak256(address_2), None);
1062
1063 let hashed_state = HashedPostState::default().with_accounts(vec![account_1, account_2]);
1065
1066 assert_eq!(hashed_state.accounts.len(), 2);
1068 assert!(hashed_state.accounts.contains_key(&keccak256(address_1)));
1069 assert!(hashed_state.accounts.contains_key(&keccak256(address_2)));
1070 }
1071
1072 #[test]
1073 fn test_hashed_post_state_with_storages() {
1074 let address_1 = Address::random();
1076 let address_2 = Address::random();
1077
1078 let storage_1 = (keccak256(address_1), HashedStorage::new(false));
1079 let storage_2 = (keccak256(address_2), HashedStorage::new(true));
1080
1081 let hashed_state = HashedPostState::default().with_storages(vec![storage_1, storage_2]);
1083
1084 assert_eq!(hashed_state.storages.len(), 2);
1086 assert!(hashed_state.storages.contains_key(&keccak256(address_1)));
1087 assert!(hashed_state.storages.contains_key(&keccak256(address_2)));
1088 }
1089
1090 #[test]
1091 fn test_hashed_post_state_is_empty() {
1092 let empty_state = HashedPostState::default();
1094 assert!(empty_state.is_empty());
1095
1096 let non_empty_state = HashedPostState::default()
1098 .with_accounts(vec![(keccak256(Address::random()), Some(Account::default()))]);
1099 assert!(!non_empty_state.is_empty());
1100 }
1101
1102 fn create_state_for_multi_proof_targets() -> HashedPostState {
1103 let mut state = HashedPostState::default();
1104
1105 let addr1 = B256::random();
1106 let addr2 = B256::random();
1107 state.accounts.insert(addr1, Some(Default::default()));
1108 state.accounts.insert(addr2, Some(Default::default()));
1109
1110 let mut storage = HashedStorage::default();
1111 let slot1 = B256::random();
1112 let slot2 = B256::random();
1113 storage.storage.insert(slot1, U256::ZERO);
1114 storage.storage.insert(slot2, U256::from(1));
1115 state.storages.insert(addr1, storage);
1116
1117 state
1118 }
1119
1120 #[test]
1121 fn test_multi_proof_targets_difference_empty_state() {
1122 let state = HashedPostState::default();
1123 let excluded = MultiProofTargets::default();
1124
1125 let targets = state.multi_proof_targets_difference(&excluded);
1126 assert!(targets.is_empty());
1127 }
1128
1129 #[test]
1130 fn test_multi_proof_targets_difference_new_account_targets() {
1131 let state = create_state_for_multi_proof_targets();
1132 let excluded = MultiProofTargets::default();
1133
1134 let targets = state.multi_proof_targets_difference(&excluded);
1136 assert_eq!(targets.len(), state.accounts.len());
1137 for addr in state.accounts.keys() {
1138 assert!(targets.contains_key(addr));
1139 }
1140 }
1141
1142 #[test]
1143 fn test_multi_proof_targets_difference_new_storage_targets() {
1144 let state = create_state_for_multi_proof_targets();
1145 let excluded = MultiProofTargets::default();
1146
1147 let targets = state.multi_proof_targets_difference(&excluded);
1148
1149 for (addr, storage) in &state.storages {
1151 assert!(targets.contains_key(addr));
1152 let target_slots = &targets[addr];
1153 assert_eq!(target_slots.len(), storage.storage.len());
1154 for slot in storage.storage.keys() {
1155 assert!(target_slots.contains(slot));
1156 }
1157 }
1158 }
1159
1160 #[test]
1161 fn test_multi_proof_targets_difference_filter_excluded_accounts() {
1162 let state = create_state_for_multi_proof_targets();
1163 let mut excluded = MultiProofTargets::default();
1164
1165 let excluded_addr = state
1167 .accounts
1168 .keys()
1169 .find(|&&addr| !state.storages.contains_key(&addr))
1170 .expect("Should have an account without storage");
1171
1172 excluded.insert(*excluded_addr, HashSet::default());
1174
1175 let targets = state.multi_proof_targets_difference(&excluded);
1176
1177 assert!(!targets.contains_key(excluded_addr));
1179 assert_eq!(targets.len(), state.accounts.len() - 1);
1181 }
1182
1183 #[test]
1184 fn test_multi_proof_targets_difference_filter_excluded_storage() {
1185 let state = create_state_for_multi_proof_targets();
1186 let mut excluded = MultiProofTargets::default();
1187
1188 let (addr, storage) = state.storages.iter().next().unwrap();
1190 let mut excluded_slots = HashSet::default();
1191 let excluded_slot = *storage.storage.keys().next().unwrap();
1192 excluded_slots.insert(excluded_slot);
1193 excluded.insert(*addr, excluded_slots);
1194
1195 let targets = state.multi_proof_targets_difference(&excluded);
1196
1197 let target_slots = &targets[addr];
1199 assert!(!target_slots.contains(&excluded_slot));
1200 assert_eq!(target_slots.len(), storage.storage.len() - 1);
1201 }
1202
1203 #[test]
1204 fn test_multi_proof_targets_difference_mixed_excluded_state() {
1205 let mut state = HashedPostState::default();
1206 let mut excluded = MultiProofTargets::default();
1207
1208 let addr1 = B256::random();
1209 let addr2 = B256::random();
1210 let slot1 = B256::random();
1211 let slot2 = B256::random();
1212
1213 state.accounts.insert(addr1, Some(Default::default()));
1214 state.accounts.insert(addr2, Some(Default::default()));
1215
1216 let mut storage = HashedStorage::default();
1217 storage.storage.insert(slot1, U256::ZERO);
1218 storage.storage.insert(slot2, U256::from(1));
1219 state.storages.insert(addr1, storage);
1220
1221 let mut excluded_slots = HashSet::default();
1222 excluded_slots.insert(slot1);
1223 excluded.insert(addr1, excluded_slots);
1224
1225 let targets = state.multi_proof_targets_difference(&excluded);
1226
1227 assert!(targets.contains_key(&addr2));
1228 assert!(!targets[&addr1].contains(&slot1));
1229 assert!(targets[&addr1].contains(&slot2));
1230 }
1231
1232 #[test]
1233 fn test_multi_proof_targets_difference_unmodified_account_with_storage() {
1234 let mut state = HashedPostState::default();
1235 let excluded = MultiProofTargets::default();
1236
1237 let addr = B256::random();
1238 let slot1 = B256::random();
1239 let slot2 = B256::random();
1240
1241 let mut storage = HashedStorage::default();
1244 storage.storage.insert(slot1, U256::from(1));
1245 storage.storage.insert(slot2, U256::from(2));
1246 state.storages.insert(addr, storage);
1247
1248 assert!(!state.accounts.contains_key(&addr));
1249 assert!(!excluded.contains_key(&addr));
1250
1251 let targets = state.multi_proof_targets_difference(&excluded);
1252
1253 assert!(targets.contains_key(&addr));
1255
1256 let target_slots = &targets[&addr];
1257 assert_eq!(target_slots.len(), 2);
1258 assert!(target_slots.contains(&slot1));
1259 assert!(target_slots.contains(&slot2));
1260 }
1261
1262 #[test]
1263 fn test_partition_by_targets() {
1264 let addr1 = B256::random();
1265 let addr2 = B256::random();
1266 let slot1 = B256::random();
1267 let slot2 = B256::random();
1268
1269 let state = HashedPostState {
1270 accounts: B256Map::from_iter([
1271 (addr1, Some(Default::default())),
1272 (addr2, Some(Default::default())),
1273 ]),
1274 storages: B256Map::from_iter([(
1275 addr1,
1276 HashedStorage {
1277 wiped: true,
1278 storage: B256Map::from_iter([(slot1, U256::ZERO), (slot2, U256::from(1))]),
1279 },
1280 )]),
1281 };
1282 let targets = MultiProofTargets::from_iter([(addr1, HashSet::from_iter([slot1]))]);
1283
1284 let (with_targets, without_targets) =
1285 state.partition_by_targets(&targets, &MultiAddedRemovedKeys::new());
1286
1287 assert_eq!(
1288 with_targets,
1289 HashedPostState {
1290 accounts: B256Map::from_iter([(addr1, Some(Default::default()))]),
1291 storages: B256Map::from_iter([(
1292 addr1,
1293 HashedStorage {
1294 wiped: true,
1295 storage: B256Map::from_iter([(slot1, U256::ZERO)])
1296 }
1297 )]),
1298 }
1299 );
1300 assert_eq!(
1301 without_targets,
1302 HashedPostState {
1303 accounts: B256Map::from_iter([(addr2, Some(Default::default()))]),
1304 storages: B256Map::from_iter([(
1305 addr1,
1306 HashedStorage {
1307 wiped: false,
1308 storage: B256Map::from_iter([(slot2, U256::from(1))])
1309 }
1310 )]),
1311 }
1312 );
1313 }
1314
1315 #[test]
1316 fn test_chunks() {
1317 let addr1 = B256::from([1; 32]);
1318 let addr2 = B256::from([2; 32]);
1319 let slot1 = B256::from([1; 32]);
1320 let slot2 = B256::from([2; 32]);
1321
1322 let state = HashedPostState {
1323 accounts: B256Map::from_iter([
1324 (addr1, Some(Default::default())),
1325 (addr2, Some(Default::default())),
1326 ]),
1327 storages: B256Map::from_iter([(
1328 addr2,
1329 HashedStorage {
1330 wiped: true,
1331 storage: B256Map::from_iter([(slot1, U256::ZERO), (slot2, U256::from(1))]),
1332 },
1333 )]),
1334 };
1335
1336 let mut chunks = state.chunks(2);
1337 assert_eq!(
1338 chunks.next(),
1339 Some(HashedPostState {
1340 accounts: B256Map::from_iter([(addr1, Some(Default::default()))]),
1341 storages: B256Map::from_iter([(addr2, HashedStorage::new(true)),])
1342 })
1343 );
1344 assert_eq!(
1345 chunks.next(),
1346 Some(HashedPostState {
1347 accounts: B256Map::default(),
1348 storages: B256Map::from_iter([(
1349 addr2,
1350 HashedStorage {
1351 wiped: false,
1352 storage: B256Map::from_iter([(slot1, U256::ZERO), (slot2, U256::from(1))]),
1353 },
1354 )])
1355 })
1356 );
1357 assert_eq!(
1358 chunks.next(),
1359 Some(HashedPostState {
1360 accounts: B256Map::from_iter([(addr2, Some(Default::default()))]),
1361 storages: B256Map::default()
1362 })
1363 );
1364 assert_eq!(chunks.next(), None);
1365 }
1366
1367 #[test]
1368 fn test_chunks_ordering_guarantee() {
1369 let addr = B256::from([1; 32]);
1372 let slot1 = B256::from([1; 32]);
1373 let slot2 = B256::from([2; 32]);
1374
1375 let state = HashedPostState {
1376 accounts: B256Map::from_iter([(addr, Some(Default::default()))]),
1377 storages: B256Map::from_iter([(
1378 addr,
1379 HashedStorage {
1380 wiped: true,
1381 storage: B256Map::from_iter([(slot1, U256::from(1)), (slot2, U256::from(2))]),
1382 },
1383 )]),
1384 };
1385
1386 let chunks: Vec<_> = state.chunks(1).collect();
1387
1388 assert_eq!(chunks.len(), 4);
1390
1391 assert!(chunks[0].accounts.is_empty());
1393 assert_eq!(chunks[0].storages.len(), 1);
1394 assert!(chunks[0].storages.get(&addr).unwrap().wiped);
1395 assert!(chunks[0].storages.get(&addr).unwrap().storage.is_empty());
1396
1397 assert!(chunks[1].accounts.is_empty());
1399 assert!(!chunks[1].storages.get(&addr).unwrap().wiped);
1400 assert_eq!(chunks[1].storages.get(&addr).unwrap().storage.len(), 1);
1401
1402 assert!(chunks[2].accounts.is_empty());
1403 assert!(!chunks[2].storages.get(&addr).unwrap().wiped);
1404 assert_eq!(chunks[2].storages.get(&addr).unwrap().storage.len(), 1);
1405
1406 assert_eq!(chunks[3].accounts.len(), 1);
1408 assert!(chunks[3].accounts.contains_key(&addr));
1409 assert!(chunks[3].storages.is_empty());
1410 }
1411
1412 #[test]
1413 fn test_hashed_post_state_sorted_extend_ref() {
1414 let mut state1 = HashedPostStateSorted {
1416 accounts: vec![
1417 (B256::from([1; 32]), Some(Account::default())),
1418 (B256::from([3; 32]), Some(Account::default())),
1419 (B256::from([5; 32]), None),
1420 ],
1421 storages: B256Map::default(),
1422 };
1423
1424 let state2 = HashedPostStateSorted {
1425 accounts: vec![
1426 (B256::from([2; 32]), Some(Account::default())),
1427 (B256::from([3; 32]), Some(Account { nonce: 1, ..Default::default() })), (B256::from([4; 32]), Some(Account::default())),
1429 (B256::from([6; 32]), None),
1430 ],
1431 storages: B256Map::default(),
1432 };
1433
1434 state1.extend_ref_and_sort(&state2);
1435
1436 assert_eq!(state1.accounts.len(), 6);
1438 assert_eq!(state1.accounts[0].0, B256::from([1; 32]));
1439 assert_eq!(state1.accounts[1].0, B256::from([2; 32]));
1440 assert_eq!(state1.accounts[2].0, B256::from([3; 32]));
1441 assert_eq!(state1.accounts[2].1.unwrap().nonce, 1); assert_eq!(state1.accounts[3].0, B256::from([4; 32]));
1443 assert_eq!(state1.accounts[4].0, B256::from([5; 32]));
1444 assert_eq!(state1.accounts[4].1, None);
1445 assert_eq!(state1.accounts[5].0, B256::from([6; 32]));
1446 assert_eq!(state1.accounts[5].1, None);
1447 }
1448
1449 #[test]
1450 fn test_hashed_storage_sorted_extend_ref() {
1451 let mut storage1 = HashedStorageSorted {
1453 storage_slots: vec![
1454 (B256::from([1; 32]), U256::from(10)),
1455 (B256::from([3; 32]), U256::from(30)),
1456 (B256::from([5; 32]), U256::ZERO),
1457 ],
1458 wiped: false,
1459 };
1460
1461 let storage2 = HashedStorageSorted {
1462 storage_slots: vec![
1463 (B256::from([2; 32]), U256::from(20)),
1464 (B256::from([3; 32]), U256::from(300)), (B256::from([4; 32]), U256::from(40)),
1466 (B256::from([6; 32]), U256::ZERO),
1467 ],
1468 wiped: false,
1469 };
1470
1471 storage1.extend_ref(&storage2);
1472
1473 assert_eq!(storage1.storage_slots.len(), 6);
1474 assert_eq!(storage1.storage_slots[0].0, B256::from([1; 32]));
1475 assert_eq!(storage1.storage_slots[0].1, U256::from(10));
1476 assert_eq!(storage1.storage_slots[1].0, B256::from([2; 32]));
1477 assert_eq!(storage1.storage_slots[1].1, U256::from(20));
1478 assert_eq!(storage1.storage_slots[2].0, B256::from([3; 32]));
1479 assert_eq!(storage1.storage_slots[2].1, U256::from(300)); assert_eq!(storage1.storage_slots[3].0, B256::from([4; 32]));
1481 assert_eq!(storage1.storage_slots[3].1, U256::from(40));
1482 assert_eq!(storage1.storage_slots[4].0, B256::from([5; 32]));
1483 assert_eq!(storage1.storage_slots[4].1, U256::ZERO);
1484 assert_eq!(storage1.storage_slots[5].0, B256::from([6; 32]));
1485 assert_eq!(storage1.storage_slots[5].1, U256::ZERO);
1486 assert!(!storage1.wiped);
1487
1488 let mut storage3 = HashedStorageSorted {
1490 storage_slots: vec![
1491 (B256::from([1; 32]), U256::from(10)),
1492 (B256::from([2; 32]), U256::ZERO),
1493 ],
1494 wiped: false,
1495 };
1496
1497 let storage4 = HashedStorageSorted {
1498 storage_slots: vec![
1499 (B256::from([3; 32]), U256::from(30)),
1500 (B256::from([4; 32]), U256::ZERO),
1501 ],
1502 wiped: true,
1503 };
1504
1505 storage3.extend_ref(&storage4);
1506
1507 assert!(storage3.wiped);
1508 assert_eq!(storage3.storage_slots.len(), 2);
1510 assert_eq!(storage3.storage_slots[0].0, B256::from([3; 32]));
1511 assert_eq!(storage3.storage_slots[0].1, U256::from(30));
1512 assert_eq!(storage3.storage_slots[1].0, B256::from([4; 32]));
1513 assert_eq!(storage3.storage_slots[1].1, U256::ZERO);
1514 }
1515
1516 #[test]
1518 fn test_hashed_post_state_extend_from_sorted_with_accounts() {
1519 let addr1 = B256::random();
1520 let addr2 = B256::random();
1521
1522 let mut state = HashedPostState::default();
1523 state.accounts.insert(addr1, Some(Default::default()));
1524
1525 let mut sorted_state = HashedPostStateSorted::default();
1526 sorted_state.accounts.push((addr2, Some(Default::default())));
1527
1528 state.extend_from_sorted(&sorted_state);
1529
1530 assert_eq!(state.accounts.len(), 2);
1531 assert!(state.accounts.contains_key(&addr1));
1532 assert!(state.accounts.contains_key(&addr2));
1533 }
1534
1535 #[test]
1537 fn test_hashed_post_state_extend_from_sorted_with_destroyed_accounts() {
1538 let addr1 = B256::random();
1539
1540 let mut state = HashedPostState::default();
1541
1542 let mut sorted_state = HashedPostStateSorted::default();
1543 sorted_state.accounts.push((addr1, None));
1544
1545 state.extend_from_sorted(&sorted_state);
1546
1547 assert!(state.accounts.contains_key(&addr1));
1548 assert_eq!(state.accounts.get(&addr1), Some(&None));
1549 }
1550
1551 #[test]
1553 fn test_hashed_storage_extend_from_sorted_non_wiped() {
1554 let slot1 = B256::random();
1555 let slot2 = B256::random();
1556 let slot3 = B256::random();
1557
1558 let mut storage = HashedStorage::from_iter(false, [(slot1, U256::from(100))]);
1559
1560 let sorted = HashedStorageSorted {
1561 storage_slots: vec![(slot2, U256::from(200)), (slot3, U256::ZERO)],
1562 wiped: false,
1563 };
1564
1565 storage.extend_from_sorted(&sorted);
1566
1567 assert!(!storage.wiped);
1568 assert_eq!(storage.storage.len(), 3);
1569 assert_eq!(storage.storage.get(&slot1), Some(&U256::from(100)));
1570 assert_eq!(storage.storage.get(&slot2), Some(&U256::from(200)));
1571 assert_eq!(storage.storage.get(&slot3), Some(&U256::ZERO));
1572 }
1573
1574 #[test]
1576 fn test_hashed_storage_extend_from_sorted_wiped() {
1577 let slot1 = B256::random();
1578 let slot2 = B256::random();
1579
1580 let mut storage = HashedStorage::from_iter(false, [(slot1, U256::from(100))]);
1581
1582 let sorted =
1583 HashedStorageSorted { storage_slots: vec![(slot2, U256::from(200))], wiped: true };
1584
1585 storage.extend_from_sorted(&sorted);
1586
1587 assert!(storage.wiped);
1588 assert_eq!(storage.storage.len(), 1);
1590 assert_eq!(storage.storage.get(&slot2), Some(&U256::from(200)));
1591 }
1592
1593 #[test]
1594 fn test_hashed_post_state_chunking_length() {
1595 let addr1 = B256::from([1; 32]);
1596 let addr2 = B256::from([2; 32]);
1597 let addr3 = B256::from([3; 32]);
1598 let addr4 = B256::from([4; 32]);
1599 let slot1 = B256::from([1; 32]);
1600 let slot2 = B256::from([2; 32]);
1601 let slot3 = B256::from([3; 32]);
1602
1603 let state = HashedPostState {
1604 accounts: B256Map::from_iter([(addr1, None), (addr2, None), (addr4, None)]),
1605 storages: B256Map::from_iter([
1606 (
1607 addr1,
1608 HashedStorage {
1609 wiped: false,
1610 storage: B256Map::from_iter([
1611 (slot1, U256::ZERO),
1612 (slot2, U256::ZERO),
1613 (slot3, U256::ZERO),
1614 ]),
1615 },
1616 ),
1617 (
1618 addr2,
1619 HashedStorage {
1620 wiped: true,
1621 storage: B256Map::from_iter([
1622 (slot1, U256::ZERO),
1623 (slot2, U256::ZERO),
1624 (slot3, U256::ZERO),
1625 ]),
1626 },
1627 ),
1628 (
1629 addr3,
1630 HashedStorage {
1631 wiped: false,
1632 storage: B256Map::from_iter([
1633 (slot1, U256::ZERO),
1634 (slot2, U256::ZERO),
1635 (slot3, U256::ZERO),
1636 ]),
1637 },
1638 ),
1639 ]),
1640 };
1641
1642 let chunking_length = state.chunking_length();
1643 for size in 1..=state.clone().chunks(1).count() {
1644 let chunk_count = state.clone().chunks(size).count();
1645 let expected_count = chunking_length.div_ceil(size);
1646 assert_eq!(
1647 chunk_count, expected_count,
1648 "chunking_length: {}, size: {}",
1649 chunking_length, size
1650 );
1651 }
1652 }
1653
1654 #[test]
1655 fn test_clone_into_sorted_equivalence() {
1656 let addr1 = B256::from([1; 32]);
1657 let addr2 = B256::from([2; 32]);
1658 let addr3 = B256::from([3; 32]);
1659 let slot1 = B256::from([1; 32]);
1660 let slot2 = B256::from([2; 32]);
1661 let slot3 = B256::from([3; 32]);
1662
1663 let state = HashedPostState {
1664 accounts: B256Map::from_iter([
1665 (addr1, Some(Account { nonce: 1, balance: U256::from(100), bytecode_hash: None })),
1666 (addr2, None),
1667 (addr3, Some(Account::default())),
1668 ]),
1669 storages: B256Map::from_iter([
1670 (
1671 addr1,
1672 HashedStorage {
1673 wiped: false,
1674 storage: B256Map::from_iter([
1675 (slot1, U256::from(10)),
1676 (slot2, U256::from(20)),
1677 ]),
1678 },
1679 ),
1680 (
1681 addr2,
1682 HashedStorage {
1683 wiped: true,
1684 storage: B256Map::from_iter([(slot3, U256::ZERO)]),
1685 },
1686 ),
1687 ]),
1688 };
1689
1690 let sorted_via_clone = state.clone().into_sorted();
1692 let sorted_via_clone_into = state.clone_into_sorted();
1693
1694 assert_eq!(sorted_via_clone, sorted_via_clone_into);
1695
1696 assert_eq!(state.accounts.len(), 3);
1698 assert_eq!(state.storages.len(), 2);
1699 }
1700
1701 #[test]
1702 fn test_hashed_storage_clone_into_sorted_equivalence() {
1703 let slot1 = B256::from([1; 32]);
1704 let slot2 = B256::from([2; 32]);
1705 let slot3 = B256::from([3; 32]);
1706
1707 let storage = HashedStorage {
1708 wiped: true,
1709 storage: B256Map::from_iter([
1710 (slot1, U256::from(100)),
1711 (slot2, U256::ZERO),
1712 (slot3, U256::from(300)),
1713 ]),
1714 };
1715
1716 let sorted_via_clone = storage.clone().into_sorted();
1718 let sorted_via_clone_into = storage.clone_into_sorted();
1719
1720 assert_eq!(sorted_via_clone, sorted_via_clone_into);
1721
1722 assert_eq!(storage.storage.len(), 3);
1724 assert!(storage.wiped);
1725 }
1726}
1727
1728#[cfg(feature = "serde-bincode-compat")]
1730pub mod serde_bincode_compat {
1731 use super::Account;
1732 use alloc::borrow::Cow;
1733 use alloy_primitives::{map::B256Map, B256, U256};
1734 use serde::{Deserialize, Deserializer, Serialize, Serializer};
1735 use serde_with::{DeserializeAs, SerializeAs};
1736
1737 #[derive(Debug, Serialize, Deserialize)]
1753 pub struct HashedPostState<'a> {
1754 accounts: Cow<'a, B256Map<Option<Account>>>,
1755 storages: B256Map<HashedStorage<'a>>,
1756 }
1757
1758 impl<'a> From<&'a super::HashedPostState> for HashedPostState<'a> {
1759 fn from(value: &'a super::HashedPostState) -> Self {
1760 Self {
1761 accounts: Cow::Borrowed(&value.accounts),
1762 storages: value.storages.iter().map(|(k, v)| (*k, v.into())).collect(),
1763 }
1764 }
1765 }
1766
1767 impl<'a> From<HashedPostState<'a>> for super::HashedPostState {
1768 fn from(value: HashedPostState<'a>) -> Self {
1769 Self {
1770 accounts: value.accounts.into_owned(),
1771 storages: value.storages.into_iter().map(|(k, v)| (k, v.into())).collect(),
1772 }
1773 }
1774 }
1775
1776 impl SerializeAs<super::HashedPostState> for HashedPostState<'_> {
1777 fn serialize_as<S>(
1778 source: &super::HashedPostState,
1779 serializer: S,
1780 ) -> Result<S::Ok, S::Error>
1781 where
1782 S: Serializer,
1783 {
1784 HashedPostState::from(source).serialize(serializer)
1785 }
1786 }
1787
1788 impl<'de> DeserializeAs<'de, super::HashedPostState> for HashedPostState<'de> {
1789 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedPostState, D::Error>
1790 where
1791 D: Deserializer<'de>,
1792 {
1793 HashedPostState::deserialize(deserializer).map(Into::into)
1794 }
1795 }
1796
1797 #[derive(Debug, Serialize, Deserialize)]
1813 pub struct HashedStorage<'a> {
1814 wiped: bool,
1815 storage: Cow<'a, B256Map<U256>>,
1816 }
1817
1818 impl<'a> From<&'a super::HashedStorage> for HashedStorage<'a> {
1819 fn from(value: &'a super::HashedStorage) -> Self {
1820 Self { wiped: value.wiped, storage: Cow::Borrowed(&value.storage) }
1821 }
1822 }
1823
1824 impl<'a> From<HashedStorage<'a>> for super::HashedStorage {
1825 fn from(value: HashedStorage<'a>) -> Self {
1826 Self { wiped: value.wiped, storage: value.storage.into_owned() }
1827 }
1828 }
1829
1830 impl SerializeAs<super::HashedStorage> for HashedStorage<'_> {
1831 fn serialize_as<S>(source: &super::HashedStorage, serializer: S) -> Result<S::Ok, S::Error>
1832 where
1833 S: Serializer,
1834 {
1835 HashedStorage::from(source).serialize(serializer)
1836 }
1837 }
1838
1839 impl<'de> DeserializeAs<'de, super::HashedStorage> for HashedStorage<'de> {
1840 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedStorage, D::Error>
1841 where
1842 D: Deserializer<'de>,
1843 {
1844 HashedStorage::deserialize(deserializer).map(Into::into)
1845 }
1846 }
1847
1848 #[derive(Debug, Serialize, Deserialize)]
1864 pub struct HashedPostStateSorted<'a> {
1865 accounts: Cow<'a, [(B256, Option<Account>)]>,
1866 storages: B256Map<HashedStorageSorted<'a>>,
1867 }
1868
1869 impl<'a> From<&'a super::HashedPostStateSorted> for HashedPostStateSorted<'a> {
1870 fn from(value: &'a super::HashedPostStateSorted) -> Self {
1871 Self {
1872 accounts: Cow::Borrowed(&value.accounts),
1873 storages: value.storages.iter().map(|(k, v)| (*k, v.into())).collect(),
1874 }
1875 }
1876 }
1877
1878 impl<'a> From<HashedPostStateSorted<'a>> for super::HashedPostStateSorted {
1879 fn from(value: HashedPostStateSorted<'a>) -> Self {
1880 Self {
1881 accounts: value.accounts.into_owned(),
1882 storages: value.storages.into_iter().map(|(k, v)| (k, v.into())).collect(),
1883 }
1884 }
1885 }
1886
1887 impl SerializeAs<super::HashedPostStateSorted> for HashedPostStateSorted<'_> {
1888 fn serialize_as<S>(
1889 source: &super::HashedPostStateSorted,
1890 serializer: S,
1891 ) -> Result<S::Ok, S::Error>
1892 where
1893 S: Serializer,
1894 {
1895 HashedPostStateSorted::from(source).serialize(serializer)
1896 }
1897 }
1898
1899 impl<'de> DeserializeAs<'de, super::HashedPostStateSorted> for HashedPostStateSorted<'de> {
1900 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedPostStateSorted, D::Error>
1901 where
1902 D: Deserializer<'de>,
1903 {
1904 HashedPostStateSorted::deserialize(deserializer).map(Into::into)
1905 }
1906 }
1907
1908 #[derive(Debug, Serialize, Deserialize)]
1924 pub struct HashedStorageSorted<'a> {
1925 storage_slots: Cow<'a, [(B256, U256)]>,
1926 wiped: bool,
1927 }
1928
1929 impl<'a> From<&'a super::HashedStorageSorted> for HashedStorageSorted<'a> {
1930 fn from(value: &'a super::HashedStorageSorted) -> Self {
1931 Self { storage_slots: Cow::Borrowed(&value.storage_slots), wiped: value.wiped }
1932 }
1933 }
1934
1935 impl<'a> From<HashedStorageSorted<'a>> for super::HashedStorageSorted {
1936 fn from(value: HashedStorageSorted<'a>) -> Self {
1937 Self { storage_slots: value.storage_slots.into_owned(), wiped: value.wiped }
1938 }
1939 }
1940
1941 impl SerializeAs<super::HashedStorageSorted> for HashedStorageSorted<'_> {
1942 fn serialize_as<S>(
1943 source: &super::HashedStorageSorted,
1944 serializer: S,
1945 ) -> Result<S::Ok, S::Error>
1946 where
1947 S: Serializer,
1948 {
1949 HashedStorageSorted::from(source).serialize(serializer)
1950 }
1951 }
1952
1953 impl<'de> DeserializeAs<'de, super::HashedStorageSorted> for HashedStorageSorted<'de> {
1954 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedStorageSorted, D::Error>
1955 where
1956 D: Deserializer<'de>,
1957 {
1958 HashedStorageSorted::deserialize(deserializer).map(Into::into)
1959 }
1960 }
1961
1962 #[cfg(test)]
1963 mod tests {
1964 use crate::{
1965 hashed_state::{
1966 HashedPostState, HashedPostStateSorted, HashedStorage, HashedStorageSorted,
1967 },
1968 serde_bincode_compat,
1969 };
1970 use alloy_primitives::{B256, U256};
1971 use reth_primitives_traits::Account;
1972 use serde::{Deserialize, Serialize};
1973 use serde_with::serde_as;
1974
1975 #[test]
1976 fn test_hashed_post_state_bincode_roundtrip() {
1977 #[serde_as]
1978 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
1979 struct Data {
1980 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedPostState")]
1981 hashed_state: HashedPostState,
1982 }
1983
1984 let mut data = Data { hashed_state: HashedPostState::default() };
1985 let encoded = bincode::serialize(&data).unwrap();
1986 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1987 assert_eq!(decoded, data);
1988
1989 data.hashed_state.accounts.insert(B256::random(), Some(Account::default()));
1990 let encoded = bincode::serialize(&data).unwrap();
1991 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1992 assert_eq!(decoded, data);
1993
1994 data.hashed_state.storages.insert(B256::random(), HashedStorage::default());
1995 let encoded = bincode::serialize(&data).unwrap();
1996 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1997 assert_eq!(decoded, data);
1998 }
1999
2000 #[test]
2001 fn test_hashed_storage_bincode_roundtrip() {
2002 #[serde_as]
2003 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
2004 struct Data {
2005 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedStorage")]
2006 hashed_storage: HashedStorage,
2007 }
2008
2009 let mut data = Data { hashed_storage: HashedStorage::default() };
2010 let encoded = bincode::serialize(&data).unwrap();
2011 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2012 assert_eq!(decoded, data);
2013
2014 data.hashed_storage.wiped = true;
2015 let encoded = bincode::serialize(&data).unwrap();
2016 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2017 assert_eq!(decoded, data);
2018
2019 data.hashed_storage.storage.insert(B256::random(), U256::from(1));
2020 let encoded = bincode::serialize(&data).unwrap();
2021 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2022 assert_eq!(decoded, data);
2023 }
2024
2025 #[test]
2026 fn test_hashed_post_state_sorted_bincode_roundtrip() {
2027 #[serde_as]
2028 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
2029 struct Data {
2030 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedPostStateSorted")]
2031 hashed_state: HashedPostStateSorted,
2032 }
2033
2034 let mut data = Data { hashed_state: HashedPostStateSorted::default() };
2035 let encoded = bincode::serialize(&data).unwrap();
2036 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2037 assert_eq!(decoded, data);
2038
2039 data.hashed_state.accounts.push((B256::random(), Some(Account::default())));
2040 data.hashed_state
2041 .accounts
2042 .push((B256::random(), Some(Account { nonce: 1, ..Default::default() })));
2043 let encoded = bincode::serialize(&data).unwrap();
2044 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2045 assert_eq!(decoded, data);
2046
2047 data.hashed_state.storages.insert(
2048 B256::random(),
2049 HashedStorageSorted {
2050 storage_slots: vec![(B256::from([1; 32]), U256::from(10))],
2051 wiped: false,
2052 },
2053 );
2054 let encoded = bincode::serialize(&data).unwrap();
2055 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2056 assert_eq!(decoded, data);
2057 }
2058
2059 #[test]
2060 fn test_hashed_storage_sorted_bincode_roundtrip() {
2061 #[serde_as]
2062 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
2063 struct Data {
2064 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedStorageSorted")]
2065 hashed_storage: HashedStorageSorted,
2066 }
2067
2068 let mut data = Data {
2069 hashed_storage: HashedStorageSorted { storage_slots: Vec::new(), wiped: false },
2070 };
2071 let encoded = bincode::serialize(&data).unwrap();
2072 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2073 assert_eq!(decoded, data);
2074
2075 data.hashed_storage.wiped = true;
2076 let encoded = bincode::serialize(&data).unwrap();
2077 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2078 assert_eq!(decoded, data);
2079
2080 data.hashed_storage.storage_slots.push((B256::random(), U256::from(1)));
2081 let encoded = bincode::serialize(&data).unwrap();
2082 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2083 assert_eq!(decoded, data);
2084 }
2085 }
2086}