reth_provider/bundle_state/
state_reverts.rs1use alloy_primitives::B256;
2use revm_database::states::RevertToSlot;
3use revm_state::FlaggedStorage;
4use std::iter::Peekable;
5
6#[expect(missing_debug_implementations)]
9pub struct StorageRevertsIter<R: Iterator, W: Iterator> {
10 reverts: Peekable<R>,
11 wiped: Peekable<W>,
12}
13
14impl<R, W> StorageRevertsIter<R, W>
15where
16 R: Iterator<Item = (B256, RevertToSlot)>,
17 W: Iterator<Item = (B256, FlaggedStorage)>,
18{
19 pub fn new(
21 reverts: impl IntoIterator<IntoIter = R>,
22 wiped: impl IntoIterator<IntoIter = W>,
23 ) -> Self {
24 Self { reverts: reverts.into_iter().peekable(), wiped: wiped.into_iter().peekable() }
25 }
26
27 fn next_revert(&mut self) -> Option<(B256, FlaggedStorage)> {
29 self.reverts.next().map(|(key, revert)| (key, revert.to_previous_value()))
30 }
31
32 fn next_wiped(&mut self) -> Option<(B256, FlaggedStorage)> {
34 self.wiped.next()
35 }
36}
37
38impl<R, W> Iterator for StorageRevertsIter<R, W>
39where
40 R: Iterator<Item = (B256, RevertToSlot)>,
41 W: Iterator<Item = (B256, FlaggedStorage)>,
42{
43 type Item = (B256, FlaggedStorage);
44
45 fn next(&mut self) -> Option<Self::Item> {
48 match (self.reverts.peek(), self.wiped.peek()) {
49 (Some(revert), Some(wiped)) => {
50 use std::cmp::Ordering;
52 match revert.0.cmp(&wiped.0) {
53 Ordering::Less => self.next_revert(),
54 Ordering::Greater => self.next_wiped(),
55 Ordering::Equal => {
56 let (key, revert_to) = *revert;
58
59 let value = match revert_to {
60 RevertToSlot::Some(value) => value,
62 RevertToSlot::Destroyed => wiped.1,
64 };
65
66 self.next_revert();
68 self.next_wiped();
69
70 Some((key, value))
71 }
72 }
73 }
74 (Some(_revert), None) => self.next_revert(),
75 (None, Some(_wiped)) => self.next_wiped(),
76 (None, None) => None,
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_storage_reverts_iter_empty() {
87 let reverts: Vec<(B256, RevertToSlot)> = vec![];
89 let wiped: Vec<(B256, FlaggedStorage)> = vec![];
90
91 let iter = StorageRevertsIter::new(reverts, wiped);
93
94 let results: Vec<_> = iter.collect();
96
97 assert_eq!(results, vec![]);
99 }
100
101 #[test]
102 fn test_storage_reverts_iter_reverts_only() {
103 let reverts = vec![
105 (B256::from_slice(&[4; 32]), RevertToSlot::Destroyed),
106 (B256::from_slice(&[5; 32]), RevertToSlot::Some(FlaggedStorage::new_from_value(40))),
107 ];
108
109 let iter = StorageRevertsIter::new(reverts, vec![]);
111
112 let results: Vec<_> = iter.collect();
114
115 assert_eq!(
117 results,
118 vec![
119 (B256::from_slice(&[4; 32]), FlaggedStorage::ZERO), (B256::from_slice(&[5; 32]), FlaggedStorage::new_from_value(40)), ]
123 );
124 }
125
126 #[test]
127 fn test_storage_reverts_iter_wiped_only() {
128 let wiped = vec![
130 (B256::from_slice(&[6; 32]), FlaggedStorage::new_from_value(50)),
131 (B256::from_slice(&[7; 32]), FlaggedStorage::new_from_value(60)),
132 ];
133
134 let iter = StorageRevertsIter::new(vec![], wiped);
136
137 let results: Vec<_> = iter.collect();
139
140 assert_eq!(
142 results,
143 vec![
144 (B256::from_slice(&[6; 32]), FlaggedStorage::new_from_value(50)), (B256::from_slice(&[7; 32]), FlaggedStorage::new_from_value(60)), ]
149 );
150 }
151
152 #[test]
153 fn test_storage_reverts_iter_interleaved() {
154 let reverts = vec![
156 (B256::from_slice(&[8; 32]), RevertToSlot::Some(FlaggedStorage::new_from_value(70))),
157 (B256::from_slice(&[9; 32]), RevertToSlot::Some(FlaggedStorage::new_from_value(80))),
158 (B256::from_slice(&[15; 32]), RevertToSlot::Some(FlaggedStorage::new_from_value(90))),
160 ];
161
162 let wiped = vec![
163 (B256::from_slice(&[8; 32]), FlaggedStorage::new_from_value(75)), (B256::from_slice(&[10; 32]), FlaggedStorage::new_from_value(85)), ];
166
167 let iter = StorageRevertsIter::new(reverts, wiped);
169
170 let results: Vec<_> = iter.collect();
172
173 assert_eq!(
175 results,
176 vec![
177 (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)), ]
183 );
184 }
185}