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 const THRESHOLD: usize = 30;
618
619 let items: alloc::vec::Vec<_> = iter.into_iter().collect();
620 let k = items.len();
621
622 if k == 0 {
623 return Self::default().into();
624 }
625 if k == 1 {
626 return items.into_iter().next().expect("k == 1");
627 }
628
629 if k < THRESHOLD {
630 let mut iter = items.iter().rev();
632 let mut acc = iter.next().expect("k > 0").as_ref().clone();
633 for next in iter {
634 acc.extend_ref_and_sort(next.as_ref());
635 }
636 return acc.into();
637 }
638
639 let accounts = kway_merge_sorted(items.iter().map(|i| i.as_ref().accounts.as_slice()));
641
642 struct StorageAcc<'a> {
643 wiped: bool,
644 sealed: bool,
645 slices: Vec<&'a [(B256, U256)]>,
646 }
647
648 let mut acc: B256Map<StorageAcc<'_>> = B256Map::default();
649
650 for item in &items {
651 for (addr, storage) in &item.as_ref().storages {
652 let entry = acc.entry(*addr).or_insert_with(|| StorageAcc {
653 wiped: false,
654 sealed: false,
655 slices: Vec::new(),
656 });
657
658 if entry.sealed {
659 continue;
660 }
661
662 entry.slices.push(storage.storage_slots.as_slice());
663 if storage.wiped {
664 entry.wiped = true;
665 entry.sealed = true;
666 }
667 }
668 }
669
670 let storages = acc
671 .into_iter()
672 .map(|(addr, entry)| {
673 let storage_slots = kway_merge_sorted(entry.slices);
674 (addr, HashedStorageSorted { wiped: entry.wiped, storage_slots })
675 })
676 .collect();
677
678 Self { accounts, storages }.into()
679 }
680
681 pub fn clear(&mut self) {
683 self.accounts.clear();
684 self.storages.clear();
685 }
686}
687
688impl AsRef<Self> for HashedPostStateSorted {
689 fn as_ref(&self) -> &Self {
690 self
691 }
692}
693
694#[derive(Clone, Eq, PartialEq, Debug, Default)]
696#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
697pub struct HashedStorageSorted {
698 pub storage_slots: Vec<(B256, U256)>,
700 pub wiped: bool,
702}
703
704impl HashedStorageSorted {
705 pub const fn is_wiped(&self) -> bool {
707 self.wiped
708 }
709
710 pub fn storage_slots_ref(&self) -> &[(B256, U256)] {
712 &self.storage_slots
713 }
714
715 pub const fn len(&self) -> usize {
717 self.storage_slots.len()
718 }
719
720 pub const fn is_empty(&self) -> bool {
722 self.storage_slots.is_empty()
723 }
724
725 pub fn extend_ref(&mut self, other: &Self) {
730 if other.wiped {
731 self.wiped = true;
733 self.storage_slots.clear();
734 self.storage_slots.extend(other.storage_slots.iter().copied());
735 return;
736 }
737
738 extend_sorted_vec(&mut self.storage_slots, &other.storage_slots);
740 }
741
742 pub fn merge_batch<'a>(updates: impl IntoIterator<Item = &'a Self>) -> Self {
745 let updates: Vec<_> = updates.into_iter().collect();
746 if updates.is_empty() {
747 return Self::default();
748 }
749
750 let wipe_idx = updates.iter().position(|u| u.wiped);
751 let relevant = wipe_idx.map_or(&updates[..], |idx| &updates[..=idx]);
752 let storage_slots = kway_merge_sorted(relevant.iter().map(|u| u.storage_slots.as_slice()));
753
754 Self { wiped: wipe_idx.is_some(), storage_slots }
755 }
756}
757
758impl From<HashedStorageSorted> for HashedStorage {
759 fn from(sorted: HashedStorageSorted) -> Self {
760 let mut storage = B256Map::default();
761
762 for (slot, value) in sorted.storage_slots {
764 storage.insert(slot, value);
765 }
766
767 Self { wiped: sorted.wiped, storage }
768 }
769}
770
771impl From<HashedPostStateSorted> for HashedPostState {
772 fn from(sorted: HashedPostStateSorted) -> Self {
773 let mut accounts =
774 B256Map::with_capacity_and_hasher(sorted.accounts.len(), Default::default());
775
776 for (address, account) in sorted.accounts {
778 accounts.insert(address, account);
779 }
780
781 let storages = sorted
783 .storages
784 .into_iter()
785 .map(|(address, storage)| (address, storage.into()))
786 .collect();
787
788 Self { accounts, storages }
789 }
790}
791
792#[derive(Debug)]
800pub struct ChunkedHashedPostState {
801 flattened: alloc::vec::IntoIter<(B256, FlattenedHashedPostStateItem)>,
802 size: usize,
803}
804
805#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
808enum FlattenedStateOrder {
809 StorageWipe,
810 StorageUpdate(B256),
811 Account,
812}
813
814#[derive(Debug)]
815enum FlattenedHashedPostStateItem {
816 Account(Option<Account>),
817 StorageWipe,
818 StorageUpdate { slot: B256, value: U256 },
819}
820
821impl FlattenedHashedPostStateItem {
822 const fn order(&self) -> FlattenedStateOrder {
823 match self {
824 Self::StorageWipe => FlattenedStateOrder::StorageWipe,
825 Self::StorageUpdate { slot, .. } => FlattenedStateOrder::StorageUpdate(*slot),
826 Self::Account(_) => FlattenedStateOrder::Account,
827 }
828 }
829}
830
831impl ChunkedHashedPostState {
832 fn new(hashed_post_state: HashedPostState, size: usize) -> Self {
833 let flattened = hashed_post_state
834 .storages
835 .into_iter()
836 .flat_map(|(address, storage)| {
837 storage
838 .wiped
839 .then_some((address, FlattenedHashedPostStateItem::StorageWipe))
840 .into_iter()
841 .chain(storage.storage.into_iter().map(move |(slot, value)| {
842 (address, FlattenedHashedPostStateItem::StorageUpdate { slot, value })
843 }))
844 })
845 .chain(hashed_post_state.accounts.into_iter().map(|(address, account)| {
846 (address, FlattenedHashedPostStateItem::Account(account))
847 }))
848 .sorted_unstable_by_key(|(address, item)| (*address, item.order()));
853
854 Self { flattened, size }
855 }
856}
857
858impl Iterator for ChunkedHashedPostState {
859 type Item = HashedPostState;
860
861 fn next(&mut self) -> Option<Self::Item> {
862 let mut chunk = HashedPostState::default();
863
864 let mut current_size = 0;
865 while current_size < self.size {
866 let Some((address, item)) = self.flattened.next() else { break };
867
868 match item {
869 FlattenedHashedPostStateItem::Account(account) => {
870 chunk.accounts.insert(address, account);
871 }
872 FlattenedHashedPostStateItem::StorageWipe => {
873 chunk.storages.entry(address).or_default().wiped = true;
874 }
875 FlattenedHashedPostStateItem::StorageUpdate { slot, value } => {
876 chunk.storages.entry(address).or_default().storage.insert(slot, value);
877 }
878 }
879
880 current_size += 1;
881 }
882
883 if chunk.is_empty() {
884 None
885 } else {
886 Some(chunk)
887 }
888 }
889}
890
891#[cfg(test)]
892mod tests {
893 use super::*;
894 use crate::KeccakKeyHasher;
895 use alloy_primitives::Bytes;
896 use revm_database::{states::StorageSlot, StorageWithOriginalValues};
897 use revm_state::{AccountInfo, Bytecode};
898
899 #[test]
900 fn hashed_state_wiped_extension() {
901 let hashed_address = B256::default();
902 let hashed_slot = B256::with_last_byte(64);
903 let hashed_slot2 = B256::with_last_byte(65);
904
905 let original_slot_value = U256::from(123);
907 let mut hashed_state = HashedPostState::default().with_storages([(
908 hashed_address,
909 HashedStorage::from_iter(
910 false,
911 [(hashed_slot, original_slot_value), (hashed_slot2, original_slot_value)],
912 ),
913 )]);
914
915 let updated_slot_value = U256::from(321);
917 let extension = HashedPostState::default().with_storages([(
918 hashed_address,
919 HashedStorage::from_iter(false, [(hashed_slot, updated_slot_value)]),
920 )]);
921 hashed_state.extend(extension);
922
923 let account_storage = hashed_state.storages.get(&hashed_address);
924 assert_eq!(
925 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
926 Some(&updated_slot_value)
927 );
928 assert_eq!(
929 account_storage.and_then(|st| st.storage.get(&hashed_slot2)),
930 Some(&original_slot_value)
931 );
932 assert_eq!(account_storage.map(|st| st.wiped), Some(false));
933
934 let wiped_extension =
936 HashedPostState::default().with_storages([(hashed_address, HashedStorage::new(true))]);
937 hashed_state.extend(wiped_extension);
938
939 let account_storage = hashed_state.storages.get(&hashed_address);
940 assert_eq!(account_storage.map(|st| st.storage.is_empty()), Some(true));
941 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
942
943 hashed_state.extend(HashedPostState::default().with_storages([(
945 hashed_address,
946 HashedStorage::from_iter(false, [(hashed_slot, original_slot_value)]),
947 )]));
948 let account_storage = hashed_state.storages.get(&hashed_address);
949 assert_eq!(
950 account_storage.and_then(|st| st.storage.get(&hashed_slot)),
951 Some(&original_slot_value)
952 );
953 assert_eq!(account_storage.and_then(|st| st.storage.get(&hashed_slot2)), None);
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_slot2, updated_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!(
967 account_storage.and_then(|st| st.storage.get(&hashed_slot2)),
968 Some(&updated_slot_value)
969 );
970 assert_eq!(account_storage.map(|st| st.wiped), Some(true));
971 }
972
973 #[test]
974 fn test_hashed_post_state_from_bundle_state() {
975 let address = Address::random();
977
978 let account_info = AccountInfo {
980 balance: U256::from(123),
981 nonce: 42,
982 code_hash: B256::random(),
983 code: Some(Bytecode::new_raw(Bytes::from(vec![1, 2]))),
984 account_id: None,
985 };
986
987 let mut storage = StorageWithOriginalValues::default();
988 storage.insert(
989 U256::from(1),
990 StorageSlot { present_value: U256::from(4), ..Default::default() },
991 );
992
993 let account = BundleAccount {
995 status: AccountStatus::Changed,
996 info: Some(account_info.clone()),
997 storage,
998 original_info: None,
999 };
1000
1001 let state = vec![(&address, &account)];
1003
1004 let hashed_state = HashedPostState::from_bundle_state::<KeccakKeyHasher>(state);
1006
1007 assert_eq!(hashed_state.accounts.len(), 1);
1009 assert_eq!(hashed_state.storages.len(), 1);
1010
1011 assert_eq!(
1013 *hashed_state.accounts.get(&keccak256(address)).unwrap(),
1014 Some(account_info.into())
1015 );
1016 }
1017
1018 #[test]
1019 fn test_hashed_post_state_with_accounts() {
1020 let address_1 = Address::random();
1022 let address_2 = Address::random();
1023
1024 let account_info_1 = AccountInfo {
1025 balance: U256::from(1000),
1026 nonce: 1,
1027 code_hash: B256::random(),
1028 code: None,
1029 account_id: None,
1030 };
1031
1032 let account_1 = (keccak256(address_1), Some(account_info_1.into()));
1034 let account_2 = (keccak256(address_2), None);
1035
1036 let hashed_state = HashedPostState::default().with_accounts(vec![account_1, account_2]);
1038
1039 assert_eq!(hashed_state.accounts.len(), 2);
1041 assert!(hashed_state.accounts.contains_key(&keccak256(address_1)));
1042 assert!(hashed_state.accounts.contains_key(&keccak256(address_2)));
1043 }
1044
1045 #[test]
1046 fn test_hashed_post_state_with_storages() {
1047 let address_1 = Address::random();
1049 let address_2 = Address::random();
1050
1051 let storage_1 = (keccak256(address_1), HashedStorage::new(false));
1052 let storage_2 = (keccak256(address_2), HashedStorage::new(true));
1053
1054 let hashed_state = HashedPostState::default().with_storages(vec![storage_1, storage_2]);
1056
1057 assert_eq!(hashed_state.storages.len(), 2);
1059 assert!(hashed_state.storages.contains_key(&keccak256(address_1)));
1060 assert!(hashed_state.storages.contains_key(&keccak256(address_2)));
1061 }
1062
1063 #[test]
1064 fn test_hashed_post_state_is_empty() {
1065 let empty_state = HashedPostState::default();
1067 assert!(empty_state.is_empty());
1068
1069 let non_empty_state = HashedPostState::default()
1071 .with_accounts(vec![(keccak256(Address::random()), Some(Account::default()))]);
1072 assert!(!non_empty_state.is_empty());
1073 }
1074
1075 fn create_state_for_multi_proof_targets() -> HashedPostState {
1076 let mut state = HashedPostState::default();
1077
1078 let addr1 = B256::random();
1079 let addr2 = B256::random();
1080 state.accounts.insert(addr1, Some(Default::default()));
1081 state.accounts.insert(addr2, Some(Default::default()));
1082
1083 let mut storage = HashedStorage::default();
1084 let slot1 = B256::random();
1085 let slot2 = B256::random();
1086 storage.storage.insert(slot1, U256::ZERO);
1087 storage.storage.insert(slot2, U256::from(1));
1088 state.storages.insert(addr1, storage);
1089
1090 state
1091 }
1092
1093 #[test]
1094 fn test_multi_proof_targets_difference_empty_state() {
1095 let state = HashedPostState::default();
1096 let excluded = MultiProofTargets::default();
1097
1098 let targets = state.multi_proof_targets_difference(&excluded);
1099 assert!(targets.is_empty());
1100 }
1101
1102 #[test]
1103 fn test_multi_proof_targets_difference_new_account_targets() {
1104 let state = create_state_for_multi_proof_targets();
1105 let excluded = MultiProofTargets::default();
1106
1107 let targets = state.multi_proof_targets_difference(&excluded);
1109 assert_eq!(targets.len(), state.accounts.len());
1110 for addr in state.accounts.keys() {
1111 assert!(targets.contains_key(addr));
1112 }
1113 }
1114
1115 #[test]
1116 fn test_multi_proof_targets_difference_new_storage_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);
1121
1122 for (addr, storage) in &state.storages {
1124 assert!(targets.contains_key(addr));
1125 let target_slots = &targets[addr];
1126 assert_eq!(target_slots.len(), storage.storage.len());
1127 for slot in storage.storage.keys() {
1128 assert!(target_slots.contains(slot));
1129 }
1130 }
1131 }
1132
1133 #[test]
1134 fn test_multi_proof_targets_difference_filter_excluded_accounts() {
1135 let state = create_state_for_multi_proof_targets();
1136 let mut excluded = MultiProofTargets::default();
1137
1138 let excluded_addr = state
1140 .accounts
1141 .keys()
1142 .find(|&&addr| !state.storages.contains_key(&addr))
1143 .expect("Should have an account without storage");
1144
1145 excluded.insert(*excluded_addr, HashSet::default());
1147
1148 let targets = state.multi_proof_targets_difference(&excluded);
1149
1150 assert!(!targets.contains_key(excluded_addr));
1152 assert_eq!(targets.len(), state.accounts.len() - 1);
1154 }
1155
1156 #[test]
1157 fn test_multi_proof_targets_difference_filter_excluded_storage() {
1158 let state = create_state_for_multi_proof_targets();
1159 let mut excluded = MultiProofTargets::default();
1160
1161 let (addr, storage) = state.storages.iter().next().unwrap();
1163 let mut excluded_slots = HashSet::default();
1164 let excluded_slot = *storage.storage.keys().next().unwrap();
1165 excluded_slots.insert(excluded_slot);
1166 excluded.insert(*addr, excluded_slots);
1167
1168 let targets = state.multi_proof_targets_difference(&excluded);
1169
1170 let target_slots = &targets[addr];
1172 assert!(!target_slots.contains(&excluded_slot));
1173 assert_eq!(target_slots.len(), storage.storage.len() - 1);
1174 }
1175
1176 #[test]
1177 fn test_multi_proof_targets_difference_mixed_excluded_state() {
1178 let mut state = HashedPostState::default();
1179 let mut excluded = MultiProofTargets::default();
1180
1181 let addr1 = B256::random();
1182 let addr2 = B256::random();
1183 let slot1 = B256::random();
1184 let slot2 = B256::random();
1185
1186 state.accounts.insert(addr1, Some(Default::default()));
1187 state.accounts.insert(addr2, Some(Default::default()));
1188
1189 let mut storage = HashedStorage::default();
1190 storage.storage.insert(slot1, U256::ZERO);
1191 storage.storage.insert(slot2, U256::from(1));
1192 state.storages.insert(addr1, storage);
1193
1194 let mut excluded_slots = HashSet::default();
1195 excluded_slots.insert(slot1);
1196 excluded.insert(addr1, excluded_slots);
1197
1198 let targets = state.multi_proof_targets_difference(&excluded);
1199
1200 assert!(targets.contains_key(&addr2));
1201 assert!(!targets[&addr1].contains(&slot1));
1202 assert!(targets[&addr1].contains(&slot2));
1203 }
1204
1205 #[test]
1206 fn test_multi_proof_targets_difference_unmodified_account_with_storage() {
1207 let mut state = HashedPostState::default();
1208 let excluded = MultiProofTargets::default();
1209
1210 let addr = B256::random();
1211 let slot1 = B256::random();
1212 let slot2 = B256::random();
1213
1214 let mut storage = HashedStorage::default();
1217 storage.storage.insert(slot1, U256::from(1));
1218 storage.storage.insert(slot2, U256::from(2));
1219 state.storages.insert(addr, storage);
1220
1221 assert!(!state.accounts.contains_key(&addr));
1222 assert!(!excluded.contains_key(&addr));
1223
1224 let targets = state.multi_proof_targets_difference(&excluded);
1225
1226 assert!(targets.contains_key(&addr));
1228
1229 let target_slots = &targets[&addr];
1230 assert_eq!(target_slots.len(), 2);
1231 assert!(target_slots.contains(&slot1));
1232 assert!(target_slots.contains(&slot2));
1233 }
1234
1235 #[test]
1236 fn test_partition_by_targets() {
1237 let addr1 = B256::random();
1238 let addr2 = B256::random();
1239 let slot1 = B256::random();
1240 let slot2 = B256::random();
1241
1242 let state = HashedPostState {
1243 accounts: B256Map::from_iter([
1244 (addr1, Some(Default::default())),
1245 (addr2, Some(Default::default())),
1246 ]),
1247 storages: B256Map::from_iter([(
1248 addr1,
1249 HashedStorage {
1250 wiped: true,
1251 storage: B256Map::from_iter([(slot1, U256::ZERO), (slot2, U256::from(1))]),
1252 },
1253 )]),
1254 };
1255 let targets = MultiProofTargets::from_iter([(addr1, HashSet::from_iter([slot1]))]);
1256
1257 let (with_targets, without_targets) =
1258 state.partition_by_targets(&targets, &MultiAddedRemovedKeys::new());
1259
1260 assert_eq!(
1261 with_targets,
1262 HashedPostState {
1263 accounts: B256Map::from_iter([(addr1, Some(Default::default()))]),
1264 storages: B256Map::from_iter([(
1265 addr1,
1266 HashedStorage {
1267 wiped: true,
1268 storage: B256Map::from_iter([(slot1, U256::ZERO)])
1269 }
1270 )]),
1271 }
1272 );
1273 assert_eq!(
1274 without_targets,
1275 HashedPostState {
1276 accounts: B256Map::from_iter([(addr2, Some(Default::default()))]),
1277 storages: B256Map::from_iter([(
1278 addr1,
1279 HashedStorage {
1280 wiped: false,
1281 storage: B256Map::from_iter([(slot2, U256::from(1))])
1282 }
1283 )]),
1284 }
1285 );
1286 }
1287
1288 #[test]
1289 fn test_chunks() {
1290 let addr1 = B256::from([1; 32]);
1291 let addr2 = B256::from([2; 32]);
1292 let slot1 = B256::from([1; 32]);
1293 let slot2 = B256::from([2; 32]);
1294
1295 let state = HashedPostState {
1296 accounts: B256Map::from_iter([
1297 (addr1, Some(Default::default())),
1298 (addr2, Some(Default::default())),
1299 ]),
1300 storages: B256Map::from_iter([(
1301 addr2,
1302 HashedStorage {
1303 wiped: true,
1304 storage: B256Map::from_iter([(slot1, U256::ZERO), (slot2, U256::from(1))]),
1305 },
1306 )]),
1307 };
1308
1309 let mut chunks = state.chunks(2);
1310 assert_eq!(
1311 chunks.next(),
1312 Some(HashedPostState {
1313 accounts: B256Map::from_iter([(addr1, Some(Default::default()))]),
1314 storages: B256Map::from_iter([(addr2, HashedStorage::new(true)),])
1315 })
1316 );
1317 assert_eq!(
1318 chunks.next(),
1319 Some(HashedPostState {
1320 accounts: B256Map::default(),
1321 storages: B256Map::from_iter([(
1322 addr2,
1323 HashedStorage {
1324 wiped: false,
1325 storage: B256Map::from_iter([(slot1, U256::ZERO), (slot2, U256::from(1))]),
1326 },
1327 )])
1328 })
1329 );
1330 assert_eq!(
1331 chunks.next(),
1332 Some(HashedPostState {
1333 accounts: B256Map::from_iter([(addr2, Some(Default::default()))]),
1334 storages: B256Map::default()
1335 })
1336 );
1337 assert_eq!(chunks.next(), None);
1338 }
1339
1340 #[test]
1341 fn test_chunks_ordering_guarantee() {
1342 let addr = B256::from([1; 32]);
1345 let slot1 = B256::from([1; 32]);
1346 let slot2 = B256::from([2; 32]);
1347
1348 let state = HashedPostState {
1349 accounts: B256Map::from_iter([(addr, Some(Default::default()))]),
1350 storages: B256Map::from_iter([(
1351 addr,
1352 HashedStorage {
1353 wiped: true,
1354 storage: B256Map::from_iter([(slot1, U256::from(1)), (slot2, U256::from(2))]),
1355 },
1356 )]),
1357 };
1358
1359 let chunks: Vec<_> = state.chunks(1).collect();
1360
1361 assert_eq!(chunks.len(), 4);
1363
1364 assert!(chunks[0].accounts.is_empty());
1366 assert_eq!(chunks[0].storages.len(), 1);
1367 assert!(chunks[0].storages.get(&addr).unwrap().wiped);
1368 assert!(chunks[0].storages.get(&addr).unwrap().storage.is_empty());
1369
1370 assert!(chunks[1].accounts.is_empty());
1372 assert!(!chunks[1].storages.get(&addr).unwrap().wiped);
1373 assert_eq!(chunks[1].storages.get(&addr).unwrap().storage.len(), 1);
1374
1375 assert!(chunks[2].accounts.is_empty());
1376 assert!(!chunks[2].storages.get(&addr).unwrap().wiped);
1377 assert_eq!(chunks[2].storages.get(&addr).unwrap().storage.len(), 1);
1378
1379 assert_eq!(chunks[3].accounts.len(), 1);
1381 assert!(chunks[3].accounts.contains_key(&addr));
1382 assert!(chunks[3].storages.is_empty());
1383 }
1384
1385 #[test]
1386 fn test_hashed_post_state_sorted_extend_ref() {
1387 let mut state1 = HashedPostStateSorted {
1389 accounts: vec![
1390 (B256::from([1; 32]), Some(Account::default())),
1391 (B256::from([3; 32]), Some(Account::default())),
1392 (B256::from([5; 32]), None),
1393 ],
1394 storages: B256Map::default(),
1395 };
1396
1397 let state2 = HashedPostStateSorted {
1398 accounts: vec![
1399 (B256::from([2; 32]), Some(Account::default())),
1400 (B256::from([3; 32]), Some(Account { nonce: 1, ..Default::default() })), (B256::from([4; 32]), Some(Account::default())),
1402 (B256::from([6; 32]), None),
1403 ],
1404 storages: B256Map::default(),
1405 };
1406
1407 state1.extend_ref_and_sort(&state2);
1408
1409 assert_eq!(state1.accounts.len(), 6);
1411 assert_eq!(state1.accounts[0].0, B256::from([1; 32]));
1412 assert_eq!(state1.accounts[1].0, B256::from([2; 32]));
1413 assert_eq!(state1.accounts[2].0, B256::from([3; 32]));
1414 assert_eq!(state1.accounts[2].1.unwrap().nonce, 1); assert_eq!(state1.accounts[3].0, B256::from([4; 32]));
1416 assert_eq!(state1.accounts[4].0, B256::from([5; 32]));
1417 assert_eq!(state1.accounts[4].1, None);
1418 assert_eq!(state1.accounts[5].0, B256::from([6; 32]));
1419 assert_eq!(state1.accounts[5].1, None);
1420 }
1421
1422 #[test]
1423 fn test_hashed_storage_sorted_extend_ref() {
1424 let mut storage1 = HashedStorageSorted {
1426 storage_slots: vec![
1427 (B256::from([1; 32]), U256::from(10)),
1428 (B256::from([3; 32]), U256::from(30)),
1429 (B256::from([5; 32]), U256::ZERO),
1430 ],
1431 wiped: false,
1432 };
1433
1434 let storage2 = HashedStorageSorted {
1435 storage_slots: vec![
1436 (B256::from([2; 32]), U256::from(20)),
1437 (B256::from([3; 32]), U256::from(300)), (B256::from([4; 32]), U256::from(40)),
1439 (B256::from([6; 32]), U256::ZERO),
1440 ],
1441 wiped: false,
1442 };
1443
1444 storage1.extend_ref(&storage2);
1445
1446 assert_eq!(storage1.storage_slots.len(), 6);
1447 assert_eq!(storage1.storage_slots[0].0, B256::from([1; 32]));
1448 assert_eq!(storage1.storage_slots[0].1, U256::from(10));
1449 assert_eq!(storage1.storage_slots[1].0, B256::from([2; 32]));
1450 assert_eq!(storage1.storage_slots[1].1, U256::from(20));
1451 assert_eq!(storage1.storage_slots[2].0, B256::from([3; 32]));
1452 assert_eq!(storage1.storage_slots[2].1, U256::from(300)); assert_eq!(storage1.storage_slots[3].0, B256::from([4; 32]));
1454 assert_eq!(storage1.storage_slots[3].1, U256::from(40));
1455 assert_eq!(storage1.storage_slots[4].0, B256::from([5; 32]));
1456 assert_eq!(storage1.storage_slots[4].1, U256::ZERO);
1457 assert_eq!(storage1.storage_slots[5].0, B256::from([6; 32]));
1458 assert_eq!(storage1.storage_slots[5].1, U256::ZERO);
1459 assert!(!storage1.wiped);
1460
1461 let mut storage3 = HashedStorageSorted {
1463 storage_slots: vec![
1464 (B256::from([1; 32]), U256::from(10)),
1465 (B256::from([2; 32]), U256::ZERO),
1466 ],
1467 wiped: false,
1468 };
1469
1470 let storage4 = HashedStorageSorted {
1471 storage_slots: vec![
1472 (B256::from([3; 32]), U256::from(30)),
1473 (B256::from([4; 32]), U256::ZERO),
1474 ],
1475 wiped: true,
1476 };
1477
1478 storage3.extend_ref(&storage4);
1479
1480 assert!(storage3.wiped);
1481 assert_eq!(storage3.storage_slots.len(), 2);
1483 assert_eq!(storage3.storage_slots[0].0, B256::from([3; 32]));
1484 assert_eq!(storage3.storage_slots[0].1, U256::from(30));
1485 assert_eq!(storage3.storage_slots[1].0, B256::from([4; 32]));
1486 assert_eq!(storage3.storage_slots[1].1, U256::ZERO);
1487 }
1488
1489 #[test]
1491 fn test_hashed_post_state_extend_from_sorted_with_accounts() {
1492 let addr1 = B256::random();
1493 let addr2 = B256::random();
1494
1495 let mut state = HashedPostState::default();
1496 state.accounts.insert(addr1, Some(Default::default()));
1497
1498 let mut sorted_state = HashedPostStateSorted::default();
1499 sorted_state.accounts.push((addr2, Some(Default::default())));
1500
1501 state.extend_from_sorted(&sorted_state);
1502
1503 assert_eq!(state.accounts.len(), 2);
1504 assert!(state.accounts.contains_key(&addr1));
1505 assert!(state.accounts.contains_key(&addr2));
1506 }
1507
1508 #[test]
1510 fn test_hashed_post_state_extend_from_sorted_with_destroyed_accounts() {
1511 let addr1 = B256::random();
1512
1513 let mut state = HashedPostState::default();
1514
1515 let mut sorted_state = HashedPostStateSorted::default();
1516 sorted_state.accounts.push((addr1, None));
1517
1518 state.extend_from_sorted(&sorted_state);
1519
1520 assert!(state.accounts.contains_key(&addr1));
1521 assert_eq!(state.accounts.get(&addr1), Some(&None));
1522 }
1523
1524 #[test]
1526 fn test_hashed_storage_extend_from_sorted_non_wiped() {
1527 let slot1 = B256::random();
1528 let slot2 = B256::random();
1529 let slot3 = B256::random();
1530
1531 let mut storage = HashedStorage::from_iter(false, [(slot1, U256::from(100))]);
1532
1533 let sorted = HashedStorageSorted {
1534 storage_slots: vec![(slot2, U256::from(200)), (slot3, U256::ZERO)],
1535 wiped: false,
1536 };
1537
1538 storage.extend_from_sorted(&sorted);
1539
1540 assert!(!storage.wiped);
1541 assert_eq!(storage.storage.len(), 3);
1542 assert_eq!(storage.storage.get(&slot1), Some(&U256::from(100)));
1543 assert_eq!(storage.storage.get(&slot2), Some(&U256::from(200)));
1544 assert_eq!(storage.storage.get(&slot3), Some(&U256::ZERO));
1545 }
1546
1547 #[test]
1549 fn test_hashed_storage_extend_from_sorted_wiped() {
1550 let slot1 = B256::random();
1551 let slot2 = B256::random();
1552
1553 let mut storage = HashedStorage::from_iter(false, [(slot1, U256::from(100))]);
1554
1555 let sorted =
1556 HashedStorageSorted { storage_slots: vec![(slot2, U256::from(200))], wiped: true };
1557
1558 storage.extend_from_sorted(&sorted);
1559
1560 assert!(storage.wiped);
1561 assert_eq!(storage.storage.len(), 1);
1563 assert_eq!(storage.storage.get(&slot2), Some(&U256::from(200)));
1564 }
1565
1566 #[test]
1567 fn test_hashed_post_state_chunking_length() {
1568 let addr1 = B256::from([1; 32]);
1569 let addr2 = B256::from([2; 32]);
1570 let addr3 = B256::from([3; 32]);
1571 let addr4 = B256::from([4; 32]);
1572 let slot1 = B256::from([1; 32]);
1573 let slot2 = B256::from([2; 32]);
1574 let slot3 = B256::from([3; 32]);
1575
1576 let state = HashedPostState {
1577 accounts: B256Map::from_iter([(addr1, None), (addr2, None), (addr4, None)]),
1578 storages: B256Map::from_iter([
1579 (
1580 addr1,
1581 HashedStorage {
1582 wiped: false,
1583 storage: B256Map::from_iter([
1584 (slot1, U256::ZERO),
1585 (slot2, U256::ZERO),
1586 (slot3, U256::ZERO),
1587 ]),
1588 },
1589 ),
1590 (
1591 addr2,
1592 HashedStorage {
1593 wiped: true,
1594 storage: B256Map::from_iter([
1595 (slot1, U256::ZERO),
1596 (slot2, U256::ZERO),
1597 (slot3, U256::ZERO),
1598 ]),
1599 },
1600 ),
1601 (
1602 addr3,
1603 HashedStorage {
1604 wiped: false,
1605 storage: B256Map::from_iter([
1606 (slot1, U256::ZERO),
1607 (slot2, U256::ZERO),
1608 (slot3, U256::ZERO),
1609 ]),
1610 },
1611 ),
1612 ]),
1613 };
1614
1615 let chunking_length = state.chunking_length();
1616 for size in 1..=state.clone().chunks(1).count() {
1617 let chunk_count = state.clone().chunks(size).count();
1618 let expected_count = chunking_length.div_ceil(size);
1619 assert_eq!(
1620 chunk_count, expected_count,
1621 "chunking_length: {}, size: {}",
1622 chunking_length, size
1623 );
1624 }
1625 }
1626
1627 #[test]
1628 fn test_clone_into_sorted_equivalence() {
1629 let addr1 = B256::from([1; 32]);
1630 let addr2 = B256::from([2; 32]);
1631 let addr3 = B256::from([3; 32]);
1632 let slot1 = B256::from([1; 32]);
1633 let slot2 = B256::from([2; 32]);
1634 let slot3 = B256::from([3; 32]);
1635
1636 let state = HashedPostState {
1637 accounts: B256Map::from_iter([
1638 (addr1, Some(Account { nonce: 1, balance: U256::from(100), bytecode_hash: None })),
1639 (addr2, None),
1640 (addr3, Some(Account::default())),
1641 ]),
1642 storages: B256Map::from_iter([
1643 (
1644 addr1,
1645 HashedStorage {
1646 wiped: false,
1647 storage: B256Map::from_iter([
1648 (slot1, U256::from(10)),
1649 (slot2, U256::from(20)),
1650 ]),
1651 },
1652 ),
1653 (
1654 addr2,
1655 HashedStorage {
1656 wiped: true,
1657 storage: B256Map::from_iter([(slot3, U256::ZERO)]),
1658 },
1659 ),
1660 ]),
1661 };
1662
1663 let sorted_via_clone = state.clone().into_sorted();
1665 let sorted_via_clone_into = state.clone_into_sorted();
1666
1667 assert_eq!(sorted_via_clone, sorted_via_clone_into);
1668
1669 assert_eq!(state.accounts.len(), 3);
1671 assert_eq!(state.storages.len(), 2);
1672 }
1673
1674 #[test]
1675 fn test_hashed_storage_clone_into_sorted_equivalence() {
1676 let slot1 = B256::from([1; 32]);
1677 let slot2 = B256::from([2; 32]);
1678 let slot3 = B256::from([3; 32]);
1679
1680 let storage = HashedStorage {
1681 wiped: true,
1682 storage: B256Map::from_iter([
1683 (slot1, U256::from(100)),
1684 (slot2, U256::ZERO),
1685 (slot3, U256::from(300)),
1686 ]),
1687 };
1688
1689 let sorted_via_clone = storage.clone().into_sorted();
1691 let sorted_via_clone_into = storage.clone_into_sorted();
1692
1693 assert_eq!(sorted_via_clone, sorted_via_clone_into);
1694
1695 assert_eq!(storage.storage.len(), 3);
1697 assert!(storage.wiped);
1698 }
1699}
1700
1701#[cfg(feature = "serde-bincode-compat")]
1703pub mod serde_bincode_compat {
1704 use super::Account;
1705 use alloc::borrow::Cow;
1706 use alloy_primitives::{map::B256Map, B256, U256};
1707 use serde::{Deserialize, Deserializer, Serialize, Serializer};
1708 use serde_with::{DeserializeAs, SerializeAs};
1709
1710 #[derive(Debug, Serialize, Deserialize)]
1726 pub struct HashedPostState<'a> {
1727 accounts: Cow<'a, B256Map<Option<Account>>>,
1728 storages: B256Map<HashedStorage<'a>>,
1729 }
1730
1731 impl<'a> From<&'a super::HashedPostState> for HashedPostState<'a> {
1732 fn from(value: &'a super::HashedPostState) -> Self {
1733 Self {
1734 accounts: Cow::Borrowed(&value.accounts),
1735 storages: value.storages.iter().map(|(k, v)| (*k, v.into())).collect(),
1736 }
1737 }
1738 }
1739
1740 impl<'a> From<HashedPostState<'a>> for super::HashedPostState {
1741 fn from(value: HashedPostState<'a>) -> Self {
1742 Self {
1743 accounts: value.accounts.into_owned(),
1744 storages: value.storages.into_iter().map(|(k, v)| (k, v.into())).collect(),
1745 }
1746 }
1747 }
1748
1749 impl SerializeAs<super::HashedPostState> for HashedPostState<'_> {
1750 fn serialize_as<S>(
1751 source: &super::HashedPostState,
1752 serializer: S,
1753 ) -> Result<S::Ok, S::Error>
1754 where
1755 S: Serializer,
1756 {
1757 HashedPostState::from(source).serialize(serializer)
1758 }
1759 }
1760
1761 impl<'de> DeserializeAs<'de, super::HashedPostState> for HashedPostState<'de> {
1762 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedPostState, D::Error>
1763 where
1764 D: Deserializer<'de>,
1765 {
1766 HashedPostState::deserialize(deserializer).map(Into::into)
1767 }
1768 }
1769
1770 #[derive(Debug, Serialize, Deserialize)]
1786 pub struct HashedStorage<'a> {
1787 wiped: bool,
1788 storage: Cow<'a, B256Map<U256>>,
1789 }
1790
1791 impl<'a> From<&'a super::HashedStorage> for HashedStorage<'a> {
1792 fn from(value: &'a super::HashedStorage) -> Self {
1793 Self { wiped: value.wiped, storage: Cow::Borrowed(&value.storage) }
1794 }
1795 }
1796
1797 impl<'a> From<HashedStorage<'a>> for super::HashedStorage {
1798 fn from(value: HashedStorage<'a>) -> Self {
1799 Self { wiped: value.wiped, storage: value.storage.into_owned() }
1800 }
1801 }
1802
1803 impl SerializeAs<super::HashedStorage> for HashedStorage<'_> {
1804 fn serialize_as<S>(source: &super::HashedStorage, serializer: S) -> Result<S::Ok, S::Error>
1805 where
1806 S: Serializer,
1807 {
1808 HashedStorage::from(source).serialize(serializer)
1809 }
1810 }
1811
1812 impl<'de> DeserializeAs<'de, super::HashedStorage> for HashedStorage<'de> {
1813 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedStorage, D::Error>
1814 where
1815 D: Deserializer<'de>,
1816 {
1817 HashedStorage::deserialize(deserializer).map(Into::into)
1818 }
1819 }
1820
1821 #[derive(Debug, Serialize, Deserialize)]
1837 pub struct HashedPostStateSorted<'a> {
1838 accounts: Cow<'a, [(B256, Option<Account>)]>,
1839 storages: B256Map<HashedStorageSorted<'a>>,
1840 }
1841
1842 impl<'a> From<&'a super::HashedPostStateSorted> for HashedPostStateSorted<'a> {
1843 fn from(value: &'a super::HashedPostStateSorted) -> Self {
1844 Self {
1845 accounts: Cow::Borrowed(&value.accounts),
1846 storages: value.storages.iter().map(|(k, v)| (*k, v.into())).collect(),
1847 }
1848 }
1849 }
1850
1851 impl<'a> From<HashedPostStateSorted<'a>> for super::HashedPostStateSorted {
1852 fn from(value: HashedPostStateSorted<'a>) -> Self {
1853 Self {
1854 accounts: value.accounts.into_owned(),
1855 storages: value.storages.into_iter().map(|(k, v)| (k, v.into())).collect(),
1856 }
1857 }
1858 }
1859
1860 impl SerializeAs<super::HashedPostStateSorted> for HashedPostStateSorted<'_> {
1861 fn serialize_as<S>(
1862 source: &super::HashedPostStateSorted,
1863 serializer: S,
1864 ) -> Result<S::Ok, S::Error>
1865 where
1866 S: Serializer,
1867 {
1868 HashedPostStateSorted::from(source).serialize(serializer)
1869 }
1870 }
1871
1872 impl<'de> DeserializeAs<'de, super::HashedPostStateSorted> for HashedPostStateSorted<'de> {
1873 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedPostStateSorted, D::Error>
1874 where
1875 D: Deserializer<'de>,
1876 {
1877 HashedPostStateSorted::deserialize(deserializer).map(Into::into)
1878 }
1879 }
1880
1881 #[derive(Debug, Serialize, Deserialize)]
1897 pub struct HashedStorageSorted<'a> {
1898 storage_slots: Cow<'a, [(B256, U256)]>,
1899 wiped: bool,
1900 }
1901
1902 impl<'a> From<&'a super::HashedStorageSorted> for HashedStorageSorted<'a> {
1903 fn from(value: &'a super::HashedStorageSorted) -> Self {
1904 Self { storage_slots: Cow::Borrowed(&value.storage_slots), wiped: value.wiped }
1905 }
1906 }
1907
1908 impl<'a> From<HashedStorageSorted<'a>> for super::HashedStorageSorted {
1909 fn from(value: HashedStorageSorted<'a>) -> Self {
1910 Self { storage_slots: value.storage_slots.into_owned(), wiped: value.wiped }
1911 }
1912 }
1913
1914 impl SerializeAs<super::HashedStorageSorted> for HashedStorageSorted<'_> {
1915 fn serialize_as<S>(
1916 source: &super::HashedStorageSorted,
1917 serializer: S,
1918 ) -> Result<S::Ok, S::Error>
1919 where
1920 S: Serializer,
1921 {
1922 HashedStorageSorted::from(source).serialize(serializer)
1923 }
1924 }
1925
1926 impl<'de> DeserializeAs<'de, super::HashedStorageSorted> for HashedStorageSorted<'de> {
1927 fn deserialize_as<D>(deserializer: D) -> Result<super::HashedStorageSorted, D::Error>
1928 where
1929 D: Deserializer<'de>,
1930 {
1931 HashedStorageSorted::deserialize(deserializer).map(Into::into)
1932 }
1933 }
1934
1935 #[cfg(test)]
1936 mod tests {
1937 use crate::{
1938 hashed_state::{
1939 HashedPostState, HashedPostStateSorted, HashedStorage, HashedStorageSorted,
1940 },
1941 serde_bincode_compat,
1942 };
1943 use alloy_primitives::{B256, U256};
1944 use reth_primitives_traits::Account;
1945 use serde::{Deserialize, Serialize};
1946 use serde_with::serde_as;
1947
1948 #[test]
1949 fn test_hashed_post_state_bincode_roundtrip() {
1950 #[serde_as]
1951 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
1952 struct Data {
1953 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedPostState")]
1954 hashed_state: HashedPostState,
1955 }
1956
1957 let mut data = Data { hashed_state: HashedPostState::default() };
1958 let encoded = bincode::serialize(&data).unwrap();
1959 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1960 assert_eq!(decoded, data);
1961
1962 data.hashed_state.accounts.insert(B256::random(), Some(Account::default()));
1963 let encoded = bincode::serialize(&data).unwrap();
1964 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1965 assert_eq!(decoded, data);
1966
1967 data.hashed_state.storages.insert(B256::random(), HashedStorage::default());
1968 let encoded = bincode::serialize(&data).unwrap();
1969 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1970 assert_eq!(decoded, data);
1971 }
1972
1973 #[test]
1974 fn test_hashed_storage_bincode_roundtrip() {
1975 #[serde_as]
1976 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
1977 struct Data {
1978 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedStorage")]
1979 hashed_storage: HashedStorage,
1980 }
1981
1982 let mut data = Data { hashed_storage: HashedStorage::default() };
1983 let encoded = bincode::serialize(&data).unwrap();
1984 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1985 assert_eq!(decoded, data);
1986
1987 data.hashed_storage.wiped = true;
1988 let encoded = bincode::serialize(&data).unwrap();
1989 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1990 assert_eq!(decoded, data);
1991
1992 data.hashed_storage.storage.insert(B256::random(), U256::from(1));
1993 let encoded = bincode::serialize(&data).unwrap();
1994 let decoded: Data = bincode::deserialize(&encoded).unwrap();
1995 assert_eq!(decoded, data);
1996 }
1997
1998 #[test]
1999 fn test_hashed_post_state_sorted_bincode_roundtrip() {
2000 #[serde_as]
2001 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
2002 struct Data {
2003 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedPostStateSorted")]
2004 hashed_state: HashedPostStateSorted,
2005 }
2006
2007 let mut data = Data { hashed_state: HashedPostStateSorted::default() };
2008 let encoded = bincode::serialize(&data).unwrap();
2009 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2010 assert_eq!(decoded, data);
2011
2012 data.hashed_state.accounts.push((B256::random(), Some(Account::default())));
2013 data.hashed_state
2014 .accounts
2015 .push((B256::random(), Some(Account { nonce: 1, ..Default::default() })));
2016 let encoded = bincode::serialize(&data).unwrap();
2017 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2018 assert_eq!(decoded, data);
2019
2020 data.hashed_state.storages.insert(
2021 B256::random(),
2022 HashedStorageSorted {
2023 storage_slots: vec![(B256::from([1; 32]), U256::from(10))],
2024 wiped: false,
2025 },
2026 );
2027 let encoded = bincode::serialize(&data).unwrap();
2028 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2029 assert_eq!(decoded, data);
2030 }
2031
2032 #[test]
2033 fn test_hashed_storage_sorted_bincode_roundtrip() {
2034 #[serde_as]
2035 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
2036 struct Data {
2037 #[serde_as(as = "serde_bincode_compat::hashed_state::HashedStorageSorted")]
2038 hashed_storage: HashedStorageSorted,
2039 }
2040
2041 let mut data = Data {
2042 hashed_storage: HashedStorageSorted { storage_slots: Vec::new(), wiped: false },
2043 };
2044 let encoded = bincode::serialize(&data).unwrap();
2045 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2046 assert_eq!(decoded, data);
2047
2048 data.hashed_storage.wiped = true;
2049 let encoded = bincode::serialize(&data).unwrap();
2050 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2051 assert_eq!(decoded, data);
2052
2053 data.hashed_storage.storage_slots.push((B256::random(), U256::from(1)));
2054 let encoded = bincode::serialize(&data).unwrap();
2055 let decoded: Data = bincode::deserialize(&encoded).unwrap();
2056 assert_eq!(decoded, data);
2057 }
2058 }
2059}