reth_provider/changesets_utils/
state_reverts.rs1use alloy_primitives::{B256, U256};
2use reth_trie::bundle_state::RevertToSlot;
3use std::{cmp::Ordering, iter::Peekable};
4
5#[expect(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, U256)>,
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, U256)> {
28 self.reverts.next().map(|(key, revert)| (key, revert.to_previous_value()))
29 }
30
31 fn next_wiped(&mut self) -> Option<(B256, U256)> {
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, U256)>,
41{
42 type Item = (B256, U256);
43
44 fn next(&mut self) -> Option<Self::Item> {
47 match (self.reverts.peek(), self.wiped.peek()) {
48 (Some(revert), Some(wiped)) => {
49 match revert.0.cmp(&wiped.0) {
51 Ordering::Less => self.next_revert(),
52 Ordering::Greater => self.next_wiped(),
53 Ordering::Equal => {
54 let (key, revert_to) = *revert;
56
57 let value = match revert_to {
58 RevertToSlot::Some(value) => value,
60 RevertToSlot::Destroyed => wiped.1,
62 };
63
64 self.next_revert();
66 self.next_wiped();
67
68 Some((key, value))
69 }
70 }
71 }
72 (Some(_revert), None) => self.next_revert(),
73 (None, Some(_wiped)) => self.next_wiped(),
74 (None, None) => None,
75 }
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_storage_reverts_iter_empty() {
85 let reverts: Vec<(B256, RevertToSlot)> = vec![];
87 let wiped: Vec<(B256, U256)> = vec![];
88
89 let iter = StorageRevertsIter::new(reverts, wiped);
91
92 let results: Vec<_> = iter.collect();
94
95 assert_eq!(results, vec![]);
97 }
98
99 #[test]
100 fn test_storage_reverts_iter_reverts_only() {
101 let reverts = vec![
103 (B256::from_slice(&[4; 32]), RevertToSlot::Destroyed),
104 (B256::from_slice(&[5; 32]), RevertToSlot::Some(U256::from(40))),
105 ];
106
107 let iter = StorageRevertsIter::new(reverts, vec![]);
109
110 let results: Vec<_> = iter.collect();
112
113 assert_eq!(
115 results,
116 vec![
117 (B256::from_slice(&[4; 32]), U256::ZERO), (B256::from_slice(&[5; 32]), U256::from(40)), ]
120 );
121 }
122
123 #[test]
124 fn test_storage_reverts_iter_wiped_only() {
125 let wiped = vec![
127 (B256::from_slice(&[6; 32]), U256::from(50)),
128 (B256::from_slice(&[7; 32]), U256::from(60)),
129 ];
130
131 let iter = StorageRevertsIter::new(vec![], wiped);
133
134 let results: Vec<_> = iter.collect();
136
137 assert_eq!(
139 results,
140 vec![
141 (B256::from_slice(&[6; 32]), U256::from(50)), (B256::from_slice(&[7; 32]), U256::from(60)), ]
144 );
145 }
146
147 #[test]
148 fn test_storage_reverts_iter_interleaved() {
149 let reverts = vec![
151 (B256::from_slice(&[8; 32]), RevertToSlot::Some(U256::from(70))),
152 (B256::from_slice(&[9; 32]), RevertToSlot::Some(U256::from(80))),
153 (B256::from_slice(&[15; 32]), RevertToSlot::Some(U256::from(90))),
155 ];
156
157 let wiped = vec![
158 (B256::from_slice(&[8; 32]), U256::from(75)), (B256::from_slice(&[10; 32]), U256::from(85)), ];
161
162 let iter = StorageRevertsIter::new(reverts, wiped);
164
165 let results: Vec<_> = iter.collect();
167
168 assert_eq!(
170 results,
171 vec![
172 (B256::from_slice(&[8; 32]), U256::from(70)), (B256::from_slice(&[9; 32]), U256::from(80)), (B256::from_slice(&[10; 32]), U256::from(85)), (B256::from_slice(&[15; 32]), U256::from(90)), ]
177 );
178 }
179}