stratus/eth/primitives/
execution_account_changes.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use std::collections::BTreeMap;

use display_json::DebugAsJson;

use super::CodeHash;
use crate::alias::RevmBytecode;
use crate::eth::primitives::Account;
use crate::eth::primitives::Address;
use crate::eth::primitives::ExecutionValueChange;
use crate::eth::primitives::Nonce;
use crate::eth::primitives::Slot;
use crate::eth::primitives::SlotIndex;
use crate::eth::primitives::Wei;

/// Changes that happened to an account during a transaction.
#[derive(DebugAsJson, Clone, PartialEq, Eq, fake::Dummy, serde::Serialize, serde::Deserialize)]
pub struct ExecutionAccountChanges {
    pub new_account: bool,
    pub address: Address,
    pub nonce: ExecutionValueChange<Nonce>,
    pub balance: ExecutionValueChange<Wei>,

    // TODO: bytecode related information should be grouped in a Bytecode struct
    #[dummy(default)]
    pub bytecode: ExecutionValueChange<Option<RevmBytecode>>,
    pub code_hash: CodeHash, // TODO: should be wrapped in a ExecutionValueChange
    pub slots: BTreeMap<SlotIndex, ExecutionValueChange<Slot>>,
}

impl ExecutionAccountChanges {
    /// Creates a new [`ExecutionAccountChanges`] from Account original values.
    pub fn from_original_values(account: impl Into<Account>) -> Self {
        let account: Account = account.into();
        Self {
            new_account: false,
            address: account.address,
            nonce: ExecutionValueChange::from_original(account.nonce),
            balance: ExecutionValueChange::from_original(account.balance),
            bytecode: ExecutionValueChange::from_original(account.bytecode),
            slots: BTreeMap::new(),
            code_hash: account.code_hash,
        }
    }

    /// Creates a new [`ExecutionAccountChanges`] from Account modified values.
    pub fn from_modified_values(account: impl Into<Account>, modified_slots: Vec<Slot>) -> Self {
        let account: Account = account.into();
        let mut changes = Self {
            new_account: true,
            address: account.address,
            nonce: ExecutionValueChange::from_modified(account.nonce),
            balance: ExecutionValueChange::from_modified(account.balance),

            // bytecode
            bytecode: ExecutionValueChange::from_modified(account.bytecode),
            code_hash: account.code_hash,

            slots: BTreeMap::new(),
        };

        for slot in modified_slots {
            changes.slots.insert(slot.index, ExecutionValueChange::from_modified(slot));
        }

        changes
    }

    /// Updates an existing account state with changes that happened during the transaction.
    pub fn apply_modifications(&mut self, modified_account: Account, modified_slots: Vec<Slot>) {
        // update nonce if modified
        let is_nonce_modified = match self.nonce.take_original_ref() {
            Some(original_nonce) => *original_nonce != modified_account.nonce,
            None => true,
        };
        if is_nonce_modified {
            self.nonce.set_modified(modified_account.nonce);
        }

        // update balance if modified
        let is_balance_modified = match self.balance.take_original_ref() {
            Some(original_balance) => *original_balance != modified_account.balance,
            None => true,
        };
        if is_balance_modified {
            self.balance.set_modified(modified_account.balance);
        }

        // update all slots because all of them are modified
        for slot in modified_slots {
            match self.slots.get_mut(&slot.index) {
                Some(ref mut entry) => {
                    entry.set_modified(slot);
                }
                None => {
                    self.slots.insert(slot.index, ExecutionValueChange::from_modified(slot));
                }
            };
        }
    }

    /// Checks if account nonce, balance or bytecode were modified.
    pub fn is_account_modified(&self) -> bool {
        self.nonce.is_modified() || self.balance.is_modified() || self.bytecode.is_modified()
    }
}