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