stratus/eth/primitives/
execution_account_changes.rs1use std::collections::BTreeMap;
2
3use display_json::DebugAsJson;
4
5use crate::alias::RevmBytecode;
6use crate::eth::primitives::Account;
7use crate::eth::primitives::Address;
8use crate::eth::primitives::ExecutionValueChange;
9use crate::eth::primitives::Nonce;
10use crate::eth::primitives::Slot;
11use crate::eth::primitives::SlotIndex;
12use crate::eth::primitives::Wei;
13
14#[derive(DebugAsJson, Clone, PartialEq, Eq, fake::Dummy, serde::Serialize, serde::Deserialize)]
16pub struct ExecutionAccountChanges {
17 pub nonce: ExecutionValueChange<Nonce>,
18 pub balance: ExecutionValueChange<Wei>,
19
20 #[dummy(default)]
22 pub bytecode: ExecutionValueChange<Option<RevmBytecode>>,
23 pub slots: BTreeMap<SlotIndex, ExecutionValueChange<Slot>>, }
25
26impl ExecutionAccountChanges {
27 pub fn merge(&mut self, other: ExecutionAccountChanges) {
30 self.nonce = other.nonce;
31 self.balance = other.balance;
32 self.bytecode = other.bytecode;
33
34 for (slot_index, slot_change) in other.slots {
36 self.slots.insert(slot_index, slot_change);
37 }
38 }
39
40 pub fn update_empty_values(&mut self, other: Account) {
41 if self.nonce.is_empty() {
42 self.nonce.set_original(other.nonce);
43 }
44 if self.balance.is_empty() {
45 self.balance.set_original(other.balance);
46 }
47 if self.bytecode.is_empty() {
48 self.bytecode.set_original(other.bytecode);
49 }
50 }
51
52 pub fn from_original_values(account: impl Into<Account>) -> Self {
54 let account: Account = account.into();
55 Self {
56 nonce: ExecutionValueChange::from_original(account.nonce),
57 balance: ExecutionValueChange::from_original(account.balance),
58 bytecode: ExecutionValueChange::from_original(account.bytecode),
59 slots: BTreeMap::new(),
60 }
61 }
62
63 pub fn from_modified_values(account: impl Into<Account>, modified_slots: Vec<Slot>) -> Self {
65 let account: Account = account.into();
66 let mut changes = Self {
67 nonce: ExecutionValueChange::from_modified(account.nonce),
68 balance: ExecutionValueChange::from_modified(account.balance),
69
70 bytecode: ExecutionValueChange::from_modified(account.bytecode),
72 slots: BTreeMap::new(),
73 };
74
75 for slot in modified_slots {
76 changes.slots.insert(slot.index, ExecutionValueChange::from_modified(slot));
77 }
78
79 changes
80 }
81
82 pub fn apply_modifications(&mut self, modified_account: Account, modified_slots: Vec<Slot>) {
84 let is_nonce_modified = match self.nonce.take_original_ref() {
86 Some(original_nonce) => *original_nonce != modified_account.nonce,
87 None => true,
88 };
89 if is_nonce_modified {
90 self.nonce.set_modified(modified_account.nonce);
91 }
92
93 let is_balance_modified = match self.balance.take_original_ref() {
95 Some(original_balance) => *original_balance != modified_account.balance,
96 None => true,
97 };
98 if is_balance_modified {
99 self.balance.set_modified(modified_account.balance);
100 }
101
102 for slot in modified_slots {
104 match self.slots.get_mut(&slot.index) {
105 Some(ref mut entry) => {
106 entry.set_modified(slot);
107 }
108 None => {
109 self.slots.insert(slot.index, ExecutionValueChange::from_modified(slot));
110 }
111 };
112 }
113 }
114
115 pub fn is_account_modified(&self) -> bool {
117 self.nonce.is_modified() || self.balance.is_modified() || self.bytecode.is_modified()
118 }
119
120 pub fn to_account(self, address: Address) -> Account {
121 Account {
122 address,
123 nonce: self.nonce.take().unwrap_or_default(),
124 balance: self.balance.take().unwrap_or_default(),
125 bytecode: self.bytecode.take().unwrap_or_default(),
126 }
127 }
128}