1use super::{
2 changes::PlainStorageRevert, AccountStatus, BundleAccount, PlainStateReverts,
3 StorageWithOriginalValues,
4};
5use core::{
6 cmp::Ordering,
7 ops::{Deref, DerefMut},
8};
9use primitives::{Address, HashMap, U256};
10use state::AccountInfo;
11use std::vec::Vec;
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 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,
146 pub storage: HashMap<U256, RevertToSlot>,
147 pub previous_status: AccountStatus,
148 pub wipe_storage: bool,
149}
150
151impl AccountRevert {
152 pub fn size_hint(&self) -> usize {
156 1 + self.storage.len()
157 }
158
159 pub fn new_selfdestructed_again(
162 status: AccountStatus,
163 account: AccountInfoRevert,
164 mut previous_storage: StorageWithOriginalValues,
165 updated_storage: StorageWithOriginalValues,
166 ) -> Self {
167 let mut previous_storage: HashMap<U256, RevertToSlot> = previous_storage
170 .drain()
171 .map(|(key, value)| (key, RevertToSlot::Some(value.present_value)))
172 .collect();
173 for (key, _) in updated_storage {
174 previous_storage
175 .entry(key)
176 .or_insert(RevertToSlot::Destroyed);
177 }
178 AccountRevert {
179 account,
180 storage: previous_storage,
181 previous_status: status,
182 wipe_storage: false,
183 }
184 }
185
186 pub fn new_selfdestructed_from_bundle(
188 account_info_revert: AccountInfoRevert,
189 bundle_account: &mut BundleAccount,
190 updated_storage: &StorageWithOriginalValues,
191 ) -> Option<Self> {
192 match bundle_account.status {
193 AccountStatus::InMemoryChange
194 | AccountStatus::Changed
195 | AccountStatus::LoadedEmptyEIP161
196 | AccountStatus::Loaded => {
197 let mut ret = AccountRevert::new_selfdestructed_again(
198 bundle_account.status,
199 account_info_revert,
200 bundle_account.storage.drain().collect(),
201 updated_storage.clone(),
202 );
203 ret.wipe_storage = true;
204 Some(ret)
205 }
206 _ => None,
207 }
208 }
209
210 pub fn new_selfdestructed(
212 status: AccountStatus,
213 account: AccountInfoRevert,
214 mut storage: StorageWithOriginalValues,
215 ) -> Self {
216 let previous_storage = storage
218 .iter_mut()
219 .map(|(key, value)| {
220 (*key, RevertToSlot::Some(value.present_value))
222 })
223 .collect();
224
225 Self {
226 account,
227 storage: previous_storage,
228 previous_status: status,
229 wipe_storage: true,
230 }
231 }
232
233 pub fn is_empty(&self) -> bool {
238 self.account == AccountInfoRevert::DoNothing
239 && self.storage.is_empty()
240 && !self.wipe_storage
241 }
242}
243
244impl PartialOrd for AccountRevert {
246 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
247 Some(self.cmp(other))
248 }
249}
250
251impl Ord for AccountRevert {
253 fn cmp(&self, other: &Self) -> Ordering {
254 if let Some(ord) = self.account.partial_cmp(&other.account) {
256 if ord != Ordering::Equal {
257 return ord;
258 }
259 }
260
261 let mut self_storage: Vec<_> = self.storage.iter().collect();
263 let mut other_storage: Vec<_> = other.storage.iter().collect();
264
265 self_storage.sort_by(|(k1, v1), (k2, v2)| k1.cmp(k2).then_with(|| v1.cmp(v2)));
267 other_storage.sort_by(|(k1, v1), (k2, v2)| k1.cmp(k2).then_with(|| v1.cmp(v2)));
268
269 for (self_entry, other_entry) in self_storage.iter().zip(other_storage.iter()) {
271 let key_ord = self_entry.0.cmp(other_entry.0);
272 if key_ord != Ordering::Equal {
273 return key_ord;
274 }
275 let value_ord = self_entry.1.cmp(other_entry.1);
276 if value_ord != Ordering::Equal {
277 return value_ord;
278 }
279 }
280
281 self_storage
283 .len()
284 .cmp(&other_storage.len())
285 .then_with(|| self.previous_status.cmp(&other.previous_status))
286 .then_with(|| self.wipe_storage.cmp(&other.wipe_storage))
287 }
288}
289
290#[derive(Clone, Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
293#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
294pub enum AccountInfoRevert {
295 #[default]
296 DoNothing,
298 DeleteIt,
300 RevertTo(AccountInfo),
302}
303
304#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
314#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
315pub enum RevertToSlot {
316 Some(U256),
317 Destroyed,
318}
319
320impl RevertToSlot {
321 pub fn to_previous_value(self) -> U256 {
322 match self {
323 RevertToSlot::Some(value) => value,
324 RevertToSlot::Destroyed => U256::ZERO,
325 }
326 }
327}