revm_database/states/
bundle_state.rs

1use super::{
2    changes::{PlainStorageChangeset, StateChangeset},
3    reverts::{AccountInfoRevert, Reverts},
4    AccountRevert, AccountStatus, BundleAccount, PlainStateReverts, RevertToSlot, StorageSlot,
5    TransitionState,
6};
7use bytecode::Bytecode;
8use core::{mem, ops::RangeInclusive};
9use primitives::{
10    hash_map::{self, Entry},
11    Address, HashMap, HashSet, B256, KECCAK_EMPTY, U256,
12};
13use state::AccountInfo;
14use std::{
15    collections::{BTreeMap, BTreeSet},
16    vec::Vec,
17};
18
19/// This builder is used to help to facilitate the initialization of `BundleState` struct
20#[derive(Debug)]
21pub struct BundleBuilder {
22    states: HashSet<Address>,
23    state_original: HashMap<Address, AccountInfo>,
24    state_present: HashMap<Address, AccountInfo>,
25    state_storage: HashMap<Address, HashMap<U256, (U256, U256)>>,
26
27    reverts: BTreeSet<(u64, Address)>,
28    revert_range: RangeInclusive<u64>,
29    revert_account: HashMap<(u64, Address), Option<Option<AccountInfo>>>,
30    revert_storage: HashMap<(u64, Address), Vec<(U256, U256)>>,
31
32    contracts: HashMap<B256, Bytecode>,
33}
34
35/// Option for [`BundleState`] when converting it to the plain state.
36#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub enum OriginalValuesKnown {
38    /// Checks changed with original values that [BundleState] has.
39    ///
40    /// If we don't expect parent blocks to be committed or unwinded from database, this option
41    /// should be used.
42    Yes,
43    /// Doesn't check original values, see the implementation of [BundleState::into_plain_state] for
44    /// more info.
45    ///
46    /// If the Bundle can be split or extended, we would not be sure about original values, in that
47    /// case this option should be used.
48    No,
49}
50impl OriginalValuesKnown {
51    /// Original value is not known for sure.
52    pub fn is_not_known(&self) -> bool {
53        matches!(self, Self::No)
54    }
55}
56
57impl Default for BundleBuilder {
58    fn default() -> Self {
59        BundleBuilder {
60            states: HashSet::default(),
61            state_original: HashMap::default(),
62            state_present: HashMap::default(),
63            state_storage: HashMap::default(),
64            reverts: BTreeSet::new(),
65            revert_range: 0..=0,
66            revert_account: HashMap::default(),
67            revert_storage: HashMap::default(),
68            contracts: HashMap::default(),
69        }
70    }
71}
72
73impl BundleBuilder {
74    /// Creates builder instance.
75    ///
76    /// `revert_range` indicates the size of BundleState `reverts` field.
77    pub fn new(revert_range: RangeInclusive<u64>) -> Self {
78        BundleBuilder {
79            revert_range,
80            ..Default::default()
81        }
82    }
83
84    /// Applies a transformation to the builder.
85    pub fn apply<F>(self, f: F) -> Self
86    where
87        F: FnOnce(Self) -> Self,
88    {
89        f(self)
90    }
91
92    /// Applies a mutable transformation to the builder.
93    pub fn apply_mut<F>(&mut self, f: F) -> &mut Self
94    where
95        F: FnOnce(&mut Self),
96    {
97        f(self);
98        self
99    }
100
101    /// Collects address info of BundleState state.
102    pub fn state_address(mut self, address: Address) -> Self {
103        self.set_state_address(address);
104        self
105    }
106
107    /// Collects account info of BundleState state.
108    pub fn state_original_account_info(mut self, address: Address, original: AccountInfo) -> Self {
109        self.set_state_original_account_info(address, original);
110        self
111    }
112
113    /// Collects account info of BundleState state.
114    pub fn state_present_account_info(mut self, address: Address, present: AccountInfo) -> Self {
115        self.set_state_present_account_info(address, present);
116        self
117    }
118
119    /// Collects storage info of BundleState state.
120    pub fn state_storage(mut self, address: Address, storage: HashMap<U256, (U256, U256)>) -> Self {
121        self.set_state_storage(address, storage);
122        self
123    }
124
125    /// Collects address info of BundleState reverts.
126    ///
127    /// `block_number` must respect `revert_range`, or the input
128    /// will be ignored during the final build process.
129    pub fn revert_address(mut self, block_number: u64, address: Address) -> Self {
130        self.set_revert_address(block_number, address);
131        self
132    }
133
134    /// Collects account info of BundleState reverts.
135    ///
136    /// `block_number` must respect `revert_range`, or the input
137    /// will be ignored during the final build process.
138    pub fn revert_account_info(
139        mut self,
140        block_number: u64,
141        address: Address,
142        account: Option<Option<AccountInfo>>,
143    ) -> Self {
144        self.set_revert_account_info(block_number, address, account);
145        self
146    }
147
148    /// Collects storage info of BundleState reverts.
149    ///
150    /// `block_number` must respect `revert_range`, or the input
151    /// will be ignored during the final build process.
152    pub fn revert_storage(
153        mut self,
154        block_number: u64,
155        address: Address,
156        storage: Vec<(U256, U256)>,
157    ) -> Self {
158        self.set_revert_storage(block_number, address, storage);
159        self
160    }
161
162    /// Collects contracts info.
163    pub fn contract(mut self, address: B256, bytecode: Bytecode) -> Self {
164        self.set_contract(address, bytecode);
165        self
166    }
167
168    /// Sets address info of BundleState state.
169    pub fn set_state_address(&mut self, address: Address) -> &mut Self {
170        self.states.insert(address);
171        self
172    }
173
174    /// Sets original account info of BundleState state.
175    pub fn set_state_original_account_info(
176        &mut self,
177        address: Address,
178        original: AccountInfo,
179    ) -> &mut Self {
180        self.states.insert(address);
181        self.state_original.insert(address, original);
182        self
183    }
184
185    /// Sets present account info of BundleState state.
186    pub fn set_state_present_account_info(
187        &mut self,
188        address: Address,
189        present: AccountInfo,
190    ) -> &mut Self {
191        self.states.insert(address);
192        self.state_present.insert(address, present);
193        self
194    }
195
196    /// Sets storage info of BundleState state.
197    pub fn set_state_storage(
198        &mut self,
199        address: Address,
200        storage: HashMap<U256, (U256, U256)>,
201    ) -> &mut Self {
202        self.states.insert(address);
203        self.state_storage.insert(address, storage);
204        self
205    }
206
207    /// Sets address info of BundleState reverts.
208    pub fn set_revert_address(&mut self, block_number: u64, address: Address) -> &mut Self {
209        self.reverts.insert((block_number, address));
210        self
211    }
212
213    /// Sets account info of BundleState reverts.
214    pub fn set_revert_account_info(
215        &mut self,
216        block_number: u64,
217        address: Address,
218        account: Option<Option<AccountInfo>>,
219    ) -> &mut Self {
220        self.reverts.insert((block_number, address));
221        self.revert_account.insert((block_number, address), account);
222        self
223    }
224
225    /// Sets storage info of BundleState reverts.
226    pub fn set_revert_storage(
227        &mut self,
228        block_number: u64,
229        address: Address,
230        storage: Vec<(U256, U256)>,
231    ) -> &mut Self {
232        self.reverts.insert((block_number, address));
233        self.revert_storage.insert((block_number, address), storage);
234        self
235    }
236
237    /// Sets contracts info.
238    pub fn set_contract(&mut self, address: B256, bytecode: Bytecode) -> &mut Self {
239        self.contracts.insert(address, bytecode);
240        self
241    }
242
243    /// Creates `BundleState` instance based on collected information.
244    pub fn build(mut self) -> BundleState {
245        let mut state_size = 0;
246        let state = self
247            .states
248            .into_iter()
249            .map(|address| {
250                let storage = self
251                    .state_storage
252                    .remove(&address)
253                    .map(|s| {
254                        s.into_iter()
255                            .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
256                            .collect()
257                    })
258                    .unwrap_or_default();
259                let bundle_account = BundleAccount::new(
260                    self.state_original.remove(&address),
261                    self.state_present.remove(&address),
262                    storage,
263                    AccountStatus::Changed,
264                );
265                state_size += bundle_account.size_hint();
266                (address, bundle_account)
267            })
268            .collect();
269
270        let mut reverts_size = 0;
271        let mut reverts_map = BTreeMap::new();
272        for block_number in self.revert_range {
273            reverts_map.insert(block_number, Vec::new());
274        }
275        self.reverts
276            .into_iter()
277            .for_each(|(block_number, address)| {
278                let account = match self
279                    .revert_account
280                    .remove(&(block_number, address))
281                    .unwrap_or_default()
282                {
283                    Some(Some(account)) => AccountInfoRevert::RevertTo(account),
284                    Some(None) => AccountInfoRevert::DeleteIt,
285                    None => AccountInfoRevert::DoNothing,
286                };
287                let storage = self
288                    .revert_storage
289                    .remove(&(block_number, address))
290                    .map(|s| {
291                        s.into_iter()
292                            .map(|(k, v)| (k, RevertToSlot::Some(v)))
293                            .collect()
294                    })
295                    .unwrap_or_default();
296                let account_revert = AccountRevert {
297                    account,
298                    storage,
299                    previous_status: AccountStatus::Changed,
300                    wipe_storage: false,
301                };
302
303                if reverts_map.contains_key(&block_number) {
304                    reverts_size += account_revert.size_hint();
305                    reverts_map
306                        .entry(block_number)
307                        .or_insert(Vec::new())
308                        .push((address, account_revert));
309                }
310            });
311
312        BundleState {
313            state,
314            contracts: self.contracts,
315            reverts: Reverts::new(reverts_map.into_values().collect()),
316            state_size,
317            reverts_size,
318        }
319    }
320
321    /// Getter for `states` field
322    pub fn get_states(&self) -> &HashSet<Address> {
323        &self.states
324    }
325
326    /// Mutable getter for `states` field
327    pub fn get_states_mut(&mut self) -> &mut HashSet<Address> {
328        &mut self.states
329    }
330
331    /// Mutable getter for `state_original` field
332    pub fn get_state_original_mut(&mut self) -> &mut HashMap<Address, AccountInfo> {
333        &mut self.state_original
334    }
335
336    /// Mutable getter for `state_present` field
337    pub fn get_state_present_mut(&mut self) -> &mut HashMap<Address, AccountInfo> {
338        &mut self.state_present
339    }
340
341    /// Mutable getter for `state_storage` field
342    pub fn get_state_storage_mut(&mut self) -> &mut HashMap<Address, HashMap<U256, (U256, U256)>> {
343        &mut self.state_storage
344    }
345
346    /// Mutable getter for `reverts` field
347    pub fn get_reverts_mut(&mut self) -> &mut BTreeSet<(u64, Address)> {
348        &mut self.reverts
349    }
350
351    /// Mutable getter for `revert_range` field
352    pub fn get_revert_range_mut(&mut self) -> &mut RangeInclusive<u64> {
353        &mut self.revert_range
354    }
355
356    /// Mutable getter for `revert_account` field
357    pub fn get_revert_account_mut(
358        &mut self,
359    ) -> &mut HashMap<(u64, Address), Option<Option<AccountInfo>>> {
360        &mut self.revert_account
361    }
362
363    /// Mutable getter for `revert_storage` field
364    pub fn get_revert_storage_mut(&mut self) -> &mut HashMap<(u64, Address), Vec<(U256, U256)>> {
365        &mut self.revert_storage
366    }
367
368    /// Mutable getter for `contracts` field
369    pub fn get_contracts_mut(&mut self) -> &mut HashMap<B256, Bytecode> {
370        &mut self.contracts
371    }
372}
373
374/// Bundle retention policy for applying substate to the bundle.
375#[derive(Debug)]
376pub enum BundleRetention {
377    /// Only plain state is updated.
378    PlainState,
379    /// Both, plain state and reverts, are retained
380    Reverts,
381}
382
383impl BundleRetention {
384    /// Returns `true` if reverts should be retained.
385    pub fn includes_reverts(&self) -> bool {
386        matches!(self, Self::Reverts)
387    }
388}
389
390/// Bundle state contain only values that got changed
391///
392/// For every account it contains both original and present state.
393///
394/// This is needed to decide if there were any changes to the account.
395///
396/// Reverts and created when TransitionState is applied to BundleState.
397///
398/// And can be used to revert BundleState to the state before transition.
399#[derive(Default, Clone, Debug, PartialEq, Eq)]
400#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
401pub struct BundleState {
402    /// Account state
403    pub state: HashMap<Address, BundleAccount>,
404    /// All created contracts in this block.
405    pub contracts: HashMap<B256, Bytecode>,
406    /// Changes to revert
407    ///
408    /// **Note**: Inside vector is *not* sorted by address.
409    ///
410    /// But it is unique by address.
411    pub reverts: Reverts,
412    /// The size of the plain state in the bundle state
413    pub state_size: usize,
414    /// The size of reverts in the bundle state
415    pub reverts_size: usize,
416}
417
418impl BundleState {
419    /// Returns builder instance for further manipulation.
420    pub fn builder(revert_range: RangeInclusive<u64>) -> BundleBuilder {
421        BundleBuilder::new(revert_range)
422    }
423
424    /// Creates it with new and old values of both Storage and AccountInfo.
425    pub fn new(
426        state: impl IntoIterator<
427            Item = (
428                Address,
429                Option<AccountInfo>,
430                Option<AccountInfo>,
431                HashMap<U256, (U256, U256)>,
432            ),
433        >,
434        reverts: impl IntoIterator<
435            Item = impl IntoIterator<
436                Item = (
437                    Address,
438                    Option<Option<AccountInfo>>,
439                    impl IntoIterator<Item = (U256, U256)>,
440                ),
441            >,
442        >,
443        contracts: impl IntoIterator<Item = (B256, Bytecode)>,
444    ) -> Self {
445        // Create state from iterator.
446        let mut state_size = 0;
447        let state = state
448            .into_iter()
449            .map(|(address, original, present, storage)| {
450                let account = BundleAccount::new(
451                    original,
452                    present,
453                    storage
454                        .into_iter()
455                        .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
456                        .collect(),
457                    AccountStatus::Changed,
458                );
459                state_size += account.size_hint();
460                (address, account)
461            })
462            .collect();
463
464        // Create reverts from iterator.
465        let mut reverts_size = 0;
466        let reverts = reverts
467            .into_iter()
468            .map(|block_reverts| {
469                block_reverts
470                    .into_iter()
471                    .map(|(address, account, storage)| {
472                        let account = match account {
473                            Some(Some(account)) => AccountInfoRevert::RevertTo(account),
474                            Some(None) => AccountInfoRevert::DeleteIt,
475                            None => AccountInfoRevert::DoNothing,
476                        };
477                        let revert = AccountRevert {
478                            account,
479                            storage: storage
480                                .into_iter()
481                                .map(|(k, v)| (k, RevertToSlot::Some(v)))
482                                .collect(),
483                            previous_status: AccountStatus::Changed,
484                            wipe_storage: false,
485                        };
486                        reverts_size += revert.size_hint();
487                        (address, revert)
488                    })
489                    .collect::<Vec<_>>()
490            })
491            .collect::<Vec<_>>();
492
493        Self {
494            state,
495            contracts: contracts.into_iter().collect(),
496            reverts: Reverts::new(reverts),
497            state_size,
498            reverts_size,
499        }
500    }
501
502    /// Returns the approximate size of changes in the bundle state.
503    ///
504    /// The estimation is not precise, because the information about the number of
505    /// destroyed entries that need to be removed is not accessible to the bundle state.
506    pub fn size_hint(&self) -> usize {
507        self.state_size + self.reverts_size + self.contracts.len()
508    }
509
510    /// Returns reference to the state.
511    pub fn state(&self) -> &HashMap<Address, BundleAccount> {
512        &self.state
513    }
514
515    /// Checks whether bundle state is empty.
516    pub fn is_empty(&self) -> bool {
517        self.len() == 0
518    }
519
520    /// Return number of changed accounts.
521    pub fn len(&self) -> usize {
522        self.state.len()
523    }
524
525    /// Gets account from state.
526    pub fn account(&self, address: &Address) -> Option<&BundleAccount> {
527        self.state.get(address)
528    }
529
530    /// Gets bytecode from state.
531    pub fn bytecode(&self, hash: &B256) -> Option<Bytecode> {
532        self.contracts.get(hash).cloned()
533    }
534
535    /// Consumes [`TransitionState`] by applying the changes and creating the
536    /// reverts.
537    ///
538    /// If [BundleRetention::includes_reverts] is `true`, then the reverts will
539    /// be retained.
540    pub fn apply_transitions_and_create_reverts(
541        &mut self,
542        transitions: TransitionState,
543        retention: BundleRetention,
544    ) {
545        let include_reverts = retention.includes_reverts();
546        // Pessimistically pre-allocate assuming _all_ accounts changed.
547        let reverts_capacity = if include_reverts {
548            transitions.transitions.len()
549        } else {
550            0
551        };
552        let mut reverts = Vec::with_capacity(reverts_capacity);
553
554        for (address, transition) in transitions.transitions.into_iter() {
555            // Add new contract if it was created/changed.
556            if let Some((hash, new_bytecode)) = transition.has_new_contract() {
557                self.contracts.insert(hash, new_bytecode.clone());
558            }
559            // Update state and create revert.
560            let revert = match self.state.entry(address) {
561                hash_map::Entry::Occupied(mut entry) => {
562                    let entry = entry.get_mut();
563                    self.state_size -= entry.size_hint();
564                    // Update and create revert if it is present
565                    let revert = entry.update_and_create_revert(transition);
566                    // Update the state size
567                    self.state_size += entry.size_hint();
568                    revert
569                }
570                hash_map::Entry::Vacant(entry) => {
571                    // Make revert from transition account
572                    let present_bundle = transition.present_bundle_account();
573                    let revert = transition.create_revert();
574                    if revert.is_some() {
575                        self.state_size += present_bundle.size_hint();
576                        entry.insert(present_bundle);
577                    }
578                    revert
579                }
580            };
581
582            // Append revert if present.
583            if let Some(revert) = revert.filter(|_| include_reverts) {
584                self.reverts_size += revert.size_hint();
585                reverts.push((address, revert));
586            }
587        }
588
589        self.reverts.push(reverts);
590    }
591
592    /// Generate a [`StateChangeset`] from the bundle state without consuming
593    /// it.
594    pub fn to_plain_state(&self, is_value_known: OriginalValuesKnown) -> StateChangeset {
595        // Pessimistically pre-allocate assuming _all_ accounts changed.
596        let state_len = self.state.len();
597        let mut accounts = Vec::with_capacity(state_len);
598        let mut storage = Vec::with_capacity(state_len);
599
600        for (address, account) in self.state.iter() {
601            // Append account info if it is changed.
602            let was_destroyed = account.was_destroyed();
603            if is_value_known.is_not_known() || account.is_info_changed() {
604                let info = account.info.as_ref().map(AccountInfo::copy_without_code);
605                accounts.push((*address, info));
606            }
607
608            // Append storage changes
609
610            // Note: Assumption is that revert is going to remove whole plain storage from
611            // database so we can check if plain state was wiped or not.
612            let mut account_storage_changed = Vec::with_capacity(account.storage.len());
613
614            for (key, slot) in account.storage.iter().map(|(k, v)| (*k, *v)) {
615                // If storage was destroyed that means that storage was wiped.
616                // In that case we need to check if present storage value is different then ZERO.
617                let destroyed_and_not_zero = was_destroyed && !slot.present_value.is_zero();
618
619                // If account is not destroyed check if original values was changed,
620                // so we can update it.
621                let not_destroyed_and_changed = !was_destroyed && slot.is_changed();
622
623                if is_value_known.is_not_known()
624                    || destroyed_and_not_zero
625                    || not_destroyed_and_changed
626                {
627                    account_storage_changed.push((key, slot.present_value));
628                }
629            }
630
631            if !account_storage_changed.is_empty() || was_destroyed {
632                // Append storage changes to account.
633                storage.push(PlainStorageChangeset {
634                    address: *address,
635                    wipe_storage: was_destroyed,
636                    storage: account_storage_changed,
637                });
638            }
639        }
640
641        let contracts = self
642            .contracts
643            .iter()
644            // Remove empty bytecodes
645            .filter(|(b, _)| **b != KECCAK_EMPTY)
646            .map(|(b, code)| (*b, code.clone()))
647            .collect::<Vec<_>>();
648        StateChangeset {
649            accounts,
650            storage,
651            contracts,
652        }
653    }
654
655    /// Converts the bundle state into a [`StateChangeset`].
656    #[deprecated = "Use `to_plain_state` instead"]
657    pub fn into_plain_state(self, is_value_known: OriginalValuesKnown) -> StateChangeset {
658        self.to_plain_state(is_value_known)
659    }
660
661    /// Generates a [`StateChangeset`] and [`PlainStateReverts`] from the bundle
662    /// state.
663    pub fn to_plain_state_and_reverts(
664        &self,
665        is_value_known: OriginalValuesKnown,
666    ) -> (StateChangeset, PlainStateReverts) {
667        (
668            self.to_plain_state(is_value_known),
669            self.reverts.to_plain_state_reverts(),
670        )
671    }
672
673    /// Consumes the bundle state and split it into a [`StateChangeset`] and a
674    /// [`PlainStateReverts`].
675    #[deprecated = "Use `to_plain_state_and_reverts` instead"]
676    pub fn into_plain_state_and_reverts(
677        self,
678        is_value_known: OriginalValuesKnown,
679    ) -> (StateChangeset, PlainStateReverts) {
680        self.to_plain_state_and_reverts(is_value_known)
681    }
682
683    /// Extends the bundle with other state.
684    ///
685    /// Updates the `other` state only if `other` is not flagged as destroyed.
686    pub fn extend_state(&mut self, other_state: HashMap<Address, BundleAccount>) {
687        for (address, other_account) in other_state {
688            match self.state.entry(address) {
689                hash_map::Entry::Occupied(mut entry) => {
690                    let this = entry.get_mut();
691                    self.state_size -= this.size_hint();
692
693                    // If other was destroyed. replace `this` storage with
694                    // the `other one.
695                    if other_account.was_destroyed() {
696                        this.storage = other_account.storage;
697                    } else {
698                        // Otherwise extend this storage with other
699                        for (key, storage_slot) in other_account.storage {
700                            // Update present value or insert storage slot.
701                            this.storage
702                                .entry(key)
703                                .or_insert(storage_slot)
704                                .present_value = storage_slot.present_value;
705                        }
706                    }
707                    this.info = other_account.info;
708                    this.status.transition(other_account.status);
709
710                    // Update the state size
711                    self.state_size += this.size_hint();
712                }
713                hash_map::Entry::Vacant(entry) => {
714                    // Just insert if empty
715                    self.state_size += other_account.size_hint();
716                    entry.insert(other_account);
717                }
718            }
719        }
720    }
721    /// Extends the state with state that is build on top of it.
722    ///
723    /// If storage was wiped in `other` state, copy `this` plain state
724    /// and put it inside `other` revert (if there is no duplicates of course).
725    ///
726    /// If `this` and `other` accounts were both destroyed invalidate second
727    /// wipe flag (from `other`).
728    ///
729    /// As wiping from database should be done only once
730    /// and we already transferred all potentially missing storages to the `other` revert.
731    pub fn extend(&mut self, mut other: Self) {
732        // Iterate over reverts and if its storage is wiped try to add previous bundle
733        // state as there is potential missing slots.
734        for (address, revert) in other.reverts.iter_mut().flatten() {
735            if revert.wipe_storage {
736                // If there is wipe storage in `other` revert
737                // we need to move storage from present state.
738                if let Some(this_account) = self.state.get_mut(address) {
739                    // As this account was destroyed inside `other` bundle.
740                    // We are fine to wipe/drain this storage and put it inside revert.
741                    for (key, value) in this_account.storage.drain() {
742                        revert
743                            .storage
744                            .entry(key)
745                            .or_insert(RevertToSlot::Some(value.present_value));
746                    }
747
748                    // Nullify `other` wipe as primary database wipe is done in `this`.
749                    if this_account.was_destroyed() {
750                        revert.wipe_storage = false;
751                    }
752                }
753            }
754
755            // Increment reverts size for each of the updated reverts.
756            self.reverts_size += revert.size_hint();
757        }
758        // Extension of state
759        self.extend_state(other.state);
760        // Contract can be just extended, when counter is introduced we will take into account that.
761        self.contracts.extend(other.contracts);
762        // Reverts can be just extended
763        self.reverts.extend(other.reverts);
764    }
765
766    /// Takes first N raw reverts from the [BundleState].
767    pub fn take_n_reverts(&mut self, reverts_to_take: usize) -> Reverts {
768        // Split is done as [0, num) and [num, len].
769        if reverts_to_take > self.reverts.len() {
770            return self.take_all_reverts();
771        }
772        let (detach, this) = self.reverts.split_at(reverts_to_take);
773        let detached_reverts = Reverts::new(detach.to_vec());
774        self.reverts_size = this
775            .iter()
776            .flatten()
777            .fold(0, |acc, (_, revert)| acc + revert.size_hint());
778        self.reverts = Reverts::new(this.to_vec());
779        detached_reverts
780    }
781
782    /// Returns and clears all reverts from [BundleState].
783    pub fn take_all_reverts(&mut self) -> Reverts {
784        self.reverts_size = 0;
785        core::mem::take(&mut self.reverts)
786    }
787
788    /// Reverts the state changes of the latest transition.
789    ///
790    /// **Note**: This is the same as `BundleState::revert(1)`
791    ///
792    /// Returns true if the state was reverted.
793    pub fn revert_latest(&mut self) -> bool {
794        // Revert the latest recorded state
795        if let Some(reverts) = self.reverts.pop() {
796            for (address, revert_account) in reverts.into_iter() {
797                self.reverts_size -= revert_account.size_hint();
798                match self.state.entry(address) {
799                    Entry::Occupied(mut entry) => {
800                        let account = entry.get_mut();
801                        self.state_size -= account.size_hint();
802                        if account.revert(revert_account) {
803                            entry.remove();
804                        } else {
805                            self.state_size += account.size_hint();
806                        }
807                    }
808                    Entry::Vacant(entry) => {
809                        // Create empty account that we will revert on.
810                        // Only place where this account is not existing is if revert is DeleteIt.
811                        let mut account = BundleAccount::new(
812                            None,
813                            None,
814                            HashMap::default(),
815                            AccountStatus::LoadedNotExisting,
816                        );
817                        if !account.revert(revert_account) {
818                            self.state_size += account.size_hint();
819                            entry.insert(account);
820                        }
821                    }
822                }
823            }
824            return true;
825        }
826
827        false
828    }
829
830    /// Reverts the state changes by N transitions back.
831    ///
832    /// See also [Self::revert_latest]
833    pub fn revert(&mut self, mut num_transitions: usize) {
834        if num_transitions == 0 {
835            return;
836        }
837
838        while self.revert_latest() {
839            num_transitions -= 1;
840            if num_transitions == 0 {
841                // Break the loop.
842                break;
843            }
844        }
845    }
846
847    /// Prepends present the state with the given [BundleState].
848    ///
849    /// It adds changes from the given state but does not override any existing changes.
850    ///
851    /// Reverts are not updated.
852    pub fn prepend_state(&mut self, mut other: BundleState) {
853        // Take this bundle
854        let this_bundle = mem::take(self);
855        // Extend other bundle state with this
856        other.extend_state(this_bundle.state);
857        // Extend other contracts
858        other.contracts.extend(this_bundle.contracts);
859        // Swap bundles
860        mem::swap(self, &mut other)
861    }
862}
863
864#[cfg(test)]
865mod tests {
866    use super::*;
867    use crate::{StorageWithOriginalValues, TransitionAccount};
868
869    #[test]
870    fn transition_states() {
871        // Dummy data
872        let address = Address::new([0x01; 20]);
873        let acc1 = AccountInfo {
874            balance: U256::from(10),
875            nonce: 1,
876            code_hash: KECCAK_EMPTY,
877            code: None,
878        };
879
880        let mut bundle_state = BundleState::default();
881
882        // Have transition from loaded to all other states
883
884        let transition = TransitionAccount {
885            info: Some(acc1),
886            status: AccountStatus::InMemoryChange,
887            previous_info: None,
888            previous_status: AccountStatus::LoadedNotExisting,
889            storage: StorageWithOriginalValues::default(),
890            storage_was_destroyed: false,
891        };
892
893        // Apply first transition
894        bundle_state.apply_transitions_and_create_reverts(
895            TransitionState::single(address, transition.clone()),
896            BundleRetention::Reverts,
897        );
898    }
899
900    const fn account1() -> Address {
901        Address::new([0x60; 20])
902    }
903
904    const fn account2() -> Address {
905        Address::new([0x61; 20])
906    }
907
908    fn slot1() -> U256 {
909        U256::from(5)
910    }
911
912    fn slot2() -> U256 {
913        U256::from(7)
914    }
915
916    /// Tests bundle one.
917    fn test_bundle1() -> BundleState {
918        // Block changes
919        BundleState::new(
920            vec![
921                (
922                    account1(),
923                    None,
924                    Some(AccountInfo {
925                        nonce: 1,
926                        balance: U256::from(10),
927                        code_hash: KECCAK_EMPTY,
928                        code: None,
929                    }),
930                    HashMap::from_iter([
931                        (slot1(), (U256::from(0), U256::from(10))),
932                        (slot2(), (U256::from(0), U256::from(15))),
933                    ]),
934                ),
935                (
936                    account2(),
937                    None,
938                    Some(AccountInfo {
939                        nonce: 1,
940                        balance: U256::from(10),
941                        code_hash: KECCAK_EMPTY,
942                        code: None,
943                    }),
944                    HashMap::default(),
945                ),
946            ],
947            vec![vec![
948                (
949                    account1(),
950                    Some(None),
951                    vec![(slot1(), U256::from(0)), (slot2(), U256::from(0))],
952                ),
953                (account2(), Some(None), vec![]),
954            ]],
955            vec![],
956        )
957    }
958
959    /// Tests bundle two.
960    fn test_bundle2() -> BundleState {
961        // Block changes
962        BundleState::new(
963            vec![(
964                account1(),
965                None,
966                Some(AccountInfo {
967                    nonce: 3,
968                    balance: U256::from(20),
969                    code_hash: KECCAK_EMPTY,
970                    code: None,
971                }),
972                HashMap::from_iter([(slot1(), (U256::from(0), U256::from(15)))]),
973            )],
974            vec![vec![(
975                account1(),
976                Some(Some(AccountInfo {
977                    nonce: 1,
978                    balance: U256::from(10),
979                    code_hash: KECCAK_EMPTY,
980                    code: None,
981                })),
982                vec![(slot1(), U256::from(10))],
983            )]],
984            vec![],
985        )
986    }
987
988    /// Tests bundle three.
989    fn test_bundle3() -> BundleState {
990        BundleState::builder(0..=0)
991            .state_present_account_info(
992                account1(),
993                AccountInfo {
994                    nonce: 1,
995                    balance: U256::from(10),
996                    code_hash: KECCAK_EMPTY,
997                    code: None,
998                },
999            )
1000            .state_storage(
1001                account1(),
1002                HashMap::from_iter([(slot1(), (U256::from(0), U256::from(10)))]),
1003            )
1004            .state_address(account2())
1005            .state_present_account_info(
1006                account2(),
1007                AccountInfo {
1008                    nonce: 1,
1009                    balance: U256::from(10),
1010                    code_hash: KECCAK_EMPTY,
1011                    code: None,
1012                },
1013            )
1014            .revert_address(0, account1())
1015            .revert_account_info(0, account1(), Some(None))
1016            .revert_storage(0, account1(), vec![(slot1(), U256::from(0))])
1017            .revert_account_info(0, account2(), Some(None))
1018            .build()
1019    }
1020
1021    /// Tests bundle four.
1022    fn test_bundle4() -> BundleState {
1023        BundleState::builder(0..=0)
1024            .state_present_account_info(
1025                account1(),
1026                AccountInfo {
1027                    nonce: 3,
1028                    balance: U256::from(20),
1029                    code_hash: KECCAK_EMPTY,
1030                    code: None,
1031                },
1032            )
1033            .state_storage(
1034                account1(),
1035                HashMap::from_iter([(slot1(), (U256::from(0), U256::from(15)))]),
1036            )
1037            .revert_address(0, account1())
1038            .revert_account_info(
1039                0,
1040                account1(),
1041                Some(Some(AccountInfo {
1042                    nonce: 1,
1043                    balance: U256::from(10),
1044                    code_hash: KECCAK_EMPTY,
1045                    code: None,
1046                })),
1047            )
1048            .revert_storage(0, account1(), vec![(slot1(), U256::from(10))])
1049            .build()
1050    }
1051
1052    fn sanity_path(bundle1: BundleState, bundle2: BundleState) {
1053        let mut extended = bundle1.clone();
1054        extended.extend(bundle2.clone());
1055
1056        let mut reverted = extended.clone();
1057        // Revert zero does nothing.
1058        reverted.revert(0);
1059        assert_eq!(reverted, extended);
1060
1061        // Revert by one gives us bundle one.
1062        reverted.revert(1);
1063        assert_eq!(reverted, bundle1);
1064
1065        // Reverted by additional one gives us empty bundle.
1066        reverted.revert(1);
1067        assert_eq!(reverted, BundleState::default());
1068
1069        let mut reverted = extended.clone();
1070
1071        // Reverted by bigger number gives us empty bundle
1072        reverted.revert(10);
1073        assert_eq!(reverted, BundleState::default());
1074    }
1075
1076    #[test]
1077    fn extend_on_destroyed_values() {
1078        let base_bundle1 = test_bundle1();
1079        let base_bundle2 = test_bundle2();
1080
1081        // test1
1082        // bundle1 has Destroyed
1083        // bundle2 has Changed
1084        // end should be DestroyedChanged.
1085        let mut b1 = base_bundle1.clone();
1086        let mut b2 = base_bundle2.clone();
1087        b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1088        b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1089        b1.extend(b2);
1090        assert_eq!(
1091            b1.state.get_mut(&account1()).unwrap().status,
1092            AccountStatus::DestroyedChanged
1093        );
1094
1095        // test2
1096        // bundle1 has Changed
1097        // bundle2 has Destroyed
1098        // end should be Destroyed
1099        let mut b1 = base_bundle1.clone();
1100        let mut b2 = base_bundle2.clone();
1101        b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1102        b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1103        b2.reverts[0][0].1.wipe_storage = true;
1104        b1.extend(b2);
1105        assert_eq!(
1106            b1.state.get_mut(&account1()).unwrap().status,
1107            AccountStatus::Destroyed
1108        );
1109
1110        // test2 extension
1111        // revert of b2 should contains plain state of b1.
1112        let mut revert1 = base_bundle2.reverts[0][0].clone();
1113        revert1.1.wipe_storage = true;
1114        revert1
1115            .1
1116            .storage
1117            .insert(slot2(), RevertToSlot::Some(U256::from(15)));
1118
1119        assert_eq!(
1120            b1.reverts.as_ref(),
1121            vec![base_bundle1.reverts[0].clone(), vec![revert1]],
1122        );
1123
1124        // test3
1125        // bundle1 has InMemoryChange
1126        // bundle2 has Change
1127        // end should be InMemoryChange.
1128
1129        let mut b1 = base_bundle1.clone();
1130        let mut b2 = base_bundle2.clone();
1131        b1.state.get_mut(&account1()).unwrap().status = AccountStatus::InMemoryChange;
1132        b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1133        b1.extend(b2);
1134        assert_eq!(
1135            b1.state.get_mut(&account1()).unwrap().status,
1136            AccountStatus::InMemoryChange
1137        );
1138    }
1139
1140    #[test]
1141    fn test_sanity_path() {
1142        sanity_path(test_bundle1(), test_bundle2());
1143        sanity_path(test_bundle3(), test_bundle4());
1144    }
1145
1146    #[test]
1147    fn test_multi_reverts_with_delete() {
1148        let mut state = BundleBuilder::new(0..=3)
1149            .revert_address(0, account1())
1150            .revert_account_info(2, account1(), Some(Some(AccountInfo::default())))
1151            .revert_account_info(3, account1(), Some(None))
1152            .build();
1153
1154        state.revert_latest();
1155        // State for account one was deleted
1156        assert_eq!(state.state.get(&account1()), None);
1157
1158        state.revert_latest();
1159        // State is set to
1160        assert_eq!(
1161            state.state.get(&account1()),
1162            Some(&BundleAccount::new(
1163                None,
1164                Some(AccountInfo::default()),
1165                HashMap::default(),
1166                AccountStatus::Changed
1167            ))
1168        );
1169    }
1170
1171    #[test]
1172    fn test_revert_capacity() {
1173        let state = BundleState::builder(0..=3)
1174            .revert_address(0, account1())
1175            .revert_address(2, account2())
1176            .revert_account_info(0, account1(), Some(None))
1177            .revert_account_info(2, account2(), None)
1178            .revert_storage(0, account1(), vec![(slot1(), U256::from(10))])
1179            .build();
1180
1181        assert_eq!(state.reverts.len(), 4);
1182        assert_eq!(state.reverts[1], vec![]);
1183        assert_eq!(state.reverts[3], vec![]);
1184        assert_eq!(state.reverts[0].len(), 1);
1185        assert_eq!(state.reverts[2].len(), 1);
1186
1187        let (addr1, revert1) = &state.reverts[0][0];
1188        assert_eq!(addr1, &account1());
1189        assert_eq!(revert1.account, AccountInfoRevert::DeleteIt);
1190
1191        let (addr2, revert2) = &state.reverts[2][0];
1192        assert_eq!(addr2, &account2());
1193        assert_eq!(revert2.account, AccountInfoRevert::DoNothing);
1194    }
1195
1196    #[test]
1197    fn take_reverts() {
1198        let bundle1 = test_bundle1();
1199        let bundle2 = test_bundle2();
1200
1201        let mut extended = bundle1.clone();
1202        extended.extend(bundle2.clone());
1203
1204        // Check that we have two reverts
1205        assert_eq!(extended.reverts.len(), 2);
1206
1207        // Take all by big N
1208        let mut extended2 = extended.clone();
1209        assert_eq!(extended2.take_n_reverts(100), extended.reverts);
1210
1211        // Take all reverts
1212        let mut extended2 = extended.clone();
1213        assert_eq!(extended2.take_all_reverts(), extended.reverts);
1214
1215        // Take zero revert
1216        let taken_reverts = extended.take_n_reverts(0);
1217        assert_eq!(taken_reverts, Reverts::default());
1218        assert_eq!(extended.reverts.len(), 2);
1219
1220        // Take one revert
1221        let taken_reverts = extended.take_n_reverts(1);
1222        assert_eq!(taken_reverts, bundle1.reverts);
1223
1224        // Take last revert
1225        let taken_reverts = extended.take_n_reverts(1);
1226        assert_eq!(taken_reverts, bundle2.reverts);
1227    }
1228
1229    #[test]
1230    fn prepend_state() {
1231        let address1 = account1();
1232        let address2 = account2();
1233
1234        let account1 = AccountInfo {
1235            nonce: 1,
1236            ..Default::default()
1237        };
1238        let account1_changed = AccountInfo {
1239            nonce: 1,
1240            ..Default::default()
1241        };
1242        let account2 = AccountInfo {
1243            nonce: 1,
1244            ..Default::default()
1245        };
1246
1247        let present_state = BundleState::builder(2..=2)
1248            .state_present_account_info(address1, account1_changed.clone())
1249            .build();
1250        assert_eq!(present_state.reverts.len(), 1);
1251        let previous_state = BundleState::builder(1..=1)
1252            .state_present_account_info(address1, account1)
1253            .state_present_account_info(address2, account2.clone())
1254            .build();
1255        assert_eq!(previous_state.reverts.len(), 1);
1256
1257        let mut test = present_state;
1258
1259        test.prepend_state(previous_state);
1260
1261        assert_eq!(test.state.len(), 2);
1262        // Reverts num should stay the same.
1263        assert_eq!(test.reverts.len(), 1);
1264        // Account1 is not overwritten.
1265        assert_eq!(
1266            test.state.get(&address1).unwrap().info,
1267            Some(account1_changed)
1268        );
1269        // Account2 got inserted
1270        assert_eq!(test.state.get(&address2).unwrap().info, Some(account2));
1271    }
1272
1273    #[test]
1274    fn test_getters() {
1275        let mut builder = BundleBuilder::new(0..=3);
1276
1277        // Test get_states and get_states_mut
1278        assert!(builder.get_states().is_empty());
1279        builder.get_states_mut().insert(account1());
1280        assert!(builder.get_states().contains(&account1()));
1281
1282        // Test get_state_original_mut
1283        assert!(builder.get_state_original_mut().is_empty());
1284        builder
1285            .get_state_original_mut()
1286            .insert(account1(), AccountInfo::default());
1287        assert!(builder.get_state_original_mut().contains_key(&account1()));
1288
1289        // Test get_state_present_mut
1290        assert!(builder.get_state_present_mut().is_empty());
1291        builder
1292            .get_state_present_mut()
1293            .insert(account1(), AccountInfo::default());
1294        assert!(builder.get_state_present_mut().contains_key(&account1()));
1295
1296        // Test get_state_storage_mut
1297        assert!(builder.get_state_storage_mut().is_empty());
1298        builder
1299            .get_state_storage_mut()
1300            .insert(account1(), HashMap::default());
1301        assert!(builder.get_state_storage_mut().contains_key(&account1()));
1302
1303        // Test get_reverts_mut
1304        assert!(builder.get_reverts_mut().is_empty());
1305        builder.get_reverts_mut().insert((0, account1()));
1306        assert!(builder.get_reverts_mut().contains(&(0, account1())));
1307
1308        // Test get_revert_range_mut
1309        assert_eq!(builder.get_revert_range_mut().clone(), 0..=3);
1310
1311        // Test get_revert_account_mut
1312        assert!(builder.get_revert_account_mut().is_empty());
1313        builder
1314            .get_revert_account_mut()
1315            .insert((0, account1()), Some(None));
1316        assert!(builder
1317            .get_revert_account_mut()
1318            .contains_key(&(0, account1())));
1319
1320        // Test get_revert_storage_mut
1321        assert!(builder.get_revert_storage_mut().is_empty());
1322        builder
1323            .get_revert_storage_mut()
1324            .insert((0, account1()), vec![(slot1(), U256::from(0))]);
1325        assert!(builder
1326            .get_revert_storage_mut()
1327            .contains_key(&(0, account1())));
1328
1329        // Test get_contracts_mut
1330        assert!(builder.get_contracts_mut().is_empty());
1331        builder
1332            .get_contracts_mut()
1333            .insert(B256::default(), Bytecode::default());
1334        assert!(builder.get_contracts_mut().contains_key(&B256::default()));
1335    }
1336}