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 pub fn from_bundle_state<'a, KH: KeyHasher>(
50 state: impl IntoIterator<Item = (&'a Address, &'a BundleAccount)>,
51 ) -> Self {
52 state
53 .into_iter()
54 .map(|(address, account)| {
55 let hashed_address = KH::hash_key(address);
56 let hashed_account = account.info.as_ref().map(Into::into);
57 let hashed_storage = HashedStorage::from_plain_storage(
58 account.status,
59 account.storage.iter().map(|(slot, value)| (slot, &value.present_value)),
60 );
61
62 (
63 hashed_address,
64 hashed_account,
65 (!hashed_storage.is_empty()).then_some(hashed_storage),
66 )
67 })
68 .collect()
69 }
70
71 pub fn from_hashed_storage(hashed_address: B256, storage: HashedStorage) -> Self {
73 Self {
74 accounts: HashMap::default(),
75 storages: HashMap::from_iter([(hashed_address, storage)]),
76 }
77 }
78
79 pub fn with_accounts(
81 mut self,
82 accounts: impl IntoIterator<Item = (B256, Option<Account>)>,
83 ) -> Self {
84 self.accounts = HashMap::from_iter(accounts);
85 self
86 }
87
88 pub fn with_storages(
90 mut self,
91 storages: impl IntoIterator<Item = (B256, HashedStorage)>,
92 ) -> Self {
93 self.storages = HashMap::from_iter(storages);
94 self
95 }
96
97 pub fn is_empty(&self) -> bool {
99 self.accounts.is_empty() && self.storages.is_empty()
100 }
101
102 pub fn construct_prefix_sets(&self) -> TriePrefixSetsMut {
106 let mut account_prefix_set = PrefixSetMut::with_capacity(self.accounts.len());
108 let mut destroyed_accounts = HashSet::default();
109 for (hashed_address, account) in &self.accounts {
110 account_prefix_set.insert(Nibbles::unpack(hashed_address));
111
112 if account.is_none() {
113 destroyed_accounts.insert(*hashed_address);
114 }
115 }
116
117 let mut storage_prefix_sets =
119 HashMap::with_capacity_and_hasher(self.storages.len(), Default::default());
120 for (hashed_address, hashed_storage) in &self.storages {
121 account_prefix_set.insert(Nibbles::unpack(hashed_address));
122 storage_prefix_sets.insert(*hashed_address, hashed_storage.construct_prefix_set());
123 }
124
125 TriePrefixSetsMut { account_prefix_set, storage_prefix_sets, destroyed_accounts }
126 }
127
128 pub fn multi_proof_targets(&self) -> MultiProofTargets {
130 let mut targets = MultiProofTargets::with_capacity(self.accounts.len());
132 for hashed_address in self.accounts.keys() {
133 targets.insert(*hashed_address, Default::default());
134 }
135 for (hashed_address, storage) in &self.storages {
136 targets.entry(*hashed_address).or_default().extend(storage.storage.keys().copied());
137 }
138 targets
139 }
140
141 pub fn multi_proof_targets_difference(
147 &self,
148 excluded: &MultiProofTargets,
149 ) -> MultiProofTargets {
150 let mut targets = MultiProofTargets::default();
151 for hashed_address in self.accounts.keys() {
152 if !excluded.contains_key(hashed_address) {
153 targets.insert(*hashed_address, Default::default());
154 }
155 }
156 for (hashed_address, storage) in &self.storages {
157 let maybe_excluded_storage = excluded.get(hashed_address);
158 let mut hashed_slots_targets = storage
159 .storage
160 .keys()
161 .filter(|slot| !maybe_excluded_storage.is_some_and(|f| f.contains(*slot)))
162 .peekable();
163 if hashed_slots_targets.peek().is_some() {
164 targets.entry(*hashed_address).or_default().extend(hashed_slots_targets);
165 }
166 }
167 targets
168 }
169
170 pub fn partition_by_targets(
177 mut self,
178 targets: &MultiProofTargets,
179 added_removed_keys: &MultiAddedRemovedKeys,
180 ) -> (Self, Self) {
181 let mut state_updates_not_in_targets = Self::default();
182
183 self.storages.retain(|&address, storage| {
184 let storage_added_removed_keys = added_removed_keys.get_storage(&address);
185
186 let (retain, storage_not_in_targets) = match targets.get(&address) {
187 Some(storage_in_targets) => {
188 let mut storage_not_in_targets = HashedStorage::default();
189 storage.storage.retain(|&slot, value| {
190 if storage_in_targets.contains(&slot) &&
191 !storage_added_removed_keys.is_some_and(|k| k.is_removed(&slot))
192 {
193 return true
194 }
195
196 storage_not_in_targets.storage.insert(slot, *value);
197 false
198 });
199
200 let retain = !storage.storage.is_empty();
204
205 if !retain {
209 storage_not_in_targets.wiped = storage.wiped;
210 }
211
212 (
213 retain,
214 storage_not_in_targets.is_empty().not().then_some(storage_not_in_targets),
215 )
216 }
217 None => (false, Some(core::mem::take(storage))),
218 };
219
220 if let Some(storage_not_in_targets) = storage_not_in_targets {
221 state_updates_not_in_targets.storages.insert(address, storage_not_in_targets);
222 }
223
224 retain
225 });
226 self.accounts.retain(|&address, account| {
227 if targets.contains_key(&address) {
228 return true
229 }
230
231 state_updates_not_in_targets.accounts.insert(address, *account);
232 false
233 });
234
235 (self, state_updates_not_in_targets)
236 }
237
238 pub fn chunks(self, size: usize) -> ChunkedHashedPostState {
242 ChunkedHashedPostState::new(self, size)
243 }
244
245 pub fn chunking_length(&self) -> usize {
247 self.accounts.len() +
248 self.storages
249 .values()
250 .map(|storage| if storage.wiped { 1 } else { 0 } + storage.storage.len())
251 .sum::<usize>()
252 }
253
254 pub fn extend(&mut self, other: Self) {
257 self.extend_inner(Cow::Owned(other));
258 }
259
260 pub fn extend_ref(&mut self, other: &Self) {
265 self.extend_inner(Cow::Borrowed(other));
266 }
267
268 fn extend_inner(&mut self, other: Cow<'_, Self>) {
269 self.accounts.extend(other.accounts.iter().map(|(&k, &v)| (k, v)));
270
271 self.storages.reserve(other.storages.len());
272 match other {
273 Cow::Borrowed(other) => {
274 self.extend_storages(other.storages.iter().map(|(k, v)| (*k, Cow::Borrowed(v))))
275 }
276 Cow::Owned(other) => {
277 self.extend_storages(other.storages.into_iter().map(|(k, v)| (k, Cow::Owned(v))))
278 }
279 }
280 }
281
282 fn extend_storages<'a>(
283 &mut self,
284 storages: impl IntoIterator<Item = (B256, Cow<'a, HashedStorage>)>,
285 ) {
286 for (hashed_address, storage) in storages {
287 match self.storages.entry(hashed_address) {
288 hash_map::Entry::Vacant(entry) => {
289 entry.insert(storage.into_owned());
290 }
291 hash_map::Entry::Occupied(mut entry) => {
292 entry.get_mut().extend(&storage);
293 }
294 }
295 }
296 }
297
298 pub fn extend_from_sorted(&mut self, sorted: &HashedPostStateSorted) {
302 self.accounts.reserve(sorted.accounts.len());
304
305 for (address, account) in &sorted.accounts {
307 self.accounts.insert(*address, *account);
308 }
309
310 self.storages.reserve(sorted.storages.len());
312
313 for (hashed_address, sorted_storage) in &sorted.storages {
315 match self.storages.entry(*hashed_address) {
316 hash_map::Entry::Vacant(entry) => {
317 let mut new_storage = HashedStorage::new(false);
318 new_storage.extend_from_sorted(sorted_storage);
319 entry.insert(new_storage);
320 }
321 hash_map::Entry::Occupied(mut entry) => {
322 entry.get_mut().extend_from_sorted(sorted_storage);
323 }
324 }
325 }
326 }
327
328 pub fn into_sorted(self) -> HashedPostStateSorted {
330 let mut accounts: Vec<_> = self.accounts.into_iter().collect();
331 accounts.sort_unstable_by_key(|(address, _)| *address);
332
333 let storages = self
334 .storages
335 .into_iter()
336 .map(|(hashed_address, storage)| (hashed_address, storage.into_sorted()))
337 .collect();
338
339 HashedPostStateSorted { accounts, storages }
340 }
341
342 pub fn clone_into_sorted(&self) -> HashedPostStateSorted {
345 let mut accounts: Vec<_> = self.accounts.iter().map(|(&k, &v)| (k, v)).collect();
346 accounts.sort_unstable_by_key(|(address, _)| *address);
347
348 let storages = self
349 .storages
350 .iter()
351 .map(|(&hashed_address, storage)| (hashed_address, storage.clone_into_sorted()))
352 .collect();
353
354 HashedPostStateSorted { accounts, storages }
355 }
356
357 pub fn clear(&mut self) {
359 self.accounts.clear();
360 self.storages.clear();
361 }
362}
363
364impl FromIterator<(B256, Option<Account>, Option<HashedStorage>)> for HashedPostState {
365 fn from_iter<T: IntoIterator<Item = (B256, Option<Account>, Option<HashedStorage>)>>(
381 iter: T,
382 ) -> Self {
383 let iter = iter.into_iter();
384 let (lower, _) = iter.size_hint();
385 let mut hashed_state = Self::with_capacity(lower);
386
387 for (hashed_address, info, hashed_storage) in iter {
388 hashed_state.accounts.insert(hashed_address, info);
389 if let Some(storage) = hashed_storage {
390 hashed_state.storages.insert(hashed_address, storage);
391 }
392 }
393
394 hashed_state
395 }
396}
397
398#[cfg(feature = "rayon")]
399impl FromParallelIterator<(B256, Option<Account>, Option<HashedStorage>)> for HashedPostState {
400 fn from_par_iter<I>(par_iter: I) -> Self
412 where
413 I: IntoParallelIterator<Item = (B256, Option<Account>, Option<HashedStorage>)>,
414 {
415 let vec: Vec<_> = par_iter.into_par_iter().collect();
416 vec.into_iter().collect()
417 }
418}
419
420#[derive(PartialEq, Eq, Clone, Debug, Default)]
422#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
423pub struct HashedStorage {
424 pub wiped: bool,
426 pub storage: B256Map<U256>,
428}
429
430impl HashedStorage {
431 pub fn new(wiped: bool) -> Self {
433 Self { wiped, storage: HashMap::default() }
434 }
435
436 pub fn is_empty(&self) -> bool {
438 !self.wiped && self.storage.is_empty()
439 }
440
441 pub fn from_iter(wiped: bool, iter: impl IntoIterator<Item = (B256, U256)>) -> Self {
443 Self { wiped, storage: HashMap::from_iter(iter) }
444 }
445
446 pub fn from_plain_storage<'a>(
448 status: AccountStatus,
449 storage: impl IntoIterator<Item = (&'a U256, &'a U256)>,
450 ) -> Self {
451 Self::from_iter(
452 status.was_destroyed(),
453 storage.into_iter().map(|(key, value)| (keccak256(B256::from(*key)), *value)),
454 )
455 }
456
457 pub fn construct_prefix_set(&self) -> PrefixSetMut {
459 if self.wiped {
460 PrefixSetMut::all()
461 } else {
462 let mut prefix_set = PrefixSetMut::with_capacity(self.storage.len());
463 for hashed_slot in self.storage.keys() {
464 prefix_set.insert(Nibbles::unpack(hashed_slot));
465 }
466 prefix_set
467 }
468 }
469
470 pub fn extend(&mut self, other: &Self) {
473 if other.wiped {
474 self.wiped = true;
475 self.storage.clear();
476 }
477 self.storage.extend(other.storage.iter().map(|(&k, &v)| (k, v)));
478 }
479
480 pub fn extend_from_sorted(&mut self, sorted: &HashedStorageSorted) {
484 if sorted.wiped {
485 self.wiped = true;
486 self.storage.clear();
487 }
488
489 self.storage.reserve(sorted.storage_slots.len());
491
492 for (slot, value) in &sorted.storage_slots {
494 self.storage.insert(*slot, *value);
495 }
496 }
497
498 pub fn into_sorted(self) -> HashedStorageSorted {
500 let mut storage_slots: Vec<_> = self.storage.into_iter().collect();
501 storage_slots.sort_unstable_by_key(|(key, _)| *key);
502
503 HashedStorageSorted { storage_slots, wiped: self.wiped }
504 }
505
506 pub fn clone_into_sorted(&self) -> HashedStorageSorted {
509 let mut storage_slots: Vec<_> = self.storage.iter().map(|(&k, &v)| (k, v)).collect();
510 storage_slots.sort_unstable_by_key(|(key, _)| *key);
511
512 HashedStorageSorted { storage_slots, wiped: self.wiped }
513 }
514}
515
516#[derive(PartialEq, Eq, Clone, Default, Debug)]
518#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
519pub struct HashedPostStateSorted {
520 pub accounts: Vec<(B256, Option<Account>)>,
522 pub storages: B256Map<HashedStorageSorted>,
524}
525
526impl HashedPostStateSorted {
527 pub const fn new(
529 accounts: Vec<(B256, Option<Account>)>,
530 storages: B256Map<HashedStorageSorted>,
531 ) -> Self {
532 Self { accounts, storages }
533 }
534
535 pub const fn accounts(&self) -> &Vec<(B256, Option<Account>)> {
537 &self.accounts
538 }
539
540 pub const fn account_storages(&self) -> &B256Map<HashedStorageSorted> {
542 &self.storages
543 }
544
545 pub fn is_empty(&self) -> bool {
547 self.accounts.is_empty() && self.storages.is_empty()
548 }
549
550 pub fn total_len(&self) -> usize {
552 self.accounts.len() + self.storages.values().map(|s| s.len()).sum::<usize>()
553 }
554
555 pub fn construct_prefix_sets(&self) -> TriePrefixSetsMut {
560 let mut account_prefix_set = PrefixSetMut::with_capacity(self.accounts.len());
561 let mut destroyed_accounts = HashSet::default();
562 for (hashed_address, account) in &self.accounts {
563 account_prefix_set.insert(Nibbles::unpack(hashed_address));
564 if account.is_none() {
565 destroyed_accounts.insert(*hashed_address);
566 }
567 }
568
569 let mut storage_prefix_sets =
570 B256Map::with_capacity_and_hasher(self.storages.len(), Default::default());
571 for (hashed_address, hashed_storage) in &self.storages {
572 account_prefix_set.insert(Nibbles::unpack(hashed_address));
574
575 let prefix_set = if hashed_storage.wiped {
576 PrefixSetMut::all()
577 } else {
578 let mut prefix_set =
579 PrefixSetMut::with_capacity(hashed_storage.storage_slots.len());
580 prefix_set.extend_keys(
581 hashed_storage
582 .storage_slots
583 .iter()
584 .map(|(hashed_slot, _)| Nibbles::unpack(hashed_slot)),
585 );
586 prefix_set
587 };
588
589 storage_prefix_sets.insert(*hashed_address, prefix_set);
590 }
591
592 TriePrefixSetsMut { account_prefix_set, storage_prefix_sets, destroyed_accounts }
593 }
594
595 pub fn extend_ref_and_sort(&mut self, other: &Self) {
600 extend_sorted_vec(&mut self.accounts, &other.accounts);
602
603 for (hashed_address, other_storage) in &other.storages {
605 self.storages
606 .entry(*hashed_address)
607 .and_modify(|existing| existing.extend_ref(other_storage))
608 .or_insert_with(|| other_storage.clone());
609 }
610 }
611
612 pub fn merge_batch<T: AsRef<Self> + From<Self>>(iter: impl IntoIterator<Item = T>) -> T {
617 let items: alloc::vec::Vec<_> = iter.into_iter().collect();
618 match items.len() {
619 0 => Self::default().into(),
620 1 => items.into_iter().next().expect("len == 1"),
621 _ => Self::merge_slice(&items).into(),
622 }
623 }
624
625 pub fn merge_slice<T: AsRef<Self>>(items: &[T]) -> Self {
631 const THRESHOLD: usize = 30;
632
633 let k = items.len();
634
635 if k == 0 {
636 return Self::default();
637 }
638 if k == 1 {
639 return items[0].as_ref().clone();
640 }
641
642 if k < THRESHOLD {
643 let mut iter = items.iter().rev();
645 let mut acc = iter.next().expect("k > 0").as_ref().clone();
646 for next in iter {
647 acc.extend_ref_and_sort(next.as_ref());
648 }
649 return acc;
650 }
651
652 let accounts = kway_merge_sorted(items.iter().map(|i| i.as_ref().accounts.as_slice()));
654
655 struct StorageAcc<'a> {
656 wiped: bool,
657 sealed: bool,
658 slices: Vec<&'a [(B256, U256)]>,
659 }
660
661 let mut acc: B256Map<StorageAcc<'_>> = B256Map::default();
662
663 for item in items {
664 for (addr, storage) in &item.as_ref().storages {
665 let entry = acc.entry(*addr).or_insert_with(|| StorageAcc {
666 wiped: false,
667 sealed: false,
668 slices: Vec::new(),
669 });
670
671 if entry.sealed {
672 continue;
673 }
674
675 entry.slices.push(storage.storage_slots.as_slice());
676 if storage.wiped {
677 entry.wiped = true;
678 entry.sealed = true;
679 }
680 }
681 }
682
683 let storages = acc
684 .into_iter()
685 .map(|(addr, entry)| {
686 let storage_slots = kway_merge_sorted(entry.slices);
687 (addr, HashedStorageSorted { wiped: entry.wiped, storage_slots })
688 })
689 .collect();
690
691 Self { accounts, storages }
692 }
693
694 pub fn clear(&mut self) {
696 self.accounts.clear();
697 self.storages.clear();
698 }
699}
700
701impl AsRef<Self> for HashedPostStateSorted {
702 fn as_ref(&self) -> &Self {
703 self
704 }
705}
706
707#[derive(Clone, Eq, PartialEq, Debug, Default)]
709#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
710pub struct HashedStorageSorted {
711 pub storage_slots: Vec<(B256, U256)>,
713 pub wiped: bool,
715}
716
717impl HashedStorageSorted {
718 pub const fn is_wiped(&self) -> bool {
720 self.wiped
721 }
722
723 pub fn storage_slots_ref(&self) -> &[(B256, U256)] {
725 &self.storage_slots
726 }
727
728 pub const fn len(&self) -> usize {
730 self.storage_slots.len()
731 }
732
733 pub const fn is_empty(&self) -> bool {
735 self.storage_slots.is_empty()
736 }
737
738 pub fn extend_ref(&mut self, other: &Self) {
743 if other.wiped {
744 self.wiped = true;
746 self.storage_slots.clear();
747 self.storage_slots.extend(other.storage_slots.iter().copied());
748 return;
749 }
750
751 extend_sorted_vec(&mut self.storage_slots, &other.storage_slots);
753 }
754
755 pub fn merge_batch<'a>(updates: impl IntoIterator<Item = &'a Self>) -> Self {
758 let updates: Vec<_> = updates.into_iter().collect();
759 if updates.is_empty() {
760 return Self::default();
761 }
762
763 let wipe_idx = updates.iter().position(|u| u.wiped);
764 let relevant = wipe_idx.map_or(&updates[..], |idx| &updates[..=idx]);
765 let storage_slots = kway_merge_sorted(relevant.iter().map(|u| u.storage_slots.as_slice()));
766
767 Self { wiped: wipe_idx.is_some(), storage_slots }
768 }
769}
770
771impl From<HashedStorageSorted> for HashedStorage {
772 fn from(sorted: HashedStorageSorted) -> Self {
773 let mut storage = B256Map::default();
774
775 for (slot, value) in sorted.storage_slots {
777 storage.insert(slot, value);
778 }
779
780 Self { wiped: sorted.wiped, storage }
781 }
782}
783
784impl From<HashedPostStateSorted> for HashedPostState {
785 fn from(sorted: HashedPostStateSorted) -> Self {
786 let mut accounts =
787 B256Map::with_capacity_and_hasher(sorted.accounts.len(), Default::default());
788
789 for (address, account) in sorted.accounts {
791 accounts.insert(address, account);
792 }
793
794 let storages = sorted
796 .storages
797 .into_iter()
798 .map(|(address, storage)| (address, storage.into()))
799 .collect();
800
801 Self { accounts, storages }
802 }
803}
804
805#[derive(Debug)]
813pub struct ChunkedHashedPostState {
814 flattened: alloc::vec::IntoIter<(B256, FlattenedHashedPostStateItem)>,
815 size: usize,
816}
817
818#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
821enum FlattenedStateOrder {
822 StorageWipe,
823 StorageUpdate(B256),
824 Account,
825}
826
827#[derive(Debug)]
828enum FlattenedHashedPostStateItem {
829 Account(Option<Account>),
830 StorageWipe,
831 StorageUpdate { slot: B256, value: U256 },
832}
833
834impl FlattenedHashedPostStateItem {
835 const fn order(&self) -> FlattenedStateOrder {
836 match self {
837 Self::StorageWipe => FlattenedStateOrder::StorageWipe,
838 Self::StorageUpdate { slot, .. } => FlattenedStateOrder::StorageUpdate(*slot),
839 Self::Account(_) => FlattenedStateOrder::Account,
840 }
841 }
842}
843
844impl ChunkedHashedPostState {
845 fn new(hashed_post_state: HashedPostState, size: usize) -> Self {
846 let flattened = hashed_post_state
847 .storages
848 .into_iter()
849 .flat_map(|(address, storage)| {
850 storage
851 .wiped
852 .then_some((address, FlattenedHashedPostStateItem::StorageWipe))
853 .into_iter()
854 .chain(storage.storage.into_iter().map(move |(slot, value)| {
855 (address, FlattenedHashedPostStateItem::StorageUpdate { slot, value })
856 }))
857 })
858 .chain(hashed_post_state.accounts.into_iter().map(|(address, account)| {
859 (address, FlattenedHashedPostStateItem::Account(account))
860 }))
861 .sorted_unstable_by_key(|(address, item)| (*address, item.order()));
866
867 Self { flattened, size }
868 }
869}
870
871impl Iterator for ChunkedHashedPostState {
872 type Item = HashedPostState;
873
874 fn next(&mut self) -> Option<Self::Item> {
875 let mut chunk = HashedPostState::default();
876
877 let mut current_size = 0;
878 while current_size < self.size {
879 let Some((address, item)) = self.flattened.next() else { break };
880
881 match item {
882 FlattenedHashedPostStateItem::Account(account) => {
883 chunk.accounts.insert(address, account);
884 }
885 FlattenedHashedPostStateItem::StorageWipe => {
886 chunk.storages.entry(address).or_default().wiped = true;
887 }
888 FlattenedHashedPostStateItem::StorageUpdate { slot, value } => {
889 chunk.storages.entry(address).or_default().storage.insert(slot, value);
890 }
891 }
892
893 current_size += 1;
894 }
895
896 if chunk.is_empty() {
897 None
898 } else {
899 Some(chunk)
900 }
901 }
902}
903
904#[cfg(test)]
905mod tests {
906 use super::*;
907 use crate::KeccakKeyHasher;
908 use alloy_primitives::Bytes;
909 use revm_database::{states::StorageSlot, StorageWithOriginalValues};
910 use revm_state::{AccountInfo, Bytecode};
911
912 #[test]
913 fn hashed_state_wiped_extension() {
914 let hashed_address = B256::default();
915 let hashed_slot = B256::with_last_byte(64);
916 let hashed_slot2 = B256::with_last_byte(65);
917
918 let original_slot_value = U256::from(123);
920 let mut hashed_state = HashedPostState::default().with_storages([(
921 hashed_address,
922 HashedStorage::from_iter(
923 false,
924 [(hashed_slot, original_slot_value), (hashed_slot2, original_slot_value)],
925 ),
926 )]);
927
928 let updated_slot_value = U256::from(321);
930 let extension = HashedPostState::default().with_storages([(
931 hashed_address,
932 HashedStorage::from_iter(false, [(hashed_slot, updated_slot_value)]),
933 )]);
934 hashed_state.extend(extension);
935
936 let account_storage = hashed_state.storages.get(&hashed_address);
937 assert_eq!(
938 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
939 Some(&updated_slot_value)
940 );
941 assert_eq!(
942 account_storage.and_then(|st| st.storage.get(&hashed_slot2)),
943 Some(&original_slot_value)
944 );
945 assert_eq!(account_storage.map(|st| st.wiped), Some(false));
946
947 let wiped_extension =
949 HashedPostState::default().with_storages([(hashed_address, HashedStorage::new(true))]);
950 hashed_state.extend(wiped_extension);
951
952 let account_storage = hashed_state.storages.get(&hashed_address);
953 assert_eq!(account_storage.map(|st| st.storage.is_empty()), Some(true));
954 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
955
956 hashed_state.extend(HashedPostState::default().with_storages([(
958 hashed_address,
959 HashedStorage::from_iter(false, [(hashed_slot, original_slot_value)]),
960 )]));
961 let account_storage = hashed_state.storages.get(&hashed_address);
962 assert_eq!(
963 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
964 Some(&original_slot_value)
965 );
966 assert_eq!(account_storage.and_then(|st| st.storage.get(&hashed_slot2)), None);
967 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
968
969 hashed_state.extend(HashedPostState::default().with_storages([(
971 hashed_address,
972 HashedStorage::from_iter(false, [(hashed_slot2, updated_slot_value)]),
973 )]));
974 let account_storage = hashed_state.storages.get(&hashed_address);
975 assert_eq!(
976 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
977 Some(&original_slot_value)
978 );
979 assert_eq!(
980 account_storage.and_then(|st| st.storage.get(&hashed_slot2)),
981 Some(&updated_slot_value)
982 );
983 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
984 }
985
986 #[test]
987 fn test_hashed_post_state_from_bundle_state() {
988 let address = Address::random();
990
991 let account_info = AccountInfo {
993 balance: U256::from(123),
994 nonce: 42,
995 code_hash: B256::random(),
996 code: Some(Bytecode::new_raw(Bytes::from(vec![1, 2]))),
997 account_id: None,
998 };
999
1000 let mut storage = StorageWithOriginalValues::default();
1001 storage.insert(
1002 U256::from(1),
1003 StorageSlot { present_value: U256::from(4), ..Default::default() },
1004 );
1005
1006 let account = BundleAccount {
1008 status: AccountStatus::Changed,
1009 info: Some(account_info.clone()),
1010 storage,
1011 original_info: None,
1012 };
1013
1014 let state = vec![(&address, &account)];
1016
1017 let hashed_state = HashedPostState::from_bundle_state::<KeccakKeyHasher>(state);
1019
1020 assert_eq!(hashed_state.accounts.len(), 1);
1022 assert_eq!(hashed_state.storages.len(), 1);
1023
1024 assert_eq!(
1026 *hashed_state.accounts.get(&keccak256(address)).unwrap(),
1027 Some(account_info.into())
1028 );
1029 }
1030
1031 #[test]
1032 fn test_hashed_post_state_with_accounts() {
1033 let address_1 = Address::random();
1035 let address_2 = Address::random();
1036
1037 let account_info_1 = AccountInfo {
1038 balance: U256::from(1000),
1039 nonce: 1,
1040 code_hash: B256::random(),
1041 code: None,
1042 account_id: None,
1043 };
1044
1045 let account_1 = (keccak256(address_1), Some(account_info_1.into()));
1047 let account_2 = (keccak256(address_2), None);
1048
1049 let hashed_state = HashedPostState::default().with_accounts(vec![account_1, account_2]);
1051
1052 assert_eq!(hashed_state.accounts.len(), 2);
1054 assert!(hashed_state.accounts.contains_key(&keccak256(address_1)));
1055 assert!(hashed_state.accounts.contains_key(&keccak256(address_2)));
1056 }
1057
1058 #[test]
1059 fn test_hashed_post_state_with_storages() {
1060 let address_1 = Address::random();
1062 let address_2 = Address::random();
1063
1064 let storage_1 = (keccak256(address_1), HashedStorage::new(false));
1065 let storage_2 = (keccak256(address_2), HashedStorage::new(true));
1066
1067 let hashed_state = HashedPostState::default().with_storages(vec![storage_1, storage_2]);
1069
1070 assert_eq!(hashed_state.storages.len(), 2);
1072 assert!(hashed_state.storages.contains_key(&keccak256(address_1)));
1073 assert!(hashed_state.storages.contains_key(&keccak256(address_2)));
1074 }
1075
1076 #[test]
1077 fn test_hashed_post_state_is_empty() {
1078 let empty_state = HashedPostState::default();
1080 assert!(empty_state.is_empty());
1081
1082 let non_empty_state = HashedPostState::default()
1084 .with_accounts(vec![(keccak256(Address::random()), Some(Account::default()))]);
1085 assert!(!non_empty_state.is_empty());
1086 }
1087
1088 fn create_state_for_multi_proof_targets() -> HashedPostState {
1089 let mut state = HashedPostState::default();
1090
1091 let addr1 = B256::random();
1092 let addr2 = B256::random();
1093 state.accounts.insert(addr1, Some(Default::default()));
1094 state.accounts.insert(addr2, Some(Default::default()));
1095
1096 let mut storage = HashedStorage::default();
1097 let slot1 = B256::random();
1098 let slot2 = B256::random();
1099 storage.storage.insert(slot1, U256::ZERO);
1100 storage.storage.insert(slot2, U256::from(1));
1101 state.storages.insert(addr1, storage);
1102
1103 state
1104 }
1105
1106 #[test]
1107 fn test_multi_proof_targets_difference_empty_state() {
1108 let state = HashedPostState::default();
1109 let excluded = MultiProofTargets::default();
1110
1111 let targets = state.multi_proof_targets_difference(&excluded);
1112 assert!(targets.is_empty());
1113 }
1114
1115 #[test]
1116 fn test_multi_proof_targets_difference_new_account_targets() {
1117 let state = create_state_for_multi_proof_targets();
1118 let excluded = MultiProofTargets::default();
1119
1120 let targets = state.multi_proof_targets_difference(&excluded);
1122 assert_eq!(targets.len(), state.accounts.len());
1123 for addr in state.accounts.keys() {
1124 assert!(targets.contains_key(addr));
1125 }
1126 }
1127
1128 #[test]
1129 fn test_multi_proof_targets_difference_new_storage_targets() {
1130 let state = create_state_for_multi_proof_targets();
1131 let excluded = MultiProofTargets::default();
1132
1133 let targets = state.multi_proof_targets_difference(&excluded);
1134
1135 for (addr, storage) in &state.storages {
1137 assert!(targets.contains_key(addr));
1138 let target_slots = &targets[addr];
1139 assert_eq!(target_slots.len(), storage.storage.len());
1140 for slot in storage.storage.keys() {
1141 assert!(target_slots.contains(slot));
1142 }
1143 }
1144 }
1145
1146 #[test]
1147 fn test_multi_proof_targets_difference_filter_excluded_accounts() {
1148 let state = create_state_for_multi_proof_targets();
1149 let mut excluded = MultiProofTargets::default();
1150
1151 let excluded_addr = state
1153 .accounts
1154 .keys()
1155 .find(|&&addr| !state.storages.contains_key(&addr))
1156 .expect("Should have an account without storage");
1157
1158 excluded.insert(*excluded_addr, HashSet::default());
1160
1161 let targets = state.multi_proof_targets_difference(&excluded);
1162
1163 assert!(!targets.contains_key(excluded_addr));
1165 assert_eq!(targets.len(), state.accounts.len() - 1);
1167 }
1168
1169 #[test]
1170 fn test_multi_proof_targets_difference_filter_excluded_storage() {
1171 let state = create_state_for_multi_proof_targets();
1172 let mut excluded = MultiProofTargets::default();
1173
1174 let (addr, storage) = state.storages.iter().next().unwrap();
1176 let mut excluded_slots = HashSet::default();
1177 let excluded_slot = *storage.storage.keys().next().unwrap();
1178 excluded_slots.insert(excluded_slot);
1179 excluded.insert(*addr, excluded_slots);
1180
1181 let targets = state.multi_proof_targets_difference(&excluded);
1182
1183 let target_slots = &targets[addr];
1185 assert!(!target_slots.contains(&excluded_slot));
1186 assert_eq!(target_slots.len(), storage.storage.len() - 1);
1187 }
1188
1189 #[test]
1190 fn test_multi_proof_targets_difference_mixed_excluded_state() {
1191 let mut state = HashedPostState::default();
1192 let mut excluded = MultiProofTargets::default();
1193
1194 let addr1 = B256::random();
1195 let addr2 = B256::random();
1196 let slot1 = B256::random();
1197 let slot2 = B256::random();
1198
1199 state.accounts.insert(addr1, Some(Default::default()));
1200 state.accounts.insert(addr2, Some(Default::default()));
1201
1202 let mut storage = HashedStorage::default();
1203 storage.storage.insert(slot1, U256::ZERO);
1204 storage.storage.insert(slot2, U256::from(1));
1205 state.storages.insert(addr1, storage);
1206
1207 let mut excluded_slots = HashSet::default();
1208 excluded_slots.insert(slot1);
1209 excluded.insert(addr1, excluded_slots);
1210
1211 let targets = state.multi_proof_targets_difference(&excluded);
1212
1213 assert!(targets.contains_key(&addr2));
1214 assert!(!targets[&addr1].contains(&slot1));
1215 assert!(targets[&addr1].contains(&slot2));
1216 }
1217
1218 #[test]
1219 fn test_multi_proof_targets_difference_unmodified_account_with_storage() {
1220 let mut state = HashedPostState::default();
1221 let excluded = MultiProofTargets::default();
1222
1223 let addr = B256::random();
1224 let slot1 = B256::random();
1225 let slot2 = B256::random();
1226
1227 let mut storage = HashedStorage::default();
1230 storage.storage.insert(slot1, U256::from(1));
1231 storage.storage.insert(slot2, U256::from(2));
1232 state.storages.insert(addr, storage);
1233
1234 assert!(!state.accounts.contains_key(&addr));
1235 assert!(!excluded.contains_key(&addr));
1236
1237 let targets = state.multi_proof_targets_difference(&excluded);
1238
1239 assert!(targets.contains_key(&addr));
1241
1242 let target_slots = &targets[&addr];
1243 assert_eq!(target_slots.len(), 2);
1244 assert!(target_slots.contains(&slot1));
1245 assert!(target_slots.contains(&slot2));
1246 }
1247
1248 #[test]
1249 fn test_partition_by_targets() {
1250 let addr1 = B256::random();
1251 let addr2 = B256::random();
1252 let slot1 = B256::random();
1253 let slot2 = B256::random();
1254
1255 let state = HashedPostState {
1256 accounts: B256Map::from_iter([
1257 (addr1, Some(Default::default())),
1258 (addr2, Some(Default::default())),
1259 ]),
1260 storages: B256Map::from_iter([(
1261 addr1,
1262 HashedStorage {
1263 wiped: true,
1264 storage: B256Map::from_iter([(slot1, U256::ZERO), (slot2, U256::from(1))]),
1265 },
1266 )]),
1267 };
1268 let targets = MultiProofTargets::from_iter([(addr1, HashSet::from_iter([slot1]))]);
1269
1270 let (with_targets, without_targets) =
1271 state.partition_by_targets(&targets, &MultiAddedRemovedKeys::new());
1272
1273 assert_eq!(
1274 with_targets,
1275 HashedPostState {
1276 accounts: B256Map::from_iter([(addr1, Some(Default::default()))]),
1277 storages: B256Map::from_iter([(
1278 addr1,
1279 HashedStorage {
1280 wiped: true,
1281 storage: B256Map::from_iter([(slot1, U256::ZERO)])
1282 }
1283 )]),
1284 }
1285 );
1286 assert_eq!(
1287 without_targets,
1288 HashedPostState {
1289 accounts: B256Map::from_iter([(addr2, Some(Default::default()))]),
1290 storages: B256Map::from_iter([(
1291 addr1,
1292 HashedStorage {
1293 wiped: false,
1294 storage: B256Map::from_iter([(slot2, U256::from(1))])
1295 }
1296 )]),
1297 }
1298 );
1299 }
1300
1301 #[test]
1302 fn test_chunks() {
1303 let addr1 = B256::from([1; 32]);
1304 let addr2 = B256::from([2; 32]);
1305 let slot1 = B256::from([1; 32]);
1306 let slot2 = B256::from([2; 32]);
1307
1308 let state = HashedPostState {
1309 accounts: B256Map::from_iter([
1310 (addr1, Some(Default::default())),
1311 (addr2, Some(Default::default())),
1312 ]),
1313 storages: B256Map::from_iter([(
1314 addr2,
1315 HashedStorage {
1316 wiped: true,
1317 storage: B256Map::from_iter([(slot1, U256::ZERO), (slot2, U256::from(1))]),
1318 },
1319 )]),
1320 };
1321
1322 let mut chunks = state.chunks(2);
1323 assert_eq!(
1324 chunks.next(),
1325 Some(HashedPostState {
1326 accounts: B256Map::from_iter([(addr1, Some(Default::default()))]),
1327 storages: B256Map::from_iter([(addr2, HashedStorage::new(true)),])
1328 })
1329 );
1330 assert_eq!(
1331 chunks.next(),
1332 Some(HashedPostState {
1333 accounts: B256Map::default(),
1334 storages: B256Map::from_iter([(
1335 addr2,
1336 HashedStorage {
1337 wiped: false,
1338 storage: B256Map::from_iter([(slot1, U256::ZERO), (slot2, U256::from(1))]),
1339 },
1340 )])
1341 })
1342 );
1343 assert_eq!(
1344 chunks.next(),
1345 Some(HashedPostState {
1346 accounts: B256Map::from_iter([(addr2, Some(Default::default()))]),
1347 storages: B256Map::default()
1348 })
1349 );
1350 assert_eq!(chunks.next(), None);
1351 }
1352
1353 #[test]
1354 fn test_chunks_ordering_guarantee() {
1355 let addr = B256::from([1; 32]);
1358 let slot1 = B256::from([1; 32]);
1359 let slot2 = B256::from([2; 32]);
1360
1361 let state = HashedPostState {
1362 accounts: B256Map::from_iter([(addr, Some(Default::default()))]),
1363 storages: B256Map::from_iter([(
1364 addr,
1365 HashedStorage {
1366 wiped: true,
1367 storage: B256Map::from_iter([(slot1, U256::from(1)), (slot2, U256::from(2))]),
1368 },
1369 )]),
1370 };
1371
1372 let chunks: Vec<_> = state.chunks(1).collect();
1373
1374 assert_eq!(chunks.len(), 4);
1376
1377 assert!(chunks[0].accounts.is_empty());
1379 assert_eq!(chunks[0].storages.len(), 1);
1380 assert!(chunks[0].storages.get(&addr).unwrap().wiped);
1381 assert!(chunks[0].storages.get(&addr).unwrap().storage.is_empty());
1382
1383 assert!(chunks[1].accounts.is_empty());
1385 assert!(!chunks[1].storages.get(&addr).unwrap().wiped);
1386 assert_eq!(chunks[1].storages.get(&addr).unwrap().storage.len(), 1);
1387
1388 assert!(chunks[2].accounts.is_empty());
1389 assert!(!chunks[2].storages.get(&addr).unwrap().wiped);
1390 assert_eq!(chunks[2].storages.get(&addr).unwrap().storage.len(), 1);
1391
1392 assert_eq!(chunks[3].accounts.len(), 1);
1394 assert!(chunks[3].accounts.contains_key(&addr));
1395 assert!(chunks[3].storages.is_empty());
1396 }
1397
1398 #[test]
1399 fn test_hashed_post_state_sorted_extend_ref() {
1400 let mut state1 = HashedPostStateSorted {
1402 accounts: vec![
1403 (B256::from([1; 32]), Some(Account::default())),
1404 (B256::from([3; 32]), Some(Account::default())),
1405 (B256::from([5; 32]), None),
1406 ],
1407 storages: B256Map::default(),
1408 };
1409
1410 let state2 = HashedPostStateSorted {
1411 accounts: vec![
1412 (B256::from([2; 32]), Some(Account::default())),
1413 (B256::from([3; 32]), Some(Account { nonce: 1, ..Default::default() })), (B256::from([4; 32]), Some(Account::default())),
1415 (B256::from([6; 32]), None),
1416 ],
1417 storages: B256Map::default(),
1418 };
1419
1420 state1.extend_ref_and_sort(&state2);
1421
1422 assert_eq!(state1.accounts.len(), 6);
1424 assert_eq!(state1.accounts[0].0, B256::from([1; 32]));
1425 assert_eq!(state1.accounts[1].0, B256::from([2; 32]));
1426 assert_eq!(state1.accounts[2].0, B256::from([3; 32]));
1427 assert_eq!(state1.accounts[2].1.unwrap().nonce, 1); assert_eq!(state1.accounts[3].0, B256::from([4; 32]));
1429 assert_eq!(state1.accounts[4].0, B256::from([5; 32]));
1430 assert_eq!(state1.accounts[4].1, None);
1431 assert_eq!(state1.accounts[5].0, B256::from([6; 32]));
1432 assert_eq!(state1.accounts[5].1, None);
1433 }
1434
1435 #[test]
1436 fn test_hashed_storage_sorted_extend_ref() {
1437 let mut storage1 = HashedStorageSorted {
1439 storage_slots: vec![
1440 (B256::from([1; 32]), U256::from(10)),
1441 (B256::from([3; 32]), U256::from(30)),
1442 (B256::from([5; 32]), U256::ZERO),
1443 ],
1444 wiped: false,
1445 };
1446
1447 let storage2 = HashedStorageSorted {
1448 storage_slots: vec![
1449 (B256::from([2; 32]), U256::from(20)),
1450 (B256::from([3; 32]), U256::from(300)), (B256::from([4; 32]), U256::from(40)),
1452 (B256::from([6; 32]), U256::ZERO),
1453 ],
1454 wiped: false,
1455 };
1456
1457 storage1.extend_ref(&storage2);
1458
1459 assert_eq!(storage1.storage_slots.len(), 6);
1460 assert_eq!(storage1.storage_slots[0].0, B256::from([1; 32]));
1461 assert_eq!(storage1.storage_slots[0].1, U256::from(10));
1462 assert_eq!(storage1.storage_slots[1].0, B256::from([2; 32]));
1463 assert_eq!(storage1.storage_slots[1].1, U256::from(20));
1464 assert_eq!(storage1.storage_slots[2].0, B256::from([3; 32]));
1465 assert_eq!(storage1.storage_slots[2].1, U256::from(300)); assert_eq!(storage1.storage_slots[3].0, B256::from([4; 32]));
1467 assert_eq!(storage1.storage_slots[3].1, U256::from(40));
1468 assert_eq!(storage1.storage_slots[4].0, B256::from([5; 32]));
1469 assert_eq!(storage1.storage_slots[4].1, U256::ZERO);
1470 assert_eq!(storage1.storage_slots[5].0, B256::from([6; 32]));
1471 assert_eq!(storage1.storage_slots[5].1, U256::ZERO);
1472 assert!(!storage1.wiped);
1473
1474 let mut storage3 = HashedStorageSorted {
1476 storage_slots: vec![
1477 (B256::from([1; 32]), U256::from(10)),
1478 (B256::from([2; 32]), U256::ZERO),
1479 ],
1480 wiped: false,
1481 };
1482
1483 let storage4 = HashedStorageSorted {
1484 storage_slots: vec![
1485 (B256::from([3; 32]), U256::from(30)),
1486 (B256::from([4; 32]), U256::ZERO),
1487 ],
1488 wiped: true,
1489 };
1490
1491 storage3.extend_ref(&storage4);
1492
1493 assert!(storage3.wiped);
1494 assert_eq!(storage3.storage_slots.len(), 2);
1496 assert_eq!(storage3.storage_slots[0].0, B256::from([3; 32]));
1497 assert_eq!(storage3.storage_slots[0].1, U256::from(30));
1498 assert_eq!(storage3.storage_slots[1].0, B256::from([4; 32]));
1499 assert_eq!(storage3.storage_slots[1].1, U256::ZERO);
1500 }
1501
1502 #[test]
1504 fn test_hashed_post_state_extend_from_sorted_with_accounts() {
1505 let addr1 = B256::random();
1506 let addr2 = B256::random();
1507
1508 let mut state = HashedPostState::default();
1509 state.accounts.insert(addr1, Some(Default::default()));
1510
1511 let mut sorted_state = HashedPostStateSorted::default();
1512 sorted_state.accounts.push((addr2, Some(Default::default())));
1513
1514 state.extend_from_sorted(&sorted_state);
1515
1516 assert_eq!(state.accounts.len(), 2);
1517 assert!(state.accounts.contains_key(&addr1));
1518 assert!(state.accounts.contains_key(&addr2));
1519 }
1520
1521 #[test]
1523 fn test_hashed_post_state_extend_from_sorted_with_destroyed_accounts() {
1524 let addr1 = B256::random();
1525
1526 let mut state = HashedPostState::default();
1527
1528 let mut sorted_state = HashedPostStateSorted::default();
1529 sorted_state.accounts.push((addr1, None));
1530
1531 state.extend_from_sorted(&sorted_state);
1532
1533 assert!(state.accounts.contains_key(&addr1));
1534 assert_eq!(state.accounts.get(&addr1), Some(&None));
1535 }
1536
1537 #[test]
1539 fn test_hashed_storage_extend_from_sorted_non_wiped() {
1540 let slot1 = B256::random();
1541 let slot2 = B256::random();
1542 let slot3 = B256::random();
1543
1544 let mut storage = HashedStorage::from_iter(false, [(slot1, U256::from(100))]);
1545
1546 let sorted = HashedStorageSorted {
1547 storage_slots: vec![(slot2, U256::from(200)), (slot3, U256::ZERO)],
1548 wiped: false,
1549 };
1550
1551 storage.extend_from_sorted(&sorted);
1552
1553 assert!(!storage.wiped);
1554 assert_eq!(storage.storage.len(), 3);
1555 assert_eq!(storage.storage.get(&slot1), Some(&U256::from(100)));
1556 assert_eq!(storage.storage.get(&slot2), Some(&U256::from(200)));
1557 assert_eq!(storage.storage.get(&slot3), Some(&U256::ZERO));
1558 }
1559
1560 #[test]
1562 fn test_hashed_storage_extend_from_sorted_wiped() {
1563 let slot1 = B256::random();
1564 let slot2 = B256::random();
1565
1566 let mut storage = HashedStorage::from_iter(false, [(slot1, U256::from(100))]);
1567
1568 let sorted =
1569 HashedStorageSorted { storage_slots: vec![(slot2, U256::from(200))], wiped: true };
1570
1571 storage.extend_from_sorted(&sorted);
1572
1573 assert!(storage.wiped);
1574 assert_eq!(storage.storage.len(), 1);
1576 assert_eq!(storage.storage.get(&slot2), Some(&U256::from(200)));
1577 }
1578
1579 #[test]
1580 fn test_hashed_post_state_chunking_length() {
1581 let addr1 = B256::from([1; 32]);
1582 let addr2 = B256::from([2; 32]);
1583 let addr3 = B256::from([3; 32]);
1584 let addr4 = B256::from([4; 32]);
1585 let slot1 = B256::from([1; 32]);
1586 let slot2 = B256::from([2; 32]);
1587 let slot3 = B256::from([3; 32]);
1588
1589 let state = HashedPostState {
1590 accounts: B256Map::from_iter([(addr1, None), (addr2, None), (addr4, None)]),
1591 storages: B256Map::from_iter([
1592 (
1593 addr1,
1594 HashedStorage {
1595 wiped: false,
1596 storage: B256Map::from_iter([
1597 (slot1, U256::ZERO),
1598 (slot2, U256::ZERO),
1599 (slot3, U256::ZERO),
1600 ]),
1601 },
1602 ),
1603 (
1604 addr2,
1605 HashedStorage {
1606 wiped: true,
1607 storage: B256Map::from_iter([
1608 (slot1, U256::ZERO),
1609 (slot2, U256::ZERO),
1610 (slot3, U256::ZERO),
1611 ]),
1612 },
1613 ),
1614 (
1615 addr3,
1616 HashedStorage {
1617 wiped: false,
1618 storage: B256Map::from_iter([
1619 (slot1, U256::ZERO),
1620 (slot2, U256::ZERO),
1621 (slot3, U256::ZERO),
1622 ]),
1623 },
1624 ),
1625 ]),
1626 };
1627
1628 let chunking_length = state.chunking_length();
1629 for size in 1..=state.clone().chunks(1).count() {
1630 let chunk_count = state.clone().chunks(size).count();
1631 let expected_count = chunking_length.div_ceil(size);
1632 assert_eq!(
1633 chunk_count, expected_count,
1634 "chunking_length: {}, size: {}",
1635 chunking_length, size
1636 );
1637 }
1638 }
1639
1640 #[test]
1641 fn test_clone_into_sorted_equivalence() {
1642 let addr1 = B256::from([1; 32]);
1643 let addr2 = B256::from([2; 32]);
1644 let addr3 = B256::from([3; 32]);
1645 let slot1 = B256::from([1; 32]);
1646 let slot2 = B256::from([2; 32]);
1647 let slot3 = B256::from([3; 32]);
1648
1649 let state = HashedPostState {
1650 accounts: B256Map::from_iter([
1651 (addr1, Some(Account { nonce: 1, balance: U256::from(100), bytecode_hash: None })),
1652 (addr2, None),
1653 (addr3, Some(Account::default())),
1654 ]),
1655 storages: B256Map::from_iter([
1656 (
1657 addr1,
1658 HashedStorage {
1659 wiped: false,
1660 storage: B256Map::from_iter([
1661 (slot1, U256::from(10)),
1662 (slot2, U256::from(20)),
1663 ]),
1664 },
1665 ),
1666 (
1667 addr2,
1668 HashedStorage {
1669 wiped: true,
1670 storage: B256Map::from_iter([(slot3, U256::ZERO)]),
1671 },
1672 ),
1673 ]),
1674 };
1675
1676 let sorted_via_clone = state.clone().into_sorted();
1678 let sorted_via_clone_into = state.clone_into_sorted();
1679
1680 assert_eq!(sorted_via_clone, sorted_via_clone_into);
1681
1682 assert_eq!(state.accounts.len(), 3);
1684 assert_eq!(state.storages.len(), 2);
1685 }
1686
1687 #[test]
1688 fn test_hashed_storage_clone_into_sorted_equivalence() {
1689 let slot1 = B256::from([1; 32]);
1690 let slot2 = B256::from([2; 32]);
1691 let slot3 = B256::from([3; 32]);
1692
1693 let storage = HashedStorage {
1694 wiped: true,
1695 storage: B256Map::from_iter([
1696 (slot1, U256::from(100)),
1697 (slot2, U256::ZERO),
1698 (slot3, U256::from(300)),
1699 ]),
1700 };
1701
1702 let sorted_via_clone = storage.clone().into_sorted();
1704 let sorted_via_clone_into = storage.clone_into_sorted();
1705
1706 assert_eq!(sorted_via_clone, sorted_via_clone_into);
1707
1708 assert_eq!(storage.storage.len(), 3);
1710 assert!(storage.wiped);
1711 }
1712}
1713
1714#[cfg(feature = "serde-bincode-compat")]
1716pub mod serde_bincode_compat {
1717 use super::Account;
1718 use alloc::borrow::Cow;
1719 use alloy_primitives::{map::B256Map, B256, U256};
1720 use serde::{Deserialize, Deserializer, Serialize, Serializer};
1721 use serde_with::{DeserializeAs, SerializeAs};
1722
1723 #[derive(Debug, Serialize, Deserialize)]
1739 pub struct HashedPostState<'a> {
1740 accounts: Cow<'a, B256Map<Option<Account>>>,
1741 storages: B256Map<HashedStorage<'a>>,
1742 }
1743
1744 impl<'a> From<&'a super::HashedPostState> for HashedPostState<'a> {
1745 fn from(value: &'a super::HashedPostState) -> Self {
1746 Self {
1747 accounts: Cow::Borrowed(&value.accounts),
1748 storages: value.storages.iter().map(|(k, v)| (*k, v.into())).collect(),
1749 }
1750 }
1751 }
1752
1753 impl<'a> From<HashedPostState<'a>> for super::HashedPostState {
1754 fn from(value: HashedPostState<'a>) -> Self {
1755 Self {
1756 accounts: value.accounts.into_owned(),
1757 storages: value.storages.into_iter().map(|(k, v)| (k, v.into())).collect(),
1758 }
1759 }
1760 }
1761
1762 impl SerializeAs<super::HashedPostState> for HashedPostState<'_> {
1763 fn serialize_as<S>(
1764 source: &super::HashedPostState,
1765 serializer: S,
1766 ) -> Result<S::Ok, S::Error>
1767 where
1768 S: Serializer,
1769 {
1770 HashedPostState::from(source).serialize(serializer)
1771 }
1772 }
1773
1774 impl<'de> DeserializeAs<'de, super::HashedPostState> for HashedPostState<'de> {
1775 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedPostState, D::Error>
1776 where
1777 D: Deserializer<'de>,
1778 {
1779 HashedPostState::deserialize(deserializer).map(Into::into)
1780 }
1781 }
1782
1783 #[derive(Debug, Serialize, Deserialize)]
1799 pub struct HashedStorage<'a> {
1800 wiped: bool,
1801 storage: Cow<'a, B256Map<U256>>,
1802 }
1803
1804 impl<'a> From<&'a super::HashedStorage> for HashedStorage<'a> {
1805 fn from(value: &'a super::HashedStorage) -> Self {
1806 Self { wiped: value.wiped, storage: Cow::Borrowed(&value.storage) }
1807 }
1808 }
1809
1810 impl<'a> From<HashedStorage<'a>> for super::HashedStorage {
1811 fn from(value: HashedStorage<'a>) -> Self {
1812 Self { wiped: value.wiped, storage: value.storage.into_owned() }
1813 }
1814 }
1815
1816 impl SerializeAs<super::HashedStorage> for HashedStorage<'_> {
1817 fn serialize_as<S>(source: &super::HashedStorage, serializer: S) -> Result<S::Ok, S::Error>
1818 where
1819 S: Serializer,
1820 {
1821 HashedStorage::from(source).serialize(serializer)
1822 }
1823 }
1824
1825 impl<'de> DeserializeAs<'de, super::HashedStorage> for HashedStorage<'de> {
1826 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedStorage, D::Error>
1827 where
1828 D: Deserializer<'de>,
1829 {
1830 HashedStorage::deserialize(deserializer).map(Into::into)
1831 }
1832 }
1833
1834 #[derive(Debug, Serialize, Deserialize)]
1850 pub struct HashedPostStateSorted<'a> {
1851 accounts: Cow<'a, [(B256, Option<Account>)]>,
1852 storages: B256Map<HashedStorageSorted<'a>>,
1853 }
1854
1855 impl<'a> From<&'a super::HashedPostStateSorted> for HashedPostStateSorted<'a> {
1856 fn from(value: &'a super::HashedPostStateSorted) -> Self {
1857 Self {
1858 accounts: Cow::Borrowed(&value.accounts),
1859 storages: value.storages.iter().map(|(k, v)| (*k, v.into())).collect(),
1860 }
1861 }
1862 }
1863
1864 impl<'a> From<HashedPostStateSorted<'a>> for super::HashedPostStateSorted {
1865 fn from(value: HashedPostStateSorted<'a>) -> Self {
1866 Self {
1867 accounts: value.accounts.into_owned(),
1868 storages: value.storages.into_iter().map(|(k, v)| (k, v.into())).collect(),
1869 }
1870 }
1871 }
1872
1873 impl SerializeAs<super::HashedPostStateSorted> for HashedPostStateSorted<'_> {
1874 fn serialize_as<S>(
1875 source: &super::HashedPostStateSorted,
1876 serializer: S,
1877 ) -> Result<S::Ok, S::Error>
1878 where
1879 S: Serializer,
1880 {
1881 HashedPostStateSorted::from(source).serialize(serializer)
1882 }
1883 }
1884
1885 impl<'de> DeserializeAs<'de, super::HashedPostStateSorted> for HashedPostStateSorted<'de> {
1886 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedPostStateSorted, D::Error>
1887 where
1888 D: Deserializer<'de>,
1889 {
1890 HashedPostStateSorted::deserialize(deserializer).map(Into::into)
1891 }
1892 }
1893
1894 #[derive(Debug, Serialize, Deserialize)]
1910 pub struct HashedStorageSorted<'a> {
1911 storage_slots: Cow<'a, [(B256, U256)]>,
1912 wiped: bool,
1913 }
1914
1915 impl<'a> From<&'a super::HashedStorageSorted> for HashedStorageSorted<'a> {
1916 fn from(value: &'a super::HashedStorageSorted) -> Self {
1917 Self { storage_slots: Cow::Borrowed(&value.storage_slots), wiped: value.wiped }
1918 }
1919 }
1920
1921 impl<'a> From<HashedStorageSorted<'a>> for super::HashedStorageSorted {
1922 fn from(value: HashedStorageSorted<'a>) -> Self {
1923 Self { storage_slots: value.storage_slots.into_owned(), wiped: value.wiped }
1924 }
1925 }
1926
1927 impl SerializeAs<super::HashedStorageSorted> for HashedStorageSorted<'_> {
1928 fn serialize_as<S>(
1929 source: &super::HashedStorageSorted,
1930 serializer: S,
1931 ) -> Result<S::Ok, S::Error>
1932 where
1933 S: Serializer,
1934 {
1935 HashedStorageSorted::from(source).serialize(serializer)
1936 }
1937 }
1938
1939 impl<'de> DeserializeAs<'de, super::HashedStorageSorted> for HashedStorageSorted<'de> {
1940 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedStorageSorted, D::Error>
1941 where
1942 D: Deserializer<'de>,
1943 {
1944 HashedStorageSorted::deserialize(deserializer).map(Into::into)
1945 }
1946 }
1947
1948 #[cfg(test)]
1949 mod tests {
1950 use crate::{
1951 hashed_state::{
1952 HashedPostState, HashedPostStateSorted, HashedStorage, HashedStorageSorted,
1953 },
1954 serde_bincode_compat,
1955 };
1956 use alloy_primitives::{B256, U256};
1957 use reth_primitives_traits::Account;
1958 use serde::{Deserialize, Serialize};
1959 use serde_with::serde_as;
1960
1961 #[test]
1962 fn test_hashed_post_state_bincode_roundtrip() {
1963 #[serde_as]
1964 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
1965 struct Data {
1966 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedPostState")]
1967 hashed_state: HashedPostState,
1968 }
1969
1970 let mut data = Data { hashed_state: HashedPostState::default() };
1971 let encoded = bincode::serialize(&data).unwrap();
1972 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1973 assert_eq!(decoded, data);
1974
1975 data.hashed_state.accounts.insert(B256::random(), Some(Account::default()));
1976 let encoded = bincode::serialize(&data).unwrap();
1977 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1978 assert_eq!(decoded, data);
1979
1980 data.hashed_state.storages.insert(B256::random(), HashedStorage::default());
1981 let encoded = bincode::serialize(&data).unwrap();
1982 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1983 assert_eq!(decoded, data);
1984 }
1985
1986 #[test]
1987 fn test_hashed_storage_bincode_roundtrip() {
1988 #[serde_as]
1989 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
1990 struct Data {
1991 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedStorage")]
1992 hashed_storage: HashedStorage,
1993 }
1994
1995 let mut data = Data { hashed_storage: HashedStorage::default() };
1996 let encoded = bincode::serialize(&data).unwrap();
1997 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1998 assert_eq!(decoded, data);
1999
2000 data.hashed_storage.wiped = true;
2001 let encoded = bincode::serialize(&data).unwrap();
2002 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2003 assert_eq!(decoded, data);
2004
2005 data.hashed_storage.storage.insert(B256::random(), U256::from(1));
2006 let encoded = bincode::serialize(&data).unwrap();
2007 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2008 assert_eq!(decoded, data);
2009 }
2010
2011 #[test]
2012 fn test_hashed_post_state_sorted_bincode_roundtrip() {
2013 #[serde_as]
2014 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
2015 struct Data {
2016 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedPostStateSorted")]
2017 hashed_state: HashedPostStateSorted,
2018 }
2019
2020 let mut data = Data { hashed_state: HashedPostStateSorted::default() };
2021 let encoded = bincode::serialize(&data).unwrap();
2022 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2023 assert_eq!(decoded, data);
2024
2025 data.hashed_state.accounts.push((B256::random(), Some(Account::default())));
2026 data.hashed_state
2027 .accounts
2028 .push((B256::random(), Some(Account { nonce: 1, ..Default::default() })));
2029 let encoded = bincode::serialize(&data).unwrap();
2030 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2031 assert_eq!(decoded, data);
2032
2033 data.hashed_state.storages.insert(
2034 B256::random(),
2035 HashedStorageSorted {
2036 storage_slots: vec![(B256::from([1; 32]), U256::from(10))],
2037 wiped: false,
2038 },
2039 );
2040 let encoded = bincode::serialize(&data).unwrap();
2041 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2042 assert_eq!(decoded, data);
2043 }
2044
2045 #[test]
2046 fn test_hashed_storage_sorted_bincode_roundtrip() {
2047 #[serde_as]
2048 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
2049 struct Data {
2050 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedStorageSorted")]
2051 hashed_storage: HashedStorageSorted,
2052 }
2053
2054 let mut data = Data {
2055 hashed_storage: HashedStorageSorted { storage_slots: Vec::new(), wiped: false },
2056 };
2057 let encoded = bincode::serialize(&data).unwrap();
2058 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2059 assert_eq!(decoded, data);
2060
2061 data.hashed_storage.wiped = true;
2062 let encoded = bincode::serialize(&data).unwrap();
2063 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2064 assert_eq!(decoded, data);
2065
2066 data.hashed_storage.storage_slots.push((B256::random(), U256::from(1)));
2067 let encoded = bincode::serialize(&data).unwrap();
2068 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2069 assert_eq!(decoded, data);
2070 }
2071 }
2072}