1use crate::{
4 bal::{writes::BalWrites, BalError, BlockAccessIndex},
5 Account, AccountInfo, EvmStorage,
6};
7use alloy_eip7928::{
8 AccountChanges as AlloyAccountChanges, BalanceChange as AlloyBalanceChange,
9 CodeChange as AlloyCodeChange, NonceChange as AlloyNonceChange,
10 SlotChanges as AlloySlotChanges, StorageChange as AlloyStorageChange,
11};
12use bytecode::{Bytecode, BytecodeDecodeError};
13use core::ops::{Deref, DerefMut};
14use primitives::{Address, StorageKey, StorageValue, B256, U256};
15use std::{
16 collections::{btree_map::Entry, BTreeMap},
17 vec::Vec,
18};
19
20#[derive(Debug, Default, Clone, PartialEq, Eq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct AccountBal {
24 pub account_info: AccountInfoBal,
26 pub storage: StorageBal,
28}
29
30impl Deref for AccountBal {
31 type Target = AccountInfoBal;
32
33 fn deref(&self) -> &Self::Target {
34 &self.account_info
35 }
36}
37
38impl DerefMut for AccountBal {
39 fn deref_mut(&mut self) -> &mut Self::Target {
40 &mut self.account_info
41 }
42}
43
44impl AccountBal {
45 pub fn populate_account_info(
47 &self,
48 bal_index: BlockAccessIndex,
49 account: &mut AccountInfo,
50 ) -> bool {
51 self.account_info.populate_account_info(bal_index, account)
52 }
53
54 #[inline]
56 pub fn update(&mut self, bal_index: BlockAccessIndex, account: &Account) {
57 if account.is_selfdestructed_locally() {
58 let empty_info = AccountInfo::default();
59 self.account_info
60 .update(bal_index, &account.original_info(), &empty_info);
61 self.storage
63 .update_selfdestruct(bal_index, &account.storage);
64 return;
65 }
66
67 self.account_info
68 .update(bal_index, &account.original_info(), &account.info);
69
70 self.storage.update(bal_index, &account.storage);
71 }
72
73 #[inline]
82 pub fn try_from_alloy(
83 alloy_account: AlloyAccountChanges,
84 ) -> Result<(Address, Self), BytecodeDecodeError> {
85 Ok((
86 alloy_account.address,
87 AccountBal {
88 account_info: AccountInfoBal {
89 nonce: BalWrites::from(alloy_account.nonce_changes),
90 balance: BalWrites::from(alloy_account.balance_changes),
91 code: BalWrites::try_from(alloy_account.code_changes)?,
92 },
93 storage: StorageBal::from_iter(
94 alloy_account
95 .storage_changes
96 .into_iter()
97 .chain(
98 alloy_account
99 .storage_reads
100 .into_iter()
101 .map(|key| AlloySlotChanges::new(key, Default::default())),
102 )
103 .map(|slot| (slot.slot, BalWrites::from(slot.changes))),
104 ),
105 },
106 ))
107 }
108
109 #[inline]
118 pub fn clone_from_alloy(
119 alloy_account: &AlloyAccountChanges,
120 ) -> Result<(Address, Self), BytecodeDecodeError> {
121 Ok((
122 alloy_account.address,
123 AccountBal {
124 account_info: AccountInfoBal {
125 nonce: BalWrites::from(alloy_account.nonce_changes.as_slice()),
126 balance: BalWrites::from(alloy_account.balance_changes.as_slice()),
127 code: BalWrites::try_from(alloy_account.code_changes.as_slice())?,
128 },
129 storage: StorageBal::from_iter(
130 alloy_account
131 .storage_changes
132 .iter()
133 .map(|slot| (slot.slot, BalWrites::from(slot.changes.as_slice())))
134 .chain(
135 alloy_account
136 .storage_reads
137 .iter()
138 .map(|key| (*key, BalWrites::default())),
139 ),
140 ),
141 },
142 ))
143 }
144
145 #[inline]
156 pub fn into_alloy_account(self, address: Address) -> AlloyAccountChanges {
157 let storage_len = self.storage.storage.len();
158 let mut storage_reads = Vec::with_capacity(storage_len);
159 let mut storage_changes = Vec::with_capacity(storage_len);
160 for (key, value) in self.storage.storage {
161 if value.writes.is_empty() {
162 storage_reads.push(key);
163 } else {
164 let mut changes = value
165 .writes
166 .into_iter()
167 .map(|(index, value)| AlloyStorageChange::new(index, value))
168 .collect::<Vec<_>>();
169 changes.sort_unstable_by_key(|change| change.block_access_index);
170
171 storage_changes.push(AlloySlotChanges::new(key, changes));
172 }
173 }
174
175 let mut balance_changes = self
176 .account_info
177 .balance
178 .writes
179 .into_iter()
180 .map(|(index, value)| AlloyBalanceChange::new(index, value))
181 .collect::<Vec<_>>();
182 balance_changes.sort_unstable_by_key(|change| change.block_access_index);
183
184 let mut nonce_changes = self
185 .account_info
186 .nonce
187 .writes
188 .into_iter()
189 .map(|(index, value)| AlloyNonceChange::new(index, value))
190 .collect::<Vec<_>>();
191 nonce_changes.sort_unstable_by_key(|change| change.block_access_index);
192
193 let mut code_changes = self
194 .account_info
195 .code
196 .writes
197 .into_iter()
198 .map(|(index, (_, value))| AlloyCodeChange::new(index, value.original_bytes()))
199 .collect::<Vec<_>>();
200 code_changes.sort_unstable_by_key(|change| change.block_access_index);
201
202 AlloyAccountChanges {
203 address,
204 storage_changes,
205 storage_reads,
206 balance_changes,
207 nonce_changes,
208 code_changes,
209 }
210 }
211}
212
213#[derive(Debug, Default, Clone, PartialEq, Eq)]
215#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
216pub struct AccountInfoBal {
217 pub nonce: BalWrites<u64>,
219 pub balance: BalWrites<U256>,
221 pub code: BalWrites<(B256, Bytecode)>,
223}
224
225impl AccountInfoBal {
226 pub fn populate_account_info(
228 &self,
229 bal_index: BlockAccessIndex,
230 account: &mut AccountInfo,
231 ) -> bool {
232 let mut changed = false;
233 if let Some(nonce) = self.nonce.get(bal_index) {
234 account.nonce = nonce;
235 changed = true;
236 }
237 if let Some(balance) = self.balance.get(bal_index) {
238 account.balance = balance;
239 changed = true;
240 }
241 if let Some(code) = self.code.get(bal_index) {
242 account.code_hash = code.0;
243 account.code = Some(code.1);
244 changed = true;
245 }
246 changed
247 }
248
249 #[inline]
251 pub fn update(
252 &mut self,
253 index: BlockAccessIndex,
254 original: &AccountInfo,
255 present: &AccountInfo,
256 ) {
257 self.nonce.update(index, &original.nonce, present.nonce);
258 self.balance
259 .update(index, &original.balance, present.balance);
260 if original.code_hash != present.code_hash {
261 self.code.update_with_key(
262 index,
263 &original.code_hash,
264 (present.code_hash, present.code.clone().unwrap_or_default()),
265 |i| &i.0,
266 );
267 }
268 }
269
270 #[inline]
272 pub fn extend(&mut self, bal_account: AccountInfoBal) {
273 self.nonce.extend(bal_account.nonce);
274 self.balance.extend(bal_account.balance);
275 self.code.extend(bal_account.code);
276 }
277
278 #[inline]
280 pub fn balance_update(
281 &mut self,
282 bal_index: BlockAccessIndex,
283 original_balance: &U256,
284 balance: U256,
285 ) {
286 self.balance.update(bal_index, original_balance, balance);
287 }
288
289 #[inline]
291 pub fn nonce_update(&mut self, bal_index: BlockAccessIndex, original_nonce: &u64, nonce: u64) {
292 self.nonce.update(bal_index, original_nonce, nonce);
293 }
294
295 #[inline]
297 pub fn code_update(
298 &mut self,
299 bal_index: BlockAccessIndex,
300 original_code_hash: &B256,
301 code_hash: B256,
302 code: Bytecode,
303 ) {
304 self.code
305 .update_with_key(bal_index, original_code_hash, (code_hash, code), |i| &i.0);
306 }
307}
308
309#[derive(Debug, Default, Clone, PartialEq, Eq)]
311#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
312pub struct StorageBal {
313 pub storage: BTreeMap<StorageKey, BalWrites<StorageValue>>,
315}
316
317impl StorageBal {
318 #[inline]
320 pub fn get(
321 &self,
322 address: &Address,
323 key: StorageKey,
324 bal_index: BlockAccessIndex,
325 ) -> Result<Option<StorageValue>, BalError> {
326 Ok(self.get_bal_writes(address, key)?.get(bal_index))
327 }
328
329 #[inline]
333 pub fn get_bal_writes(
334 &self,
335 address: &Address,
336 key: StorageKey,
337 ) -> Result<&BalWrites<StorageValue>, BalError> {
338 self.storage.get(&key).ok_or(BalError::SlotNotFound {
339 address: *address,
340 slot: key,
341 })
342 }
343
344 #[inline]
346 pub fn extend(&mut self, storage: StorageBal) {
347 for (key, value) in storage.storage {
348 match self.storage.entry(key) {
349 Entry::Occupied(mut entry) => {
350 entry.get_mut().extend(value);
351 }
352 Entry::Vacant(entry) => {
353 entry.insert(value);
354 }
355 }
356 }
357 }
358
359 #[inline]
361 pub fn update(&mut self, bal_index: BlockAccessIndex, storage: &EvmStorage) {
362 for (key, value) in storage {
363 self.storage.entry(*key).or_default().update(
364 bal_index,
365 &value.original_value,
366 value.present_value,
367 );
368 }
369 }
370
371 #[inline]
375 pub fn update_selfdestruct(&mut self, bal_index: BlockAccessIndex, storage: &EvmStorage) {
376 for (key, value) in storage {
377 self.storage.entry(*key).or_default().update(
378 bal_index,
379 &value.original_value,
380 StorageValue::ZERO,
381 );
382 }
383 }
384
385 #[inline]
389 pub fn update_reads(&mut self, storage: impl Iterator<Item = StorageKey>) {
390 for key in storage {
391 self.storage.entry(key).or_default();
392 }
393 }
394
395 pub fn extend_iter(
397 &mut self,
398 storage: impl Iterator<Item = (StorageKey, BalWrites<StorageValue>)>,
399 ) {
400 for (key, value) in storage {
401 self.storage.insert(key, value);
402 }
403 }
404
405 pub fn into_vecs(self) -> (Vec<StorageKey>, Vec<(StorageKey, BalWrites<StorageValue>)>) {
407 let mut reads = Vec::new();
408 let mut writes = Vec::new();
409
410 for (key, value) in self.storage {
411 if value.writes.is_empty() {
412 reads.push(key);
413 } else {
414 writes.push((key, value));
415 }
416 }
417
418 (reads, writes)
419 }
420}
421
422impl FromIterator<(StorageKey, BalWrites<StorageValue>)> for StorageBal {
423 fn from_iter<I: IntoIterator<Item = (StorageKey, BalWrites<StorageValue>)>>(iter: I) -> Self {
424 Self {
425 storage: iter.into_iter().collect(),
426 }
427 }
428}