reth_provider/bundle_state/
state_reverts.rs1use alloy_primitives::B256;
2use revm::{db::states::RevertToSlot, primitives::FlaggedStorage};
3use std::iter::Peekable;
4
5#[allow(missing_debug_implementations)]
8pub struct StorageRevertsIter<R: Iterator, W: Iterator> {
9 reverts: Peekable<R>,
10 wiped: Peekable<W>,
11}
12
13impl<R, W> StorageRevertsIter<R, W>
14where
15 R: Iterator<Item = (B256, RevertToSlot)>,
16 W: Iterator<Item = (B256, FlaggedStorage)>,
17{
18 pub fn new(
20 reverts: impl IntoIterator<IntoIter = R>,
21 wiped: impl IntoIterator<IntoIter = W>,
22 ) -> Self {
23 Self { reverts: reverts.into_iter().peekable(), wiped: wiped.into_iter().peekable() }
24 }
25
26 fn next_revert(&mut self) -> Option<(B256, FlaggedStorage)> {
28 self.reverts.next().map(|(key, revert)| (key, revert.to_previous_value()))
29 }
30
31 fn next_wiped(&mut self) -> Option<(B256, FlaggedStorage)> {
33 self.wiped.next()
34 }
35}
36
37impl<R, W> Iterator for StorageRevertsIter<R, W>
38where
39 R: Iterator<Item = (B256, RevertToSlot)>,
40 W: Iterator<Item = (B256, FlaggedStorage)>,
41{
42 type Item = (B256, FlaggedStorage);
43
44 fn next(&mut self) -> Option<Self::Item> {
47 match (self.reverts.peek(), self.wiped.peek()) {
48 (Some(revert), Some(wiped)) => {
49 use std::cmp::Ordering;
51 match revert.0.cmp(&wiped.0) {
52 Ordering::Less => self.next_revert(),
53 Ordering::Greater => self.next_wiped(),
54 Ordering::Equal => {
55 let (key, revert_to) = *revert;
57
58 let value = match revert_to {
59 RevertToSlot::Some(value) => value,
61 RevertToSlot::Destroyed => wiped.1,
63 };
64
65 self.next_revert();
67 self.next_wiped();
68
69 Some((key, value))
70 }
71 }
72 }
73 (Some(_revert), None) => self.next_revert(),
74 (None, Some(_wiped)) => self.next_wiped(),
75 (None, None) => None,
76 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn test_storage_reverts_iter_empty() {
86 let reverts: Vec<(B256, RevertToSlot)> = vec![];
88 let wiped: Vec<(B256, FlaggedStorage)> = vec![];
89
90 let iter = StorageRevertsIter::new(reverts, wiped);
92
93 let results: Vec<_> = iter.collect();
95
96 assert_eq!(results, vec![]);
98 }
99
100 #[test]
101 fn test_storage_reverts_iter_reverts_only() {
102 let reverts = vec![
104 (B256::from_slice(&[4; 32]), RevertToSlot::Destroyed),
105 (B256::from_slice(&[5; 32]), RevertToSlot::Some(FlaggedStorage::new_from_value(40))),
106 ];
107
108 let iter = StorageRevertsIter::new(reverts, vec![]);
110
111 let results: Vec<_> = iter.collect();
113
114 assert_eq!(
116 results,
117 vec![
118 (B256::from_slice(&[4; 32]), FlaggedStorage::ZERO), (B256::from_slice(&[5; 32]), FlaggedStorage::new_from_value(40)), ]
122 );
123 }
124
125 #[test]
126 fn test_storage_reverts_iter_wiped_only() {
127 let wiped = vec![
129 (B256::from_slice(&[6; 32]), FlaggedStorage::new_from_value(50)),
130 (B256::from_slice(&[7; 32]), FlaggedStorage::new_from_value(60)),
131 ];
132
133 let iter = StorageRevertsIter::new(vec![], wiped);
135
136 let results: Vec<_> = iter.collect();
138
139 assert_eq!(
141 results,
142 vec![
143 (B256::from_slice(&[6; 32]), FlaggedStorage::new_from_value(50)), (B256::from_slice(&[7; 32]), FlaggedStorage::new_from_value(60)), ]
148 );
149 }
150
151 #[test]
152 fn test_storage_reverts_iter_interleaved() {
153 let reverts = vec![
155 (B256::from_slice(&[8; 32]), RevertToSlot::Some(FlaggedStorage::new_from_value(70))),
156 (B256::from_slice(&[9; 32]), RevertToSlot::Some(FlaggedStorage::new_from_value(80))),
157 (B256::from_slice(&[15; 32]), RevertToSlot::Some(FlaggedStorage::new_from_value(90))),
159 ];
160
161 let wiped = vec![
162 (B256::from_slice(&[8; 32]), FlaggedStorage::new_from_value(75)), (B256::from_slice(&[10; 32]), FlaggedStorage::new_from_value(85)), ];
165
166 let iter = StorageRevertsIter::new(reverts, wiped);
168
169 let results: Vec<_> = iter.collect();
171
172 assert_eq!(
174 results,
175 vec![
176 (B256::from_slice(&[8; 32]), FlaggedStorage::new_from_value(70)), (B256::from_slice(&[9; 32]), FlaggedStorage::new_from_value(80)), (B256::from_slice(&[10; 32]), FlaggedStorage::new_from_value(85)), (B256::from_slice(&[15; 32]), FlaggedStorage::new_from_value(90)), ]
182 );
183 }
184}