reth_trie_common/bundle_state/
reverts.rs1use super::{
2 changes::PlainStorageRevert, AccountStatus, BundleAccount, PlainStateReverts,
3 StorageWithOriginalValues,
4};
5use alloc::vec::Vec;
6use alloy_primitives::{map::U256Map, Address, U256};
7use core::{
8 cmp::Ordering,
9 ops::{Deref, DerefMut},
10};
11use evm2::evm::AccountInfo;
12
13#[derive(Clone, Debug, Default, Eq)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct Reverts(Vec<Vec<(Address, AccountRevert)>>);
17
18impl Deref for Reverts {
19 type Target = Vec<Vec<(Address, AccountRevert)>>;
20
21 fn deref(&self) -> &Self::Target {
22 &self.0
23 }
24}
25
26impl DerefMut for Reverts {
27 fn deref_mut(&mut self) -> &mut Self::Target {
28 &mut self.0
29 }
30}
31
32impl Reverts {
33 pub const fn new(reverts: Vec<Vec<(Address, AccountRevert)>>) -> Self {
35 Self(reverts)
36 }
37
38 pub fn sort(&mut self) {
40 for revert in &mut self.0 {
41 revert.sort_by_key(|(address, _)| *address);
42 }
43 }
44
45 pub fn extend(&mut self, other: Reverts) {
47 self.0.extend(other.0);
48 }
49
50 pub fn to_plain_state_reverts(&self) -> PlainStateReverts {
54 let mut state_reverts = PlainStateReverts::with_capacity(self.0.len());
55 for reverts in &self.0 {
56 let mut accounts = Vec::with_capacity(reverts.len());
58 let mut storage = Vec::with_capacity(reverts.len());
59 for (address, revert_account) in reverts {
60 match &revert_account.account {
61 AccountInfoRevert::RevertTo(acc) => {
62 accounts.push((*address, Some(acc.clone())))
65 }
66 AccountInfoRevert::DeleteIt => accounts.push((*address, None)),
67 AccountInfoRevert::DoNothing => (),
68 }
69 if revert_account.wipe_storage || !revert_account.storage.is_empty() {
70 storage.push(PlainStorageRevert {
71 address: *address,
72 wiped: revert_account.wipe_storage,
73 storage_revert: revert_account
74 .storage
75 .iter()
76 .map(|(k, v)| (*k, *v))
77 .collect::<Vec<_>>(),
78 });
79 }
80 }
81 state_reverts.accounts.push(accounts);
82 state_reverts.storage.push(storage);
83 }
84 state_reverts
85 }
86
87 pub fn content_eq(&self, other: &Self) -> bool {
89 if self.0.len() != other.0.len() {
90 return false;
91 }
92
93 for (self_transition, other_transition) in self.0.iter().zip(other.0.iter()) {
94 if self_transition.len() != other_transition.len() {
95 return false;
96 }
97
98 let mut self_transition = self_transition.clone();
99 let mut other_transition = other_transition.clone();
100 self_transition.sort_by(|(addr1, revert1), (addr2, revert2)| {
102 addr1.cmp(addr2).then_with(|| revert1.cmp(revert2))
103 });
104 other_transition.sort_by(|(addr1, revert1), (addr2, revert2)| {
105 addr1.cmp(addr2).then_with(|| revert1.cmp(revert2))
106 });
107
108 if self_transition != other_transition {
110 return false;
111 }
112 }
113
114 true
115 }
116
117 #[deprecated = "Use `to_plain_state_reverts` instead"]
121 pub fn into_plain_state_reverts(self) -> PlainStateReverts {
122 self.to_plain_state_reverts()
123 }
124}
125
126impl PartialEq for Reverts {
127 fn eq(&self, other: &Self) -> bool {
128 self.content_eq(other)
129 }
130}
131
132#[derive(Clone, Default, Debug, PartialEq, Eq)]
143#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
144pub struct AccountRevert {
145 pub account: AccountInfoRevert,
147 pub storage: U256Map<RevertToSlot>,
149 pub previous_status: AccountStatus,
151 pub wipe_storage: bool,
153}
154
155impl AccountRevert {
156 pub fn size_hint(&self) -> usize {
160 1 + self.storage.len()
161 }
162
163 pub fn new_selfdestructed_again(
166 status: AccountStatus,
167 account: AccountInfoRevert,
168 mut previous_storage: StorageWithOriginalValues,
169 updated_storage: StorageWithOriginalValues,
170 ) -> Self {
171 let mut previous_storage: U256Map<RevertToSlot> = previous_storage
174 .drain()
175 .map(|(key, value)| (key, RevertToSlot::Some(value.present_value)))
176 .collect();
177 for (key, _) in updated_storage {
178 previous_storage.entry(key).or_insert(RevertToSlot::Destroyed);
179 }
180 AccountRevert {
181 account,
182 storage: previous_storage,
183 previous_status: status,
184 wipe_storage: false,
185 }
186 }
187
188 pub fn new_selfdestructed_from_bundle(
190 account_info_revert: AccountInfoRevert,
191 bundle_account: &mut BundleAccount,
192 updated_storage: &StorageWithOriginalValues,
193 ) -> Option<Self> {
194 match bundle_account.status {
195 AccountStatus::InMemoryChange |
196 AccountStatus::Changed |
197 AccountStatus::LoadedEmptyEIP161 |
198 AccountStatus::Loaded => {
199 let mut ret = AccountRevert::new_selfdestructed_again(
200 bundle_account.status,
201 account_info_revert,
202 core::mem::take(&mut bundle_account.storage),
203 updated_storage.clone(),
204 );
205 ret.wipe_storage = true;
206 Some(ret)
207 }
208 _ => None,
209 }
210 }
211
212 pub fn new_selfdestructed(
214 status: AccountStatus,
215 account: AccountInfoRevert,
216 mut storage: StorageWithOriginalValues,
217 ) -> Self {
218 let previous_storage = storage
220 .iter_mut()
221 .map(|(key, value)| {
222 (*key, RevertToSlot::Some(value.present_value))
224 })
225 .collect();
226
227 Self { account, storage: previous_storage, previous_status: status, wipe_storage: true }
228 }
229
230 pub fn is_empty(&self) -> bool {
235 self.account == AccountInfoRevert::DoNothing &&
236 self.storage.is_empty() &&
237 !self.wipe_storage
238 }
239}
240
241impl PartialOrd for AccountRevert {
243 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
244 Some(self.cmp(other))
245 }
246}
247
248impl Ord for AccountRevert {
250 fn cmp(&self, other: &Self) -> Ordering {
251 if let Some(ord) = self.account.partial_cmp(&other.account) {
253 if ord != Ordering::Equal {
254 return ord;
255 }
256 }
257
258 let mut self_storage: Vec<_> = self.storage.iter().collect();
260 let mut other_storage: Vec<_> = other.storage.iter().collect();
261
262 self_storage.sort_by(|(k1, v1), (k2, v2)| k1.cmp(k2).then_with(|| v1.cmp(v2)));
264 other_storage.sort_by(|(k1, v1), (k2, v2)| k1.cmp(k2).then_with(|| v1.cmp(v2)));
265
266 for (self_entry, other_entry) in self_storage.iter().zip(other_storage.iter()) {
268 let key_ord = self_entry.0.cmp(other_entry.0);
269 if key_ord != Ordering::Equal {
270 return key_ord;
271 }
272 let value_ord = self_entry.1.cmp(other_entry.1);
273 if value_ord != Ordering::Equal {
274 return value_ord;
275 }
276 }
277
278 self_storage
280 .len()
281 .cmp(&other_storage.len())
282 .then_with(|| self.previous_status.cmp(&other.previous_status))
283 .then_with(|| self.wipe_storage.cmp(&other.wipe_storage))
284 }
285}
286
287#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
290#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
291pub enum AccountInfoRevert {
292 #[default]
293 DoNothing,
295 DeleteIt,
297 RevertTo(AccountInfo),
299}
300
301impl PartialOrd for AccountInfoRevert {
302 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
303 Some(self.cmp(other))
304 }
305}
306
307impl Ord for AccountInfoRevert {
310 fn cmp(&self, other: &Self) -> Ordering {
311 match (self, other) {
312 (Self::RevertTo(a), Self::RevertTo(b)) => {
313 let order = a
314 .balance
315 .cmp(&b.balance)
316 .then_with(|| a.nonce.cmp(&b.nonce))
317 .then_with(|| a.code_hash.cmp(&b.code_hash));
318 #[cfg(feature = "account-ext")]
319 let order = order.then_with(|| a.extension.as_ref().cmp(b.extension.as_ref()));
320 order
321 }
322 (Self::DoNothing, Self::DoNothing) | (Self::DeleteIt, Self::DeleteIt) => {
323 Ordering::Equal
324 }
325 (Self::DoNothing, _) | (Self::DeleteIt, Self::RevertTo(_)) => Ordering::Less,
326 (_, Self::DoNothing) | (Self::RevertTo(_), Self::DeleteIt) => Ordering::Greater,
327 }
328 }
329}
330
331#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
341#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
342pub enum RevertToSlot {
343 Some(U256),
345 Destroyed,
347}
348
349impl RevertToSlot {
350 pub const fn to_previous_value(self) -> U256 {
352 match self {
353 RevertToSlot::Some(value) => value,
354 RevertToSlot::Destroyed => U256::ZERO,
355 }
356 }
357}
358
359#[cfg(test)]
360mod test {
361 use super::*;
362
363 #[test]
364 fn content_eq_ignores_order_of_same_address() {
365 let address = Address::with_last_byte(1);
366 let do_nothing = AccountRevert::default();
367 let delete_it =
368 AccountRevert { account: AccountInfoRevert::DeleteIt, ..Default::default() };
369 let a =
370 Reverts::new(vec![vec![(address, do_nothing.clone()), (address, delete_it.clone())]]);
371 let b = Reverts::new(vec![vec![(address, delete_it), (address, do_nothing)]]);
372 assert_eq!(a, b);
373 }
374}