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