anvil_zksync_core/node/
storage_logs.rs1use std::collections::HashMap;
2
3use crate::formatter::log::Formatter;
4use crate::formatter::pubdata_bytes::PubdataBytesInfo;
5
6use anvil_zksync_common::sh_println;
7use anvil_zksync_types::ShowStorageLogs;
8use zksync_multivm::interface::VmExecutionResultAndLogs;
9use zksync_types::h256_to_u256;
10use zksync_types::{
11 utils::storage_key_for_eth_balance,
12 writes::{
13 compression::compress_with_best_strategy, BYTES_PER_DERIVED_KEY,
14 BYTES_PER_ENUMERATION_INDEX,
15 },
16 StorageKey, BOOTLOADER_ADDRESS, SYSTEM_CONTEXT_ADDRESS,
17};
18use zksync_types::{StorageLogKind, StorageLogWithPreviousValue};
19
20fn is_storage_key_free(key: &StorageKey) -> bool {
21 key.address() == &SYSTEM_CONTEXT_ADDRESS
22 || *key == storage_key_for_eth_balance(&BOOTLOADER_ADDRESS)
23}
24
25fn compute_and_update_pubdata_cost(
26 cost_paid: &mut HashMap<StorageKey, u32>,
27 log_query: &StorageLogWithPreviousValue,
28) -> PubdataBytesInfo {
29 let storage_key = log_query.log.key;
30
31 if is_storage_key_free(&storage_key) {
32 PubdataBytesInfo::FreeSlot
33 } else {
34 let compressed_value_size = compress_with_best_strategy(
36 h256_to_u256(log_query.previous_value),
37 h256_to_u256(log_query.log.value),
38 )
39 .len() as u32;
40
41 let final_pubdata_cost = if log_query.log.kind == StorageLogKind::InitialWrite {
42 (BYTES_PER_DERIVED_KEY as u32) + compressed_value_size
43 } else {
44 (BYTES_PER_ENUMERATION_INDEX as u32) + compressed_value_size
45 };
46
47 let result = match cost_paid.get(&storage_key).copied() {
48 Some(already_paid) => {
49 let to_pay = final_pubdata_cost.saturating_sub(already_paid);
50 if to_pay > 0 {
51 PubdataBytesInfo::AdditionalPayment(to_pay, final_pubdata_cost)
52 } else {
53 PubdataBytesInfo::PaidAlready
54 }
55 }
56 None => PubdataBytesInfo::Paid(final_pubdata_cost),
57 };
58 cost_paid.insert(storage_key, final_pubdata_cost);
59 result
60 }
61}
62
63pub fn print_storage_logs_details(
64 show_storage_logs: ShowStorageLogs,
65 result: &VmExecutionResultAndLogs,
66) {
67 sh_println!("\n");
68 sh_println!(
69 "[Storage Logs] ({} entries)",
70 result.logs.storage_logs.len()
71 );
72
73 let mut cost_paid = HashMap::<StorageKey, u32>::default();
74
75 for (index, log_query) in result.logs.storage_logs.iter().enumerate() {
76 let pubdata_bytes_info = if matches!(
77 log_query.log.kind,
78 StorageLogKind::RepeatedWrite | StorageLogKind::InitialWrite
79 ) {
80 Some(compute_and_update_pubdata_cost(&mut cost_paid, log_query))
81 } else {
82 None
83 };
84
85 let should_print = match show_storage_logs {
87 ShowStorageLogs::Write => matches!(
88 log_query.log.kind,
89 StorageLogKind::RepeatedWrite | StorageLogKind::InitialWrite
90 ),
91 ShowStorageLogs::Paid => pubdata_bytes_info
92 .as_ref()
93 .map(|x| x.does_cost())
94 .unwrap_or_default(),
95 ShowStorageLogs::Read => log_query.log.kind == StorageLogKind::Read,
96 ShowStorageLogs::All => true,
97 _ => false,
98 };
99
100 if should_print {
101 let is_last = index == result.logs.storage_logs.len() - 1;
102 let mut formatter = Formatter::new();
103 formatter.print_storage_logs(log_query, pubdata_bytes_info, index + 1, is_last);
104 }
105 }
106}