Skip to main content

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