Skip to main content

reth_provider/changesets_utils/
state_reverts.rs

1use alloy_primitives::{B256, U256};
2use reth_trie::bundle_state::RevertToSlot;
3use std::{cmp::Ordering, iter::Peekable};
4
5/// Iterator over storage reverts.
6/// See [`StorageRevertsIter::next`] for more details.
7#[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    /// Create a new iterator over storage reverts.
19    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    /// Consume next revert and return it.
27    fn next_revert(&mut self) -> Option<(B256, U256)> {
28        self.reverts.next().map(|(key, revert)| (key, revert.to_previous_value()))
29    }
30
31    /// Consume next wiped storage and return it.
32    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    /// Iterate over storage reverts and wiped entries and return items in the sorted order.
45    /// NOTE: The implementation assumes that inner iterators are already sorted.
46    fn next(&mut self) -> Option<Self::Item> {
47        match (self.reverts.peek(), self.wiped.peek()) {
48            (Some(revert), Some(wiped)) => {
49                // Compare the keys and return the lesser.
50                match revert.0.cmp(&wiped.0) {
51                    Ordering::Less => self.next_revert(),
52                    Ordering::Greater => self.next_wiped(),
53                    Ordering::Equal => {
54                        // Keys are the same, decide which one to return.
55                        let (key, revert_to) = *revert;
56
57                        let value = match revert_to {
58                            // If the slot is some, prefer the revert value.
59                            RevertToSlot::Some(value) => value,
60                            // If the slot was destroyed, prefer the database value.
61                            RevertToSlot::Destroyed => wiped.1,
62                        };
63
64                        // Consume both values from inner iterators.
65                        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        // Create empty sample data for reverts and wiped entries.
86        let reverts: Vec<(B256, RevertToSlot)> = vec![];
87        let wiped: Vec<(B256, U256)> = vec![];
88
89        // Create the iterator with the empty data.
90        let iter = StorageRevertsIter::new(reverts, wiped);
91
92        // Iterate and collect results into a vector for verification.
93        let results: Vec<_> = iter.collect();
94
95        // Verify that the results are empty.
96        assert_eq!(results, vec![]);
97    }
98
99    #[test]
100    fn test_storage_reverts_iter_reverts_only() {
101        // Create sample data for only reverts.
102        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        // Create the iterator with only reverts and no wiped entries.
108        let iter = StorageRevertsIter::new(reverts, vec![]);
109
110        // Iterate and collect results into a vector for verification.
111        let results: Vec<_> = iter.collect();
112
113        // Verify the output order and values.
114        assert_eq!(
115            results,
116            vec![
117                (B256::from_slice(&[4; 32]), U256::ZERO), // Revert slot previous value
118                (B256::from_slice(&[5; 32]), U256::from(40)), // Only revert present.
119            ]
120        );
121    }
122
123    #[test]
124    fn test_storage_reverts_iter_wiped_only() {
125        // Create sample data for only wiped entries.
126        let wiped = vec![
127            (B256::from_slice(&[6; 32]), U256::from(50)),
128            (B256::from_slice(&[7; 32]), U256::from(60)),
129        ];
130
131        // Create the iterator with only wiped entries and no reverts.
132        let iter = StorageRevertsIter::new(vec![], wiped);
133
134        // Iterate and collect results into a vector for verification.
135        let results: Vec<_> = iter.collect();
136
137        // Verify the output order and values.
138        assert_eq!(
139            results,
140            vec![
141                (B256::from_slice(&[6; 32]), U256::from(50)), // Only wiped present.
142                (B256::from_slice(&[7; 32]), U256::from(60)), // Only wiped present.
143            ]
144        );
145    }
146
147    #[test]
148    fn test_storage_reverts_iter_interleaved() {
149        // Create sample data for interleaved reverts and wiped entries.
150        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            // Some higher key than wiped
154            (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)), // Same key as revert
159            (B256::from_slice(&[10; 32]), U256::from(85)), // Wiped with new key
160        ];
161
162        // Create the iterator with the sample data.
163        let iter = StorageRevertsIter::new(reverts, wiped);
164
165        // Iterate and collect results into a vector for verification.
166        let results: Vec<_> = iter.collect();
167
168        // Verify the output order and values.
169        assert_eq!(
170            results,
171            vec![
172                (B256::from_slice(&[8; 32]), U256::from(70)), // Revert takes priority.
173                (B256::from_slice(&[9; 32]), U256::from(80)), // Only revert present.
174                (B256::from_slice(&[10; 32]), U256::from(85)), // Wiped entry.
175                (B256::from_slice(&[15; 32]), U256::from(90)), // Greater revert entry
176            ]
177        );
178    }
179}