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        self.state.reserve(transitions.transitions.len());
568        for (address, transition) in transitions.transitions.into_iter() {
569            // Add new contract if it was created/changed.
570            if let Some((hash, new_bytecode)) = transition.has_new_contract() {
571                self.contracts.insert(hash, new_bytecode.clone());
572            }
573            // Update state and create revert.
574            let revert = match self.state.entry(address) {
575                Entry::Occupied(mut entry) => {
576                    let entry = entry.get_mut();
577                    self.state_size -= entry.size_hint();
578                    // Update and create revert if it is present
579                    let revert = entry.update_and_create_revert(transition);
580                    // Update the state size
581                    self.state_size += entry.size_hint();
582                    revert
583                }
584                Entry::Vacant(entry) => {
585                    // Make revert from transition account
586                    let present_bundle = transition.present_bundle_account();
587                    let revert = transition.create_revert();
588                    if revert.is_some() {
589                        self.state_size += present_bundle.size_hint();
590                        entry.insert(present_bundle);
591                    }
592                    revert
593                }
594            };
595
596            // Append revert if present.
597            if let Some(revert) = revert.filter(|_| include_reverts) {
598                self.reverts_size += revert.size_hint();
599                reverts.push((address, revert));
600            }
601        }
602
603        self.reverts.push(reverts);
604    }
605
606    /// Generate a [`StateChangeset`] from the bundle state without consuming
607    /// it.
608    pub fn to_plain_state(&self, is_value_known: OriginalValuesKnown) -> StateChangeset {
609        // Pessimistically pre-allocate assuming _all_ accounts changed.
610        let state_len = self.state.len();
611        let mut accounts = Vec::with_capacity(state_len);
612        let mut storage = Vec::with_capacity(state_len);
613
614        for (address, account) in &self.state {
615            // Append account info if it is changed.
616            let was_destroyed = account.was_destroyed();
617            if is_value_known.is_not_known() || account.is_info_changed() {
618                let info = account.info.as_ref().map(AccountInfo::copy_without_code);
619                accounts.push((*address, info));
620            }
621
622            // Append storage changes
623
624            // Note: Assumption is that revert is going to remove whole plain storage from
625            // database so we can check if plain state was wiped or not.
626            let mut account_storage_changed = Vec::with_capacity(account.storage.len());
627
628            for (&key, &slot) in account.storage.iter() {
629                // If storage was destroyed that means that storage was wiped.
630                // In that case we need to check if present storage value is different then ZERO.
631                let destroyed_and_not_zero = was_destroyed && !slot.present_value.is_zero();
632
633                // If account is not destroyed check if original values was changed,
634                // so we can update it.
635                let not_destroyed_and_changed = !was_destroyed && slot.is_changed();
636
637                if is_value_known.is_not_known()
638                    || destroyed_and_not_zero
639                    || not_destroyed_and_changed
640                {
641                    account_storage_changed.push((key, slot.present_value));
642                }
643            }
644
645            if !account_storage_changed.is_empty() || was_destroyed {
646                // Append storage changes to account.
647                storage.push(PlainStorageChangeset {
648                    address: *address,
649                    wipe_storage: was_destroyed,
650                    storage: account_storage_changed,
651                });
652            }
653        }
654
655        let contracts = self
656            .contracts
657            .iter()
658            // Remove empty bytecodes
659            .filter(|(b, _)| **b != KECCAK_EMPTY)
660            .map(|(b, code)| (*b, code.clone()))
661            .collect::<Vec<_>>();
662        StateChangeset {
663            accounts,
664            storage,
665            contracts,
666        }
667    }
668
669    /// Generates a [`StateChangeset`] and [`PlainStateReverts`] from the bundle
670    /// state.
671    pub fn to_plain_state_and_reverts(
672        &self,
673        is_value_known: OriginalValuesKnown,
674    ) -> (StateChangeset, PlainStateReverts) {
675        (
676            self.to_plain_state(is_value_known),
677            self.reverts.to_plain_state_reverts(),
678        )
679    }
680
681    /// Consumes the bundle state and split it into a [`StateChangeset`] and a
682    /// [`PlainStateReverts`].
683    #[deprecated = "Use `to_plain_state_and_reverts` instead"]
684    pub fn into_plain_state_and_reverts(
685        self,
686        is_value_known: OriginalValuesKnown,
687    ) -> (StateChangeset, PlainStateReverts) {
688        self.to_plain_state_and_reverts(is_value_known)
689    }
690
691    /// Extends the bundle with other state.
692    ///
693    /// Updates the `other` state only if `other` is not flagged as destroyed.
694    pub fn extend_state(&mut self, other_state: AddressMap<BundleAccount>) {
695        self.state.reserve(other_state.len());
696        for (address, other_account) in other_state {
697            match self.state.entry(address) {
698                Entry::Occupied(mut entry) => {
699                    let this = entry.get_mut();
700                    self.state_size -= this.size_hint();
701
702                    // If other was destroyed. replace `this` storage with
703                    // the `other one.
704                    if other_account.was_destroyed() {
705                        this.storage = other_account.storage;
706                    } else {
707                        // Otherwise extend this storage with other
708                        this.storage.reserve(other_account.storage.len());
709                        for (key, storage_slot) in other_account.storage {
710                            // Update present value or insert storage slot.
711                            this.storage
712                                .entry(key)
713                                .or_insert(storage_slot)
714                                .present_value = storage_slot.present_value;
715                        }
716                    }
717                    this.info = other_account.info;
718                    this.status.transition(other_account.status);
719
720                    // Update the state size
721                    self.state_size += this.size_hint();
722                }
723                Entry::Vacant(entry) => {
724                    // Just insert if empty
725                    self.state_size += other_account.size_hint();
726                    entry.insert(other_account);
727                }
728            }
729        }
730    }
731    /// Extends the state with state that is build on top of it.
732    ///
733    /// If storage was wiped in `other` state, copy `this` plain state
734    /// and put it inside `other` revert (if there is no duplicates of course).
735    ///
736    /// If `this` and `other` accounts were both destroyed invalidate second
737    /// wipe flag (from `other`).
738    ///
739    /// As wiping from database should be done only once
740    /// and we already transferred all potentially missing storages to the `other` revert.
741    pub fn extend(&mut self, mut other: Self) {
742        // Iterate over reverts and if its storage is wiped try to add previous bundle
743        // state as there is potential missing slots.
744        for (address, revert) in other.reverts.iter_mut().flatten() {
745            if revert.wipe_storage {
746                // If there is wipe storage in `other` revert
747                // we need to move storage from present state.
748                if let Some(this_account) = self.state.get_mut(address) {
749                    // As this account was destroyed inside `other` bundle.
750                    // We are fine to wipe/drain this storage and put it inside revert.
751                    for (key, value) in this_account.storage.drain() {
752                        revert
753                            .storage
754                            .entry(key)
755                            .or_insert(RevertToSlot::Some(value.present_value));
756                    }
757
758                    // Nullify `other` wipe as primary database wipe is done in `this`.
759                    if this_account.was_destroyed() {
760                        revert.wipe_storage = false;
761                    }
762                }
763            }
764
765            // Increment reverts size for each of the updated reverts.
766            self.reverts_size += revert.size_hint();
767        }
768        // Extension of state
769        self.extend_state(other.state);
770        // Contract can be just extended, when counter is introduced we will take into account that.
771        self.contracts.extend(other.contracts);
772        // Reverts can be just extended
773        self.reverts.extend(other.reverts);
774    }
775
776    /// Takes first N raw reverts from the [BundleState].
777    pub fn take_n_reverts(&mut self, reverts_to_take: usize) -> Reverts {
778        // Split is done as [0, num) and [num, len].
779        if reverts_to_take > self.reverts.len() {
780            return self.take_all_reverts();
781        }
782        let (detach, this) = self.reverts.split_at(reverts_to_take);
783        let detached_reverts = Reverts::new(detach.to_vec());
784        self.reverts_size = this
785            .iter()
786            .flatten()
787            .fold(0, |acc, (_, revert)| acc + revert.size_hint());
788        self.reverts = Reverts::new(this.to_vec());
789        detached_reverts
790    }
791
792    /// Returns and clears all reverts from [BundleState].
793    pub fn take_all_reverts(&mut self) -> Reverts {
794        self.reverts_size = 0;
795        mem::take(&mut self.reverts)
796    }
797
798    /// Reverts the state changes of the latest transition.
799    ///
800    /// **Note**: This is the same as `BundleState::revert(1)`
801    ///
802    /// Returns true if the state was reverted.
803    pub fn revert_latest(&mut self) -> bool {
804        // Revert the latest recorded state
805        if let Some(reverts) = self.reverts.pop() {
806            for (address, revert_account) in reverts.into_iter() {
807                self.reverts_size -= revert_account.size_hint();
808                match self.state.entry(address) {
809                    Entry::Occupied(mut entry) => {
810                        let account = entry.get_mut();
811                        self.state_size -= account.size_hint();
812                        if account.revert(revert_account) {
813                            entry.remove();
814                        } else {
815                            self.state_size += account.size_hint();
816                        }
817                    }
818                    Entry::Vacant(entry) => {
819                        // Create empty account that we will revert on.
820                        // Only place where this account is not existing is if revert is DeleteIt.
821                        let mut account = BundleAccount::new(
822                            None,
823                            None,
824                            HashMap::default(),
825                            AccountStatus::LoadedNotExisting,
826                        );
827                        if !account.revert(revert_account) {
828                            self.state_size += account.size_hint();
829                            entry.insert(account);
830                        }
831                    }
832                }
833            }
834            return true;
835        }
836
837        false
838    }
839
840    /// Reverts the state changes by N transitions back.
841    ///
842    /// See also [Self::revert_latest]
843    pub fn revert(&mut self, mut num_transitions: usize) {
844        if num_transitions == 0 {
845            return;
846        }
847
848        while self.revert_latest() {
849            num_transitions -= 1;
850            if num_transitions == 0 {
851                // Break the loop.
852                break;
853            }
854        }
855    }
856
857    /// Prepends present the state with the given [BundleState].
858    ///
859    /// It adds changes from the given state but does not override any existing changes.
860    ///
861    /// Reverts are not updated.
862    pub fn prepend_state(&mut self, mut other: BundleState) {
863        // Take this bundle
864        let this_bundle = mem::take(self);
865        // Extend other bundle state with this
866        other.extend_state(this_bundle.state);
867        // Extend other contracts
868        other.contracts.extend(this_bundle.contracts);
869        // Swap bundles
870        mem::swap(self, &mut other)
871    }
872}
873
874#[cfg(test)]
875mod tests {
876    use super::*;
877    use crate::{StorageWithOriginalValues, TransitionAccount};
878    use primitives::U256;
879
880    #[test]
881    fn transition_states() {
882        // Dummy data
883        let address = Address::new([0x01; 20]);
884        let acc1 = AccountInfo {
885            balance: U256::from(10),
886            nonce: 1,
887            ..Default::default()
888        };
889
890        let mut bundle_state = BundleState::default();
891
892        // Have transition from loaded to all other states
893
894        let transition = TransitionAccount {
895            info: Some(acc1),
896            status: AccountStatus::InMemoryChange,
897            previous_info: None,
898            previous_status: AccountStatus::LoadedNotExisting,
899            storage: StorageWithOriginalValues::default(),
900            storage_was_destroyed: false,
901        };
902
903        // Apply first transition
904        bundle_state.apply_transitions_and_create_reverts(
905            TransitionState::single(address, transition.clone()),
906            BundleRetention::Reverts,
907        );
908    }
909
910    const fn account1() -> Address {
911        Address::new([0x60; 20])
912    }
913
914    const fn account2() -> Address {
915        Address::new([0x61; 20])
916    }
917
918    fn slot1() -> StorageKey {
919        StorageKey::from(5)
920    }
921
922    fn slot2() -> StorageKey {
923        StorageKey::from(7)
924    }
925
926    /// Tests bundle one.
927    fn test_bundle1() -> BundleState {
928        // Block changes
929        BundleState::new(
930            vec![
931                (
932                    account1(),
933                    None,
934                    Some(AccountInfo {
935                        nonce: 1,
936                        balance: U256::from(10),
937                        ..Default::default()
938                    }),
939                    HashMap::from_iter([
940                        (slot1(), (StorageValue::from(0), StorageValue::from(10))),
941                        (slot2(), (StorageValue::from(0), StorageValue::from(15))),
942                    ]),
943                ),
944                (
945                    account2(),
946                    None,
947                    Some(AccountInfo {
948                        nonce: 1,
949                        balance: U256::from(10),
950                        ..Default::default()
951                    }),
952                    HashMap::default(),
953                ),
954            ],
955            vec![vec![
956                (
957                    account1(),
958                    Some(None),
959                    vec![
960                        (slot1(), StorageValue::from(0)),
961                        (slot2(), StorageValue::from(0)),
962                    ],
963                ),
964                (account2(), Some(None), vec![]),
965            ]],
966            vec![],
967        )
968    }
969
970    /// Tests bundle two.
971    fn test_bundle2() -> BundleState {
972        // Block changes
973        BundleState::new(
974            vec![(
975                account1(),
976                None,
977                Some(AccountInfo {
978                    nonce: 3,
979                    balance: U256::from(20),
980                    ..Default::default()
981                }),
982                HashMap::from_iter([(slot1(), (StorageValue::from(0), StorageValue::from(15)))]),
983            )],
984            vec![vec![(
985                account1(),
986                Some(Some(AccountInfo {
987                    nonce: 1,
988                    balance: U256::from(10),
989                    ..Default::default()
990                })),
991                vec![(slot1(), StorageValue::from(10))],
992            )]],
993            vec![],
994        )
995    }
996
997    /// Tests bundle three.
998    fn test_bundle3() -> BundleState {
999        BundleState::builder(0..=0)
1000            .state_present_account_info(
1001                account1(),
1002                AccountInfo {
1003                    nonce: 1,
1004                    balance: U256::from(10),
1005                    ..Default::default()
1006                },
1007            )
1008            .state_storage(
1009                account1(),
1010                HashMap::from_iter([(slot1(), (StorageValue::from(0), StorageValue::from(10)))]),
1011            )
1012            .state_address(account2())
1013            .state_present_account_info(
1014                account2(),
1015                AccountInfo {
1016                    nonce: 1,
1017                    balance: U256::from(10),
1018                    ..Default::default()
1019                },
1020            )
1021            .revert_address(0, account1())
1022            .revert_account_info(0, account1(), Some(None))
1023            .revert_storage(0, account1(), vec![(slot1(), StorageValue::from(0))])
1024            .revert_account_info(0, account2(), Some(None))
1025            .build()
1026    }
1027
1028    /// Tests bundle four.
1029    fn test_bundle4() -> BundleState {
1030        BundleState::builder(0..=0)
1031            .state_present_account_info(
1032                account1(),
1033                AccountInfo {
1034                    nonce: 3,
1035                    balance: U256::from(20),
1036                    ..Default::default()
1037                },
1038            )
1039            .state_storage(
1040                account1(),
1041                HashMap::from_iter([(slot1(), (StorageValue::from(0), StorageValue::from(15)))]),
1042            )
1043            .revert_address(0, account1())
1044            .revert_account_info(
1045                0,
1046                account1(),
1047                Some(Some(AccountInfo {
1048                    nonce: 1,
1049                    balance: U256::from(10),
1050                    ..Default::default()
1051                })),
1052            )
1053            .revert_storage(0, account1(), vec![(slot1(), StorageValue::from(10))])
1054            .build()
1055    }
1056
1057    fn sanity_path(bundle1: BundleState, bundle2: BundleState) {
1058        let mut extended = bundle1.clone();
1059        extended.extend(bundle2.clone());
1060
1061        let mut reverted = extended.clone();
1062        // Revert zero does nothing.
1063        reverted.revert(0);
1064        assert_eq!(reverted, extended);
1065
1066        // Revert by one gives us bundle one.
1067        reverted.revert(1);
1068        assert_eq!(reverted, bundle1);
1069
1070        // Reverted by additional one gives us empty bundle.
1071        reverted.revert(1);
1072        assert_eq!(reverted, BundleState::default());
1073
1074        let mut reverted = extended.clone();
1075
1076        // Reverted by bigger number gives us empty bundle
1077        reverted.revert(10);
1078        assert_eq!(reverted, BundleState::default());
1079    }
1080
1081    #[test]
1082    fn extend_on_destroyed_values() {
1083        let base_bundle1 = test_bundle1();
1084        let base_bundle2 = test_bundle2();
1085
1086        // test1
1087        // bundle1 has Destroyed
1088        // bundle2 has Changed
1089        // end should be DestroyedChanged.
1090        let mut b1 = base_bundle1.clone();
1091        let mut b2 = base_bundle2.clone();
1092        b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1093        b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1094        b1.extend(b2);
1095        assert_eq!(
1096            b1.state.get_mut(&account1()).unwrap().status,
1097            AccountStatus::DestroyedChanged
1098        );
1099
1100        // test2
1101        // bundle1 has Changed
1102        // bundle2 has Destroyed
1103        // end should be Destroyed
1104        let mut b1 = base_bundle1.clone();
1105        let mut b2 = base_bundle2.clone();
1106        b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1107        b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1108        b2.reverts[0][0].1.wipe_storage = true;
1109        b1.extend(b2);
1110        assert_eq!(
1111            b1.state.get_mut(&account1()).unwrap().status,
1112            AccountStatus::Destroyed
1113        );
1114
1115        // test2 extension
1116        // revert of b2 should contains plain state of b1.
1117        let mut revert1 = base_bundle2.reverts[0][0].clone();
1118        revert1.1.wipe_storage = true;
1119        revert1
1120            .1
1121            .storage
1122            .insert(slot2(), RevertToSlot::Some(StorageValue::from(15)));
1123
1124        assert_eq!(
1125            b1.reverts.as_ref(),
1126            vec![base_bundle1.reverts[0].clone(), vec![revert1]],
1127        );
1128
1129        // test3
1130        // bundle1 has InMemoryChange
1131        // bundle2 has Change
1132        // end should be InMemoryChange.
1133
1134        let mut b1 = base_bundle1.clone();
1135        let mut b2 = base_bundle2.clone();
1136        b1.state.get_mut(&account1()).unwrap().status = AccountStatus::InMemoryChange;
1137        b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1138        b1.extend(b2);
1139        assert_eq!(
1140            b1.state.get_mut(&account1()).unwrap().status,
1141            AccountStatus::InMemoryChange
1142        );
1143    }
1144
1145    #[test]
1146    fn test_sanity_path() {
1147        sanity_path(test_bundle1(), test_bundle2());
1148        sanity_path(test_bundle3(), test_bundle4());
1149    }
1150
1151    #[test]
1152    fn test_multi_reverts_with_delete() {
1153        let mut state = BundleBuilder::new(0..=3)
1154            .revert_address(0, account1())
1155            .revert_account_info(2, account1(), Some(Some(AccountInfo::default())))
1156            .revert_account_info(3, account1(), Some(None))
1157            .build();
1158
1159        state.revert_latest();
1160        // State for account one was deleted
1161        assert_eq!(state.state.get(&account1()), None);
1162
1163        state.revert_latest();
1164        // State is set to
1165        assert_eq!(
1166            state.state.get(&account1()),
1167            Some(&BundleAccount::new(
1168                None,
1169                Some(AccountInfo::default()),
1170                HashMap::default(),
1171                AccountStatus::Changed
1172            ))
1173        );
1174    }
1175
1176    #[test]
1177    fn test_revert_capacity() {
1178        let state = BundleState::builder(0..=3)
1179            .revert_address(0, account1())
1180            .revert_address(2, account2())
1181            .revert_account_info(0, account1(), Some(None))
1182            .revert_account_info(2, account2(), None)
1183            .revert_storage(0, account1(), vec![(slot1(), StorageValue::from(10))])
1184            .build();
1185
1186        assert_eq!(state.reverts.len(), 4);
1187        assert_eq!(state.reverts[1], vec![]);
1188        assert_eq!(state.reverts[3], vec![]);
1189        assert_eq!(state.reverts[0].len(), 1);
1190        assert_eq!(state.reverts[2].len(), 1);
1191
1192        let (addr1, revert1) = &state.reverts[0][0];
1193        assert_eq!(addr1, &account1());
1194        assert_eq!(revert1.account, AccountInfoRevert::DeleteIt);
1195
1196        let (addr2, revert2) = &state.reverts[2][0];
1197        assert_eq!(addr2, &account2());
1198        assert_eq!(revert2.account, AccountInfoRevert::DoNothing);
1199    }
1200
1201    #[test]
1202    fn take_reverts() {
1203        let bundle1 = test_bundle1();
1204        let bundle2 = test_bundle2();
1205
1206        let mut extended = bundle1.clone();
1207        extended.extend(bundle2.clone());
1208
1209        // Check that we have two reverts
1210        assert_eq!(extended.reverts.len(), 2);
1211
1212        // Take all by big N
1213        let mut extended2 = extended.clone();
1214        assert_eq!(extended2.take_n_reverts(100), extended.reverts);
1215
1216        // Take all reverts
1217        let mut extended2 = extended.clone();
1218        assert_eq!(extended2.take_all_reverts(), extended.reverts);
1219
1220        // Take zero revert
1221        let taken_reverts = extended.take_n_reverts(0);
1222        assert_eq!(taken_reverts, Reverts::default());
1223        assert_eq!(extended.reverts.len(), 2);
1224
1225        // Take one revert
1226        let taken_reverts = extended.take_n_reverts(1);
1227        assert_eq!(taken_reverts, bundle1.reverts);
1228
1229        // Take last revert
1230        let taken_reverts = extended.take_n_reverts(1);
1231        assert_eq!(taken_reverts, bundle2.reverts);
1232    }
1233
1234    #[test]
1235    fn prepend_state() {
1236        let address1 = account1();
1237        let address2 = account2();
1238
1239        let account1 = AccountInfo {
1240            nonce: 1,
1241            ..Default::default()
1242        };
1243        let account1_changed = AccountInfo {
1244            nonce: 1,
1245            ..Default::default()
1246        };
1247        let account2 = AccountInfo {
1248            nonce: 1,
1249            ..Default::default()
1250        };
1251
1252        let present_state = BundleState::builder(2..=2)
1253            .state_present_account_info(address1, account1_changed.clone())
1254            .build();
1255        assert_eq!(present_state.reverts.len(), 1);
1256        let previous_state = BundleState::builder(1..=1)
1257            .state_present_account_info(address1, account1)
1258            .state_present_account_info(address2, account2.clone())
1259            .build();
1260        assert_eq!(previous_state.reverts.len(), 1);
1261
1262        let mut test = present_state;
1263
1264        test.prepend_state(previous_state);
1265
1266        assert_eq!(test.state.len(), 2);
1267        // Reverts num should stay the same.
1268        assert_eq!(test.reverts.len(), 1);
1269        // Account1 is not overwritten.
1270        assert_eq!(
1271            test.state.get(&address1).unwrap().info,
1272            Some(account1_changed)
1273        );
1274        // Account2 got inserted
1275        assert_eq!(test.state.get(&address2).unwrap().info, Some(account2));
1276    }
1277
1278    #[test]
1279    fn test_getters() {
1280        let mut builder = BundleBuilder::new(0..=3);
1281
1282        // Test get_states and get_states_mut
1283        assert!(builder.get_states().is_empty());
1284        builder.get_states_mut().insert(account1());
1285        assert!(builder.get_states().contains(&account1()));
1286
1287        // Test get_state_original_mut
1288        assert!(builder.get_state_original_mut().is_empty());
1289        builder
1290            .get_state_original_mut()
1291            .insert(account1(), AccountInfo::default());
1292        assert!(builder.get_state_original_mut().contains_key(&account1()));
1293
1294        // Test get_state_present_mut
1295        assert!(builder.get_state_present_mut().is_empty());
1296        builder
1297            .get_state_present_mut()
1298            .insert(account1(), AccountInfo::default());
1299        assert!(builder.get_state_present_mut().contains_key(&account1()));
1300
1301        // Test get_state_storage_mut
1302        assert!(builder.get_state_storage_mut().is_empty());
1303        builder
1304            .get_state_storage_mut()
1305            .insert(account1(), HashMap::default());
1306        assert!(builder.get_state_storage_mut().contains_key(&account1()));
1307
1308        // Test get_reverts_mut
1309        assert!(builder.get_reverts_mut().is_empty());
1310        builder.get_reverts_mut().insert((0, account1()));
1311        assert!(builder.get_reverts_mut().contains(&(0, account1())));
1312
1313        // Test get_revert_range_mut
1314        assert_eq!(builder.get_revert_range_mut().clone(), 0..=3);
1315
1316        // Test get_revert_account_mut
1317        assert!(builder.get_revert_account_mut().is_empty());
1318        builder
1319            .get_revert_account_mut()
1320            .insert((0, account1()), Some(None));
1321        assert!(builder
1322            .get_revert_account_mut()
1323            .contains_key(&(0, account1())));
1324
1325        // Test get_revert_storage_mut
1326        assert!(builder.get_revert_storage_mut().is_empty());
1327        builder
1328            .get_revert_storage_mut()
1329            .insert((0, account1()), vec![(slot1(), StorageValue::from(0))]);
1330        assert!(builder
1331            .get_revert_storage_mut()
1332            .contains_key(&(0, account1())));
1333
1334        // Test get_contracts_mut
1335        assert!(builder.get_contracts_mut().is_empty());
1336        builder
1337            .get_contracts_mut()
1338            .insert(B256::default(), Bytecode::default());
1339        assert!(builder.get_contracts_mut().contains_key(&B256::default()));
1340    }
1341}