diff --git a/Cargo.lock b/Cargo.lock index caace59cdda3..6f57271d40cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8299,7 +8299,6 @@ version = "0.1.0" dependencies = [ "anyhow", "itertools", - "metrics", "mini-moka", "rand 0.8.5", "tempfile", diff --git a/core/lib/config/src/configs/contracts.rs b/core/lib/config/src/configs/contracts.rs index 1ae5e327ff2a..5980a165cfed 100644 --- a/core/lib/config/src/configs/contracts.rs +++ b/core/lib/config/src/configs/contracts.rs @@ -5,6 +5,13 @@ use zksync_basic_types::{Address, H256}; // Local uses use super::envy_load; +#[derive(Debug, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum ProverAtGenesis { + Fri, + Old, +} + /// Data about deployed contracts. #[derive(Debug, Deserialize, Clone, PartialEq)] pub struct ContractsConfig { @@ -34,7 +41,7 @@ pub struct ContractsConfig { pub fri_recursion_scheduler_level_vk_hash: H256, pub fri_recursion_node_level_vk_hash: H256, pub fri_recursion_leaf_level_vk_hash: H256, - pub prover_at_genesis: String, + pub prover_at_genesis: ProverAtGenesis, pub snark_wrapper_vk_hash: H256, } @@ -95,7 +102,7 @@ mod tests { fri_recursion_leaf_level_vk_hash: hash( "0x72167c43a46cf38875b267d67716edc4563861364a3c03ab7aee73498421e828", ), - prover_at_genesis: "fri".to_string(), + prover_at_genesis: ProverAtGenesis::Fri, snark_wrapper_vk_hash: hash( "0x4be443afd605a782b6e56d199df2460a025c81b3dea144e135bece83612563f2", ), diff --git a/core/lib/dal/src/blocks_dal.rs b/core/lib/dal/src/blocks_dal.rs index d2ea5f6741e9..ba6684651b7e 100644 --- a/core/lib/dal/src/blocks_dal.rs +++ b/core/lib/dal/src/blocks_dal.rs @@ -352,12 +352,12 @@ impl BlocksDal<'_, '_> { let l2_to_l1_logs: Vec<_> = header .l2_to_l1_logs .iter() - .map(|log| log.to_bytes().to_vec()) + .map(|log| log.0.to_bytes().to_vec()) .collect(); let system_logs = header .system_logs .iter() - .map(|log| log.to_bytes().to_vec()) + .map(|log| log.0.to_bytes().to_vec()) .collect::>>(); // Serialization should always succeed. @@ -1496,7 +1496,10 @@ impl BlocksDal<'_, '_> { #[cfg(test)] mod tests { use zksync_contracts::BaseSystemContractsHashes; - use zksync_types::{l2_to_l1_log::L2ToL1Log, Address, ProtocolVersion, ProtocolVersionId}; + use zksync_types::{ + l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log}, + Address, ProtocolVersion, ProtocolVersionId, + }; use super::*; use crate::ConnectionPool; @@ -1525,14 +1528,14 @@ mod tests { ); header.l1_tx_count = 3; header.l2_tx_count = 5; - header.l2_to_l1_logs.push(L2ToL1Log { + header.l2_to_l1_logs.push(UserL2ToL1Log(L2ToL1Log { shard_id: 0, is_service: false, tx_number_in_block: 2, sender: Address::repeat_byte(2), key: H256::repeat_byte(3), value: H256::zero(), - }); + })); header.l2_to_l1_messages.push(vec![22; 22]); header.l2_to_l1_messages.push(vec![33; 33]); diff --git a/core/lib/dal/src/events_dal.rs b/core/lib/dal/src/events_dal.rs index 2702099e5810..6355deaf29ab 100644 --- a/core/lib/dal/src/events_dal.rs +++ b/core/lib/dal/src/events_dal.rs @@ -4,7 +4,9 @@ use std::fmt; use crate::{models::storage_event::StorageL2ToL1Log, SqlxError, StorageProcessor}; use zksync_types::{ - l2_to_l1_log::L2ToL1Log, tx::IncludedTxLocation, MiniblockNumber, VmEvent, H256, + l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log}, + tx::IncludedTxLocation, + MiniblockNumber, VmEvent, H256, }; /// Wrapper around an optional event topic allowing to hex-format it for `COPY` instructions. @@ -99,12 +101,12 @@ impl EventsDal<'_, '_> { .unwrap(); } - /// Saves L2-to-L1 logs from a miniblock. Logs must be ordered by transaction location + /// Saves user L2-to-L1 logs from a miniblock. Logs must be ordered by transaction location /// and within each transaction. - pub async fn save_l2_to_l1_logs( + pub async fn save_user_l2_to_l1_logs( &mut self, block_number: MiniblockNumber, - all_block_l2_to_l1_logs: &[(IncludedTxLocation, Vec<&L2ToL1Log>)], + all_block_l2_to_l1_logs: &[(IncludedTxLocation, Vec<&UserL2ToL1Log>)], ) { let mut copy = self .storage @@ -139,7 +141,7 @@ impl EventsDal<'_, '_> { sender, key, value, - } = log; + } = log.0; write_str!( &mut buffer, @@ -273,15 +275,15 @@ mod tests { } } - fn create_l2_to_l1_log(tx_number_in_block: u16, index: u8) -> L2ToL1Log { - L2ToL1Log { + fn create_l2_to_l1_log(tx_number_in_block: u16, index: u8) -> UserL2ToL1Log { + UserL2ToL1Log(L2ToL1Log { shard_id: 0, is_service: false, tx_number_in_block, sender: Address::repeat_byte(index), key: H256::from_low_u64_be(u64::from(index)), value: H256::repeat_byte(index), - } + }) } #[tokio::test] @@ -324,7 +326,7 @@ mod tests { (second_location, second_logs.iter().collect()), ]; conn.events_dal() - .save_l2_to_l1_logs(MiniblockNumber(1), &all_logs) + .save_user_l2_to_l1_logs(MiniblockNumber(1), &all_logs) .await; let logs = conn @@ -338,9 +340,9 @@ mod tests { assert_eq!(log.log_index_in_tx as usize, i); } for (log, expected_log) in logs.iter().zip(&first_logs) { - assert_eq!(log.key, expected_log.key.as_bytes()); - assert_eq!(log.value, expected_log.value.as_bytes()); - assert_eq!(log.sender, expected_log.sender.as_bytes()); + assert_eq!(log.key, expected_log.0.key.as_bytes()); + assert_eq!(log.value, expected_log.0.value.as_bytes()); + assert_eq!(log.sender, expected_log.0.sender.as_bytes()); } let logs = conn @@ -354,9 +356,9 @@ mod tests { assert_eq!(log.log_index_in_tx as usize, i); } for (log, expected_log) in logs.iter().zip(&second_logs) { - assert_eq!(log.key, expected_log.key.as_bytes()); - assert_eq!(log.value, expected_log.value.as_bytes()); - assert_eq!(log.sender, expected_log.sender.as_bytes()); + assert_eq!(log.key, expected_log.0.key.as_bytes()); + assert_eq!(log.value, expected_log.0.value.as_bytes()); + assert_eq!(log.sender, expected_log.0.sender.as_bytes()); } } } diff --git a/core/lib/dal/src/models/storage_block.rs b/core/lib/dal/src/models/storage_block.rs index 35a7873b5627..390bd3b2fd87 100644 --- a/core/lib/dal/src/models/storage_block.rs +++ b/core/lib/dal/src/models/storage_block.rs @@ -13,7 +13,7 @@ use zksync_types::{ api, block::{L1BatchHeader, MiniblockHeader}, commitment::{L1BatchMetaParameters, L1BatchMetadata}, - l2_to_l1_log::L2ToL1Log, + l2_to_l1_log::{L2ToL1Log, SystemL2ToL1Log, UserL2ToL1Log}, Address, L1BatchNumber, MiniblockNumber, H2048, H256, }; @@ -61,11 +61,8 @@ impl From for L1BatchHeader { .map(|raw_data| raw_data.into()) .collect(); - let system_logs: Vec<_> = l1_batch - .system_logs - .into_iter() - .map(|raw_log| L2ToL1Log::from_slice(&raw_log)) - .collect(); + let system_logs = convert_l2_to_l1_logs(l1_batch.system_logs); + let user_l2_to_l1_logs = convert_l2_to_l1_logs(l1_batch.l2_to_l1_logs); L1BatchHeader { number: L1BatchNumber(l1_batch.number as u32), @@ -75,7 +72,7 @@ impl From for L1BatchHeader { priority_ops_onchain_data, l1_tx_count: l1_batch.l1_tx_count as u16, l2_tx_count: l1_batch.l2_tx_count as u16, - l2_to_l1_logs: convert_l2_to_l1_logs(l1_batch.l2_to_l1_logs), + l2_to_l1_logs: user_l2_to_l1_logs.into_iter().map(UserL2ToL1Log).collect(), l2_to_l1_messages: l1_batch.l2_to_l1_messages, bloom: H2048::from_slice(&l1_batch.bloom), @@ -91,7 +88,7 @@ impl From for L1BatchHeader { ), l1_gas_price: l1_batch.l1_gas_price as u64, l2_fair_gas_price: l1_batch.l2_fair_gas_price as u64, - system_logs, + system_logs: system_logs.into_iter().map(SystemL2ToL1Log).collect(), protocol_version: l1_batch .protocol_version .map(|v| (v as u16).try_into().unwrap()), @@ -183,11 +180,8 @@ impl From for L1BatchHeader { .map(Vec::into) .collect(); - let system_logs: Vec<_> = l1_batch - .system_logs - .into_iter() - .map(|raw_log| L2ToL1Log::from_slice(&raw_log)) - .collect(); + let system_logs = convert_l2_to_l1_logs(l1_batch.system_logs); + let user_l2_to_l1_logs = convert_l2_to_l1_logs(l1_batch.l2_to_l1_logs); L1BatchHeader { number: L1BatchNumber(l1_batch.number as u32), @@ -197,7 +191,7 @@ impl From for L1BatchHeader { priority_ops_onchain_data, l1_tx_count: l1_batch.l1_tx_count as u16, l2_tx_count: l1_batch.l2_tx_count as u16, - l2_to_l1_logs: convert_l2_to_l1_logs(l1_batch.l2_to_l1_logs), + l2_to_l1_logs: user_l2_to_l1_logs.into_iter().map(UserL2ToL1Log).collect(), l2_to_l1_messages: l1_batch.l2_to_l1_messages, bloom: H2048::from_slice(&l1_batch.bloom), @@ -213,7 +207,7 @@ impl From for L1BatchHeader { ), l1_gas_price: l1_batch.l1_gas_price as u64, l2_fair_gas_price: l1_batch.l2_fair_gas_price as u64, - system_logs, + system_logs: system_logs.into_iter().map(SystemL2ToL1Log).collect(), protocol_version: l1_batch .protocol_version .map(|v| (v as u16).try_into().unwrap()), diff --git a/core/lib/multivm/src/glue/types/vm/current_execution_state.rs b/core/lib/multivm/src/glue/types/vm/current_execution_state.rs deleted file mode 100644 index b59bac9a3226..000000000000 --- a/core/lib/multivm/src/glue/types/vm/current_execution_state.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::glue::GlueFrom; -use vm_latest::CurrentExecutionState; - -impl GlueFrom for CurrentExecutionState { - fn glue_from(value: vm_virtual_blocks::CurrentExecutionState) -> Self { - Self { - events: value.events, - storage_log_queries: value.storage_log_queries, - used_contract_hashes: value.used_contract_hashes, - user_l2_to_l1_logs: value.l2_to_l1_logs, - deduplicated_events_logs: vec![], - system_logs: vec![], - total_log_queries: value.total_log_queries, - cycles_used: value.cycles_used, - } - } -} diff --git a/core/lib/multivm/src/glue/types/vm/vm_block_result.rs b/core/lib/multivm/src/glue/types/vm/vm_block_result.rs index 8fa2c03de238..cdbedfd4a75d 100644 --- a/core/lib/multivm/src/glue/types/vm/vm_block_result.rs +++ b/core/lib/multivm/src/glue/types/vm/vm_block_result.rs @@ -1,3 +1,5 @@ +use zksync_types::l2_to_l1_log::UserL2ToL1Log; + use crate::glue::{GlueFrom, GlueInto}; use crate::interface::{ types::outputs::VmExecutionLogs, CurrentExecutionState, ExecutionResult, Refunds, @@ -29,7 +31,12 @@ impl GlueFrom for crate::interface::FinishedL1B events: value.full_result.events, storage_log_queries: value.full_result.storage_log_queries, used_contract_hashes: value.full_result.used_contract_hashes, - user_l2_to_l1_logs: value.full_result.l2_to_l1_logs, + user_l2_to_l1_logs: value + .full_result + .l2_to_l1_logs + .into_iter() + .map(UserL2ToL1Log) + .collect(), system_logs: vec![], total_log_queries: value.full_result.total_log_queries, cycles_used: value.full_result.cycles_used, @@ -61,7 +68,12 @@ impl GlueFrom for crate::interface::FinishedL1B events: value.full_result.events, storage_log_queries: value.full_result.storage_log_queries, used_contract_hashes: value.full_result.used_contract_hashes, - user_l2_to_l1_logs: value.full_result.l2_to_l1_logs, + user_l2_to_l1_logs: value + .full_result + .l2_to_l1_logs + .into_iter() + .map(UserL2ToL1Log) + .collect(), system_logs: vec![], total_log_queries: value.full_result.total_log_queries, cycles_used: value.full_result.cycles_used, @@ -99,7 +111,12 @@ impl GlueFrom for crate::interface::Finished events: value.full_result.events, storage_log_queries: value.full_result.storage_log_queries, used_contract_hashes: value.full_result.used_contract_hashes, - user_l2_to_l1_logs: value.full_result.l2_to_l1_logs, + user_l2_to_l1_logs: value + .full_result + .l2_to_l1_logs + .into_iter() + .map(UserL2ToL1Log) + .collect(), system_logs: vec![], total_log_queries: value.full_result.total_log_queries, cycles_used: value.full_result.cycles_used, @@ -127,7 +144,12 @@ impl GlueFrom for crate::interface::VmExecut result, logs: VmExecutionLogs { events: value.full_result.events, - user_l2_to_l1_logs: value.full_result.l2_to_l1_logs, + user_l2_to_l1_logs: value + .full_result + .l2_to_l1_logs + .into_iter() + .map(UserL2ToL1Log) + .collect(), system_l2_to_l1_logs: vec![], storage_logs: value.full_result.storage_log_queries, total_log_queries_count: value.full_result.total_log_queries, @@ -189,7 +211,12 @@ impl GlueFrom for crate::interface::VmExecution result, logs: VmExecutionLogs { events: value.full_result.events, - user_l2_to_l1_logs: value.full_result.l2_to_l1_logs, + user_l2_to_l1_logs: value + .full_result + .l2_to_l1_logs + .into_iter() + .map(UserL2ToL1Log) + .collect(), system_l2_to_l1_logs: vec![], storage_logs: value.full_result.storage_log_queries, total_log_queries_count: value.full_result.total_log_queries, diff --git a/core/lib/multivm/src/glue/types/vm/vm_execution_result.rs b/core/lib/multivm/src/glue/types/vm/vm_execution_result.rs deleted file mode 100644 index a51b30a99800..000000000000 --- a/core/lib/multivm/src/glue/types/vm/vm_execution_result.rs +++ /dev/null @@ -1,58 +0,0 @@ -use crate::glue::{GlueFrom, GlueInto}; - -impl GlueFrom for vm_latest::CurrentExecutionState { - fn glue_from(value: vm_m5::vm::VmExecutionResult) -> Self { - Self { - events: value.events, - storage_log_queries: value.storage_log_queries, - used_contract_hashes: value.used_contract_hashes, - system_logs: vec![], - user_l2_to_l1_logs: value - .l2_to_l1_logs - .into_iter() - .map(GlueInto::glue_into) - .collect(), - total_log_queries: value.total_log_queries, - cycles_used: value.cycles_used, - deduplicated_events_logs: vec![], - } - } -} - -impl GlueFrom for vm_latest::CurrentExecutionState { - fn glue_from(value: vm_m6::vm::VmExecutionResult) -> Self { - Self { - events: value.events, - storage_log_queries: value.storage_log_queries, - used_contract_hashes: value.used_contract_hashes, - system_logs: vec![], - user_l2_to_l1_logs: value - .l2_to_l1_logs - .into_iter() - .map(GlueInto::glue_into) - .collect(), - total_log_queries: value.total_log_queries, - cycles_used: value.cycles_used, - deduplicated_events_logs: vec![], - } - } -} - -impl GlueFrom for vm_latest::CurrentExecutionState { - fn glue_from(value: vm_1_3_2::VmExecutionResult) -> Self { - Self { - events: value.events, - storage_log_queries: value.storage_log_queries, - used_contract_hashes: value.used_contract_hashes, - system_logs: vec![], - user_l2_to_l1_logs: value - .l2_to_l1_logs - .into_iter() - .map(GlueInto::glue_into) - .collect(), - total_log_queries: value.total_log_queries, - cycles_used: value.cycles_used, - deduplicated_events_logs: vec![], - } - } -} diff --git a/core/lib/multivm/src/glue/types/vm/vm_execution_result_and_logs.rs b/core/lib/multivm/src/glue/types/vm/vm_execution_result_and_logs.rs deleted file mode 100644 index 1bf9f3075b78..000000000000 --- a/core/lib/multivm/src/glue/types/vm/vm_execution_result_and_logs.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::glue::{GlueFrom, GlueInto}; -use vm_latest::{VmExecutionLogs, VmExecutionResultAndLogs}; - -impl GlueFrom for VmExecutionResultAndLogs { - fn glue_from(value: vm_virtual_blocks::VmExecutionResultAndLogs) -> Self { - Self { - result: value.result.glue_into(), - logs: VmExecutionLogs { - storage_logs: value.logs.storage_logs, - events: value.logs.events, - user_l2_to_l1_logs: value.logs.l2_to_l1_logs, - system_l2_to_l1_logs: vec![], - total_log_queries_count: value.logs.total_log_queries_count, - }, - statistics: value.statistics.glue_into(), - refunds: value.refunds.glue_into(), - } - } -} diff --git a/core/lib/multivm/src/interface/types/errors/bootloader_error.rs b/core/lib/multivm/src/interface/types/errors/bootloader_error.rs index b9fa3199e271..0f0e14408669 100644 --- a/core/lib/multivm/src/interface/types/errors/bootloader_error.rs +++ b/core/lib/multivm/src/interface/types/errors/bootloader_error.rs @@ -27,10 +27,10 @@ pub(crate) enum BootloaderErrorCode { MintEtherFailed, FailedToAppendTransactionToL2Block, FailedToSetL2Block, + FailedToPublishTimestampDataToL1, L1MessengerPublishingFailed, L1MessengerLogSendingFailed, FailedToCallSystemContext, - FailedToPublishTimestampDataToL1, Unknown, } @@ -63,10 +63,10 @@ impl From for BootloaderErrorCode { 23 => BootloaderErrorCode::MintEtherFailed, 24 => BootloaderErrorCode::FailedToAppendTransactionToL2Block, 25 => BootloaderErrorCode::FailedToSetL2Block, - 26 => BootloaderErrorCode::L1MessengerPublishingFailed, - 27 => BootloaderErrorCode::L1MessengerLogSendingFailed, - 28 => BootloaderErrorCode::FailedToCallSystemContext, - 29 => BootloaderErrorCode::FailedToPublishTimestampDataToL1, + 26 => BootloaderErrorCode::FailedToPublishTimestampDataToL1, + 27 => BootloaderErrorCode::L1MessengerPublishingFailed, + 28 => BootloaderErrorCode::L1MessengerLogSendingFailed, + 29 => BootloaderErrorCode::FailedToCallSystemContext, _ => BootloaderErrorCode::Unknown, } } diff --git a/core/lib/multivm/src/interface/types/outputs/execution_result.rs b/core/lib/multivm/src/interface/types/outputs/execution_result.rs index 7a3b135641f2..3181a94a9da6 100644 --- a/core/lib/multivm/src/interface/types/outputs/execution_result.rs +++ b/core/lib/multivm/src/interface/types/outputs/execution_result.rs @@ -1,7 +1,7 @@ use crate::interface::{Halt, VmExecutionStatistics, VmRevertReason}; use zksync_system_constants::PUBLISH_BYTECODE_OVERHEAD; use zksync_types::event::{extract_long_l2_to_l1_messages, extract_published_bytecodes}; -use zksync_types::l2_to_l1_log::L2ToL1Log; +use zksync_types::l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}; use zksync_types::tx::ExecutionMetrics; use zksync_types::{StorageLogQuery, Transaction, VmEvent}; use zksync_utils::bytecode::bytecode_len_in_bytes; @@ -18,8 +18,10 @@ pub struct Refunds { pub struct VmExecutionLogs { pub storage_logs: Vec, pub events: Vec, - pub user_l2_to_l1_logs: Vec, - pub system_l2_to_l1_logs: Vec, + // For pre-boojum VMs, there was no distinction between user logs and system + // logs and so all the outputted logs were treated as user_l2_to_l1_logs. + pub user_l2_to_l1_logs: Vec, + pub system_l2_to_l1_logs: Vec, // This field moved to statistics, but we need to keep it for backward compatibility pub total_log_queries_count: usize, } diff --git a/core/lib/multivm/src/interface/types/outputs/execution_state.rs b/core/lib/multivm/src/interface/types/outputs/execution_state.rs index 1408f5a08708..c76e63702326 100644 --- a/core/lib/multivm/src/interface/types/outputs/execution_state.rs +++ b/core/lib/multivm/src/interface/types/outputs/execution_state.rs @@ -1,4 +1,4 @@ -use zksync_types::l2_to_l1_log::L2ToL1Log; +use zksync_types::l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}; use zksync_types::{LogQuery, StorageLogQuery, VmEvent, U256}; /// State of the VM since the start of the batch execution. @@ -11,9 +11,11 @@ pub struct CurrentExecutionState { /// Hashes of the contracts used by the VM. pub used_contract_hashes: Vec, /// L2 to L1 logs produced by the VM. - pub system_logs: Vec, - /// L2 to L1 logs produced by the L1Messeger - pub user_l2_to_l1_logs: Vec, + pub system_logs: Vec, + /// L2 to L1 logs produced by the L1Messeger. + /// For pre-boojum VMs, there was no distinction between user logs and system + /// logs and so all the outputted logs were treated as user_l2_to_l1_logs. + pub user_l2_to_l1_logs: Vec, /// Number of log queries produced by the VM. Including l2_to_l1 logs, storage logs and events. pub total_log_queries: usize, /// Number of cycles used by the VM. diff --git a/core/lib/multivm/src/interface/types/outputs/mod.rs b/core/lib/multivm/src/interface/types/outputs/mod.rs index 97f11eba091a..39fed3ad9cb8 100644 --- a/core/lib/multivm/src/interface/types/outputs/mod.rs +++ b/core/lib/multivm/src/interface/types/outputs/mod.rs @@ -2,7 +2,6 @@ mod execution_result; mod execution_state; mod finished_l1batch; mod l2_block; -mod pubdata; mod statistic; pub use execution_result::VmExecutionLogs; @@ -10,5 +9,4 @@ pub use execution_result::{ExecutionResult, Refunds, VmExecutionResultAndLogs}; pub use execution_state::{BootloaderMemory, CurrentExecutionState}; pub use finished_l1batch::FinishedL1Batch; pub use l2_block::L2Block; -pub(crate) use pubdata::PubdataInput; pub use statistic::{VmExecutionStatistics, VmMemoryMetrics}; diff --git a/core/lib/multivm/src/interface/types/outputs/pubdata.rs b/core/lib/multivm/src/interface/types/outputs/pubdata.rs deleted file mode 100644 index fb293549f43c..000000000000 --- a/core/lib/multivm/src/interface/types/outputs/pubdata.rs +++ /dev/null @@ -1,73 +0,0 @@ -use zksync_types::ethabi; -use zksync_types::{ - event::L1MessengerL2ToL1Log, - writes::{compress_state_diffs, StateDiffRecord}, -}; - -/// Struct based on which the pubdata blob is formed -#[derive(Debug, Clone, Default)] -pub(crate) struct PubdataInput { - pub(crate) user_logs: Vec, - pub(crate) l2_to_l1_messages: Vec>, - pub(crate) published_bytecodes: Vec>, - pub(crate) state_diffs: Vec, -} - -impl PubdataInput { - pub(crate) fn build_pubdata(self) -> Vec { - let mut l1_messenger_pubdata = vec![]; - - let PubdataInput { - user_logs, - l2_to_l1_messages, - published_bytecodes, - state_diffs, - } = self; - - // Encoding user L2->L1 logs. - // Format: [(numberOfL2ToL1Logs as u32) || l2tol1logs[1] || ... || l2tol1logs[n]] - l1_messenger_pubdata.extend((user_logs.len() as u32).to_be_bytes()); - for l2tol1log in user_logs { - l1_messenger_pubdata.extend(l2tol1log.packed_encoding()); - } - - // Encoding L2->L1 messages - // Format: [(numberOfMessages as u32) || (messages[1].len() as u32) || messages[1] || ... || (messages[n].len() as u32) || messages[n]] - l1_messenger_pubdata.extend((l2_to_l1_messages.len() as u32).to_be_bytes()); - for message in l2_to_l1_messages { - l1_messenger_pubdata.extend((message.len() as u32).to_be_bytes()); - l1_messenger_pubdata.extend(message); - } - - // Encoding bytecodes - // Format: [(numberOfBytecodes as u32) || (bytecodes[1].len() as u32) || bytecodes[1] || ... || (bytecodes[n].len() as u32) || bytecodes[n]] - l1_messenger_pubdata.extend((published_bytecodes.len() as u32).to_be_bytes()); - for bytecode in published_bytecodes { - l1_messenger_pubdata.extend((bytecode.len() as u32).to_be_bytes()); - l1_messenger_pubdata.extend(bytecode); - } - - // Encoding state diffs - // Format: [size of compressed state diffs u32 || compressed state diffs || (# state diffs: intial + repeated) as u32 || sorted state diffs by ] - let state_diffs_compressed = compress_state_diffs(state_diffs.clone()); - l1_messenger_pubdata.extend(state_diffs_compressed); - l1_messenger_pubdata.extend((state_diffs.len() as u32).to_be_bytes()); - - for state_diff in state_diffs { - l1_messenger_pubdata.extend(state_diff.encode_padded()); - } - - // ABI-encoding the final pubdata - let l1_messenger_abi_encoded_pubdata = - ethabi::encode(&[ethabi::Token::Bytes(l1_messenger_pubdata)]); - - assert!( - l1_messenger_abi_encoded_pubdata.len() % 32 == 0, - "abi encoded bytes array length should be divisible by 32" - ); - - // Need to skip first word as it represents array offset - // while bootloader expects only [len || data] - l1_messenger_abi_encoded_pubdata[32..].to_vec() - } -} diff --git a/core/lib/multivm/src/versions/vm_1_3_2/legacy_types.rs b/core/lib/multivm/src/versions/vm_1_3_2/legacy_types.rs deleted file mode 100644 index 6b9ba5ac88f6..000000000000 --- a/core/lib/multivm/src/versions/vm_1_3_2/legacy_types.rs +++ /dev/null @@ -1,15 +0,0 @@ -use zksync_types::{l2_to_l1_log::L2ToL1Log, StorageLogQuery, VmEvent}; - -/// -/// Here we insert of the types that used to be present in lib/types at the time when this VM was in use. -/// - -/// Events/storage logs/l2->l1 logs created within transaction execution. -#[derive(Debug, Clone, Default, PartialEq)] -pub struct VmExecutionLogs { - pub storage_logs: Vec, - pub events: Vec, - pub l2_to_l1_logs: Vec, - // This field moved to statistics, but we need to keep it for backward compatibility - pub total_log_queries_count: usize, -} diff --git a/core/lib/multivm/src/versions/vm_1_3_2/mod.rs b/core/lib/multivm/src/versions/vm_1_3_2/mod.rs index a5669dac1875..4c46b3554a76 100644 --- a/core/lib/multivm/src/versions/vm_1_3_2/mod.rs +++ b/core/lib/multivm/src/versions/vm_1_3_2/mod.rs @@ -5,7 +5,6 @@ pub mod errors; pub mod event_sink; mod events; mod history_recorder; -pub mod legacy_types; pub mod memory; mod oracle_tools; pub mod oracles; diff --git a/core/lib/multivm/src/versions/vm_1_3_2/vm.rs b/core/lib/multivm/src/versions/vm_1_3_2/vm.rs index c3eb8d68e4a7..4646081f18ed 100644 --- a/core/lib/multivm/src/versions/vm_1_3_2/vm.rs +++ b/core/lib/multivm/src/versions/vm_1_3_2/vm.rs @@ -10,7 +10,7 @@ use zk_evm_1_3_3::zkevm_opcode_defs::decoding::{ use zk_evm_1_3_3::zkevm_opcode_defs::definitions::RET_IMPLICIT_RETURNDATA_PARAMS_REGISTER; use zksync_state::WriteStorage; use zksync_system_constants::MAX_TXS_IN_BLOCK; -use zksync_types::l2_to_l1_log::L2ToL1Log; +use zksync_types::l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log}; use zksync_types::tx::tx_execution_info::TxExecutionStatus; use zksync_types::vm_trace::{Call, VmExecutionTrace, VmTrace}; use zksync_types::{L1BatchNumber, StorageLogQuery, VmEvent, U256}; @@ -428,7 +428,7 @@ impl VmInstance { VmExecutionLogs { storage_logs, events, - user_l2_to_l1_logs: l2_to_l1_logs, + user_l2_to_l1_logs: l2_to_l1_logs.into_iter().map(UserL2ToL1Log).collect(), total_log_queries_count: storage_logs_count + log_queries.len() + precompile_calls_count, diff --git a/core/lib/multivm/src/versions/vm_latest/bootloader_state/snapshot.rs b/core/lib/multivm/src/versions/vm_latest/bootloader_state/snapshot.rs index 08267d0dfcc4..683fc28a69e9 100644 --- a/core/lib/multivm/src/versions/vm_latest/bootloader_state/snapshot.rs +++ b/core/lib/multivm/src/versions/vm_latest/bootloader_state/snapshot.rs @@ -13,7 +13,7 @@ pub(crate) struct BootloaderStateSnapshot { /// Current offset of the free space in the bootloader memory. pub(crate) free_tx_offset: usize, /// Whether the pubdata information has been provided already - pub(crate) pubdata_information: bool, + pub(crate) is_pubdata_information_provided: bool, } #[derive(Debug, Clone)] diff --git a/core/lib/multivm/src/versions/vm_latest/bootloader_state/state.rs b/core/lib/multivm/src/versions/vm_latest/bootloader_state/state.rs index 327aaf5cb121..b4641d9bc649 100644 --- a/core/lib/multivm/src/versions/vm_latest/bootloader_state/state.rs +++ b/core/lib/multivm/src/versions/vm_latest/bootloader_state/state.rs @@ -6,8 +6,8 @@ use std::cmp::Ordering; use zksync_types::{L2ChainId, U256}; use zksync_utils::bytecode::CompressedBytecodeInfo; -use crate::interface::types::outputs::PubdataInput; use crate::interface::{BootloaderMemory, L2BlockEnv, TxExecutionMode}; +use crate::vm_latest::types::internals::pubdata::PubdataInput; use crate::vm_latest::{ constants::TX_DESCRIPTION_OFFSET, types::internals::TransactionData, utils::l2_blocks::assert_next_block, @@ -255,7 +255,7 @@ impl BootloaderState { last_l2_block: self.last_l2_block().make_snapshot(), compressed_bytecodes_encoding: self.compressed_bytecodes_encoding, free_tx_offset: self.free_tx_offset, - pubdata_information: self.pubdata_information.get().is_some(), + is_pubdata_information_provided: self.pubdata_information.get().is_some(), } } @@ -271,12 +271,15 @@ impl BootloaderState { self.last_mut_l2_block() .apply_snapshot(snapshot.last_l2_block); - if !snapshot.pubdata_information { + if !snapshot.is_pubdata_information_provided { self.pubdata_information = Default::default(); } else { + // Under the correct usage of the snapshots of the bootloader state, + // this assertion should never fail, i.e. since the pubdata information + // can be set only once. However, we have this assertion just in case. assert!( self.pubdata_information.get().is_some(), - "Can not use snapshot from future" + "Snapshot with no pubdata can not rollback to snapshot with one" ); } } diff --git a/core/lib/multivm/src/versions/vm_latest/bootloader_state/utils.rs b/core/lib/multivm/src/versions/vm_latest/bootloader_state/utils.rs index 252ebabb1080..78b98f0a4046 100644 --- a/core/lib/multivm/src/versions/vm_latest/bootloader_state/utils.rs +++ b/core/lib/multivm/src/versions/vm_latest/bootloader_state/utils.rs @@ -2,15 +2,15 @@ use zksync_types::U256; use zksync_utils::bytecode::CompressedBytecodeInfo; use zksync_utils::{bytes_to_be_words, h256_to_u256}; -use crate::interface::types::outputs::PubdataInput; use crate::interface::{BootloaderMemory, TxExecutionMode}; use crate::vm_latest::bootloader_state::l2_block::BootloaderL2Block; use crate::vm_latest::constants::{ BOOTLOADER_TX_DESCRIPTION_OFFSET, BOOTLOADER_TX_DESCRIPTION_SIZE, COMPRESSED_BYTECODES_OFFSET, - OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET, OPERATOR_REFUNDS_OFFSET, TX_DESCRIPTION_OFFSET, - TX_OPERATOR_L2_BLOCK_INFO_OFFSET, TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO, TX_OVERHEAD_OFFSET, - TX_TRUSTED_GAS_LIMIT_OFFSET, + OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET, OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS, + OPERATOR_REFUNDS_OFFSET, TX_DESCRIPTION_OFFSET, TX_OPERATOR_L2_BLOCK_INFO_OFFSET, + TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO, TX_OVERHEAD_OFFSET, TX_TRUSTED_GAS_LIMIT_OFFSET, }; +use crate::vm_latest::types::internals::pubdata::PubdataInput; use super::tx::BootloaderTx; @@ -116,10 +116,19 @@ pub(crate) fn apply_pubdata_to_memory( memory: &mut BootloaderMemory, pubdata_information: PubdataInput, ) { + // Skipping two slots as they will be filled by the bootloader itself: + // - One slot is for the selector of the call to the L1Messenger. + // - The other slot is for the 0x20 offset for the calldata. let l1_messenger_pubdata_start_slot = OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + 2; - pubdata_information - .build_pubdata() + let pubdata = pubdata_information.build_pubdata(); + + assert!( + pubdata.len() / 32 <= OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS - 2, + "The encoded pubdata is too big" + ); + + pubdata .chunks(32) .enumerate() .for_each(|(slot_offset, value)| { diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs index 8db69c6c4b8b..e14103b80745 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs @@ -2,7 +2,6 @@ use zk_evm_1_4_0::aux_structures::Timestamp; use zksync_state::WriteStorage; use crate::interface::{VmExecutionMode, VmExecutionResultAndLogs}; -use crate::versions::vm_latest::tracers::traits::BoxedTracer; use crate::vm_latest::old_vm::{ history_recorder::HistoryMode, utils::{vm_may_have_ended_inner, VmExecutionResult}, @@ -17,7 +16,7 @@ use crate::vm_latest::VmExecutionStopReason; impl Vm { pub(crate) fn inspect_inner( &mut self, - mut tracers: Vec>>, + tracers: Vec>>, execution_mode: VmExecutionMode, ) -> VmExecutionResultAndLogs { let mut enable_refund_tracer = false; @@ -26,7 +25,6 @@ impl Vm { self.bootloader_state.move_tx_to_execute_pointer(); enable_refund_tracer = true; } - tracers.push(PubdataTracer::new(self.batch_env.clone(), execution_mode).into_boxed()); let (_, result) = self.inspect_and_collect_results(tracers, execution_mode, enable_refund_tracer); @@ -49,6 +47,7 @@ impl Vm { tracers, self.storage.clone(), refund_tracers, + Some(PubdataTracer::new(self.batch_env.clone(), execution_mode)), ); let timestamp_initial = Timestamp(self.state.local_state.timestamp); diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/logs.rs b/core/lib/multivm/src/versions/vm_latest/implementation/logs.rs index 66c46351700c..d65a002a3dfe 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/logs.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/logs.rs @@ -2,7 +2,7 @@ use zk_evm_1_4_0::aux_structures::Timestamp; use zksync_state::WriteStorage; use zksync_types::event::extract_l2tol1logs_from_l1_messenger; -use zksync_types::l2_to_l1_log::L2ToL1Log; +use zksync_types::l2_to_l1_log::{L2ToL1Log, SystemL2ToL1Log, UserL2ToL1Log}; use zksync_types::VmEvent; use crate::interface::types::outputs::VmExecutionLogs; @@ -26,7 +26,7 @@ impl Vm { let storage_logs_count = storage_logs.len(); let (events, system_l2_to_l1_logs) = - self.collect_events_and_l1_logs_after_timestamp(from_timestamp); + self.collect_events_and_l1_system_logs_after_timestamp(from_timestamp); let log_queries = self .state @@ -46,17 +46,23 @@ impl Vm { VmExecutionLogs { storage_logs, events, - user_l2_to_l1_logs: user_logs.into_iter().map(|log| log.into()).collect(), - system_l2_to_l1_logs, + user_l2_to_l1_logs: user_logs + .into_iter() + .map(|log| UserL2ToL1Log(log.into())) + .collect(), + system_l2_to_l1_logs: system_l2_to_l1_logs + .into_iter() + .map(SystemL2ToL1Log) + .collect(), total_log_queries_count, } } - pub(crate) fn collect_events_and_l1_logs_after_timestamp( + pub(crate) fn collect_events_and_l1_system_logs_after_timestamp( &self, from_timestamp: Timestamp, ) -> (Vec, Vec) { - logs::collect_events_and_l1_logs_after_timestamp( + logs::collect_events_and_l1_system_logs_after_timestamp( &self.state, &self.batch_env, from_timestamp, diff --git a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs index d3755fa6acd2..c4d7a16070e3 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs @@ -1,5 +1,5 @@ use zksync_system_constants::BOOTLOADER_ADDRESS; -use zksync_types::l2_to_l1_log::L2ToL1Log; +use zksync_types::l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log}; use zksync_types::storage_writes_deduplicator::StorageWritesDeduplicator; use zksync_types::{get_code_key, get_known_code_key, U256}; use zksync_utils::u256_to_h256; @@ -42,14 +42,17 @@ fn test_l1_tx_execution() { let deploy_tx = account.get_deploy_tx(&contract_code, None, TxType::L1 { serial_id: 1 }); let tx_data: TransactionData = deploy_tx.tx.clone().into(); - let required_l2_to_l1_logs = vec![L2ToL1Log { + let required_l2_to_l1_logs: Vec<_> = vec![L2ToL1Log { shard_id: 0, is_service: true, tx_number_in_block: 0, sender: BOOTLOADER_ADDRESS, key: tx_data.tx_hash(0.into()), value: u256_to_h256(U256::from(1u32)), - }]; + }] + .into_iter() + .map(UserL2ToL1Log) + .collect(); vm.vm.push_transaction(deploy_tx.tx.clone()); diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs index 3b6d0ac2e251..32155b7d1b47 100644 --- a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs @@ -28,6 +28,8 @@ use crate::vm_latest::tracers::{RefundsTracer, ResultTracer}; use crate::vm_latest::types::internals::ZkSyncVmState; use crate::vm_latest::VmExecutionStopReason; +use super::PubdataTracer; + /// Default tracer for the VM. It manages the other tracers execution and stop the vm when needed. pub(crate) struct DefaultExecutionTracer { tx_has_been_processed: bool, @@ -45,6 +47,10 @@ pub(crate) struct DefaultExecutionTracer { // ensures static dispatch, enhancing performance by avoiding dynamic dispatch overhead. // Additionally, being an internal tracer, it saves the results directly to VmResultAndLogs. pub(crate) refund_tracer: Option, + // The pubdata tracer is responsible for inserting the pubdata packing information into the bootloader + // memory at the end of the batch. Its separation from the custom tracer + // ensures static dispatch, enhancing performance by avoiding dynamic dispatch overhead. + pub(crate) pubdata_tracer: Option, pub(crate) custom_tracers: Vec>>, ret_from_the_bootloader: Option, storage: StoragePtr, @@ -86,7 +92,9 @@ impl Tracer for DefaultExecutionTracer { if let Some(refund_tracer) = &mut self.refund_tracer { >::after_decoding(refund_tracer, state, data, memory); } - + if let Some(pubdata_tracer) = &mut self.pubdata_tracer { + >::after_decoding(pubdata_tracer, state, data, memory); + } for tracer in self.custom_tracers.iter_mut() { tracer.after_decoding(state, data, memory) } @@ -123,6 +131,9 @@ impl Tracer for DefaultExecutionTracer { if let Some(refund_tracer) = &mut self.refund_tracer { refund_tracer.before_execution(state, data, memory, self.storage.clone()); } + if let Some(pubdata_tracer) = &mut self.pubdata_tracer { + pubdata_tracer.before_execution(state, data, memory, self.storage.clone()); + } for tracer in self.custom_tracers.iter_mut() { tracer.before_execution(state, data, memory, self.storage.clone()); } @@ -153,6 +164,9 @@ impl Tracer for DefaultExecutionTracer { if let Some(refund_tracer) = &mut self.refund_tracer { refund_tracer.after_execution(state, data, memory, self.storage.clone()) } + if let Some(pubdata_tracer) = &mut self.pubdata_tracer { + pubdata_tracer.after_execution(state, data, memory, self.storage.clone()) + } for tracer in self.custom_tracers.iter_mut() { tracer.after_execution(state, data, memory, self.storage.clone()); } @@ -166,6 +180,7 @@ impl DefaultExecutionTracer { custom_tracers: Vec>>, storage: StoragePtr, refund_tracer: Option, + pubdata_tracer: Option, ) -> Self { Self { tx_has_been_processed: false, @@ -177,6 +192,7 @@ impl DefaultExecutionTracer { final_batch_info_requested: false, result_tracer: ResultTracer::new(execution_mode), refund_tracer, + pubdata_tracer, custom_tracers, ret_from_the_bootloader: None, storage, @@ -238,6 +254,9 @@ impl VmTracer for DefaultExecutionTracer< if let Some(refund_tracer) = &mut self.refund_tracer { refund_tracer.initialize_tracer(state); } + if let Some(pubdata_tracer) = &mut self.pubdata_tracer { + pubdata_tracer.initialize_tracer(state); + } for processor in self.custom_tracers.iter_mut() { processor.initialize_tracer(state); } @@ -258,6 +277,11 @@ impl VmTracer for DefaultExecutionTracer< .finish_cycle(state, bootloader_state) .stricter(&result); } + if let Some(pubdata_tracer) = &mut self.pubdata_tracer { + result = pubdata_tracer + .finish_cycle(state, bootloader_state) + .stricter(&result); + } for processor in self.custom_tracers.iter_mut() { result = processor .finish_cycle(state, bootloader_state) @@ -278,6 +302,9 @@ impl VmTracer for DefaultExecutionTracer< if let Some(refund_tracer) = &mut self.refund_tracer { refund_tracer.after_vm_execution(state, bootloader_state, stop_reason.clone()); } + if let Some(pubdata_tracer) = &mut self.pubdata_tracer { + pubdata_tracer.after_vm_execution(state, bootloader_state, stop_reason.clone()); + } for processor in self.custom_tracers.iter_mut() { processor.after_vm_execution(state, bootloader_state, stop_reason.clone()); } diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/pubdata_tracer.rs b/core/lib/multivm/src/versions/vm_latest/tracers/pubdata_tracer.rs index fd50a66aa4a5..b43c96cb9124 100644 --- a/core/lib/multivm/src/versions/vm_latest/tracers/pubdata_tracer.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/pubdata_tracer.rs @@ -16,8 +16,14 @@ use zksync_types::{ use zksync_utils::u256_to_h256; use zksync_utils::{h256_to_u256, u256_to_bytes_be}; -use crate::vm_latest::old_vm::{history_recorder::HistoryMode, memory::SimpleMemory}; -use crate::vm_latest::{constants::BOOTLOADER_HEAP_PAGE, TracerExecutionStatus}; +use crate::vm_latest::{ + old_vm::{history_recorder::HistoryMode, memory::SimpleMemory}, + types::internals::pubdata::PubdataInput, +}; +use crate::{ + vm_latest::StorageOracle, + vm_latest::{constants::BOOTLOADER_HEAP_PAGE, TracerExecutionStatus}, +}; use crate::interface::types::inputs::L1BatchEnv; use crate::vm_latest::tracers::{ @@ -25,9 +31,8 @@ use crate::vm_latest::tracers::{ utils::VmHook, }; use crate::vm_latest::types::internals::ZkSyncVmState; -use crate::vm_latest::utils::logs::collect_events_and_l1_logs_after_timestamp; +use crate::vm_latest::utils::logs::collect_events_and_l1_system_logs_after_timestamp; use crate::{ - interface::types::outputs::PubdataInput, interface::VmExecutionMode, vm_latest::bootloader_state::{utils::apply_pubdata_to_memory, BootloaderState}, }; @@ -57,8 +62,11 @@ impl PubdataTracer { &self, state: &ZkSyncVmState, ) -> Vec { - let (all_generated_events, _) = - collect_events_and_l1_logs_after_timestamp(state, &self.l1_batch_env, Timestamp(0)); + let (all_generated_events, _) = collect_events_and_l1_system_logs_after_timestamp( + state, + &self.l1_batch_env, + Timestamp(0), + ); extract_l2tol1logs_from_l1_messenger(&all_generated_events) } @@ -68,8 +76,11 @@ impl PubdataTracer { &self, state: &ZkSyncVmState, ) -> Vec> { - let (all_generated_events, _) = - collect_events_and_l1_logs_after_timestamp(state, &self.l1_batch_env, Timestamp(0)); + let (all_generated_events, _) = collect_events_and_l1_system_logs_after_timestamp( + state, + &self.l1_batch_env, + Timestamp(0), + ); extract_long_l2_to_l1_messages(&all_generated_events) } @@ -80,8 +91,11 @@ impl PubdataTracer { &self, state: &ZkSyncVmState, ) -> Vec> { - let (all_generated_events, _) = - collect_events_and_l1_logs_after_timestamp(state, &self.l1_batch_env, Timestamp(0)); + let (all_generated_events, _) = collect_events_and_l1_system_logs_after_timestamp( + state, + &self.l1_batch_env, + Timestamp(0), + ); let bytecode_publication_requests = extract_bytecode_publication_requests_from_l1_messenger(&all_generated_events); @@ -105,11 +119,10 @@ impl PubdataTracer { // Packs part of L1Messenger total pubdata that corresponds to // State diffs needed to be published on L1 fn get_state_diffs( - state: &ZkSyncVmState, + storage: &StorageOracle, ) -> Vec { sort_storage_access_queries( - state - .storage + storage .storage_log_queries_after_timestamp(Timestamp(0)) .iter() .map(|log| &log.log_query), @@ -123,8 +136,7 @@ impl PubdataTracer { address: log.address, key: log.key, derived_key: log.derive_final_address(), - enumeration_index: state - .storage + enumeration_index: storage .storage .get_ptr() .borrow_mut() @@ -147,7 +159,7 @@ impl PubdataTracer { user_logs: self.get_total_user_logs(state), l2_to_l1_messages: self.get_total_l1_messenger_messages(state), published_bytecodes: self.get_total_published_bytecodes(state), - state_diffs: Self::get_state_diffs(state), + state_diffs: Self::get_state_diffs(&state.storage), } } } @@ -183,7 +195,6 @@ impl VmTracer for PubdataTracer { } if self.pubdata_info_requested { - // Whenever we are executing the block tip, we want to avoid publishing the full pubdata let pubdata_input = self.build_pubdata_input(state); // Save the pubdata for the future initial bootloader memory building diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/mod.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/mod.rs index 601b7b8bd014..c189de7266d4 100644 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/mod.rs +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/mod.rs @@ -1,6 +1,7 @@ pub(crate) use snapshot::VmSnapshot; pub(crate) use transaction_data::TransactionData; pub(crate) use vm_state::new_vm_state; +pub(crate) mod pubdata; pub use vm_state::ZkSyncVmState; mod snapshot; mod transaction_data; diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/pubdata.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/pubdata.rs new file mode 100644 index 000000000000..e246bceeac54 --- /dev/null +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/pubdata.rs @@ -0,0 +1,133 @@ +use zksync_types::ethabi; +use zksync_types::{ + event::L1MessengerL2ToL1Log, + writes::{compress_state_diffs, StateDiffRecord}, +}; + +/// Struct based on which the pubdata blob is formed +#[derive(Debug, Clone, Default)] +pub(crate) struct PubdataInput { + pub(crate) user_logs: Vec, + pub(crate) l2_to_l1_messages: Vec>, + pub(crate) published_bytecodes: Vec>, + pub(crate) state_diffs: Vec, +} + +impl PubdataInput { + pub(crate) fn build_pubdata(self) -> Vec { + let mut l1_messenger_pubdata = vec![]; + + let PubdataInput { + user_logs, + l2_to_l1_messages, + published_bytecodes, + state_diffs, + } = self; + + // Encoding user L2->L1 logs. + // Format: [(numberOfL2ToL1Logs as u32) || l2tol1logs[1] || ... || l2tol1logs[n]] + l1_messenger_pubdata.extend((user_logs.len() as u32).to_be_bytes()); + for l2tol1log in user_logs { + l1_messenger_pubdata.extend(l2tol1log.packed_encoding()); + } + + // Encoding L2->L1 messages + // Format: [(numberOfMessages as u32) || (messages[1].len() as u32) || messages[1] || ... || (messages[n].len() as u32) || messages[n]] + l1_messenger_pubdata.extend((l2_to_l1_messages.len() as u32).to_be_bytes()); + for message in l2_to_l1_messages { + l1_messenger_pubdata.extend((message.len() as u32).to_be_bytes()); + l1_messenger_pubdata.extend(message); + } + + // Encoding bytecodes + // Format: [(numberOfBytecodes as u32) || (bytecodes[1].len() as u32) || bytecodes[1] || ... || (bytecodes[n].len() as u32) || bytecodes[n]] + l1_messenger_pubdata.extend((published_bytecodes.len() as u32).to_be_bytes()); + for bytecode in published_bytecodes { + l1_messenger_pubdata.extend((bytecode.len() as u32).to_be_bytes()); + l1_messenger_pubdata.extend(bytecode); + } + + // Encoding state diffs + // Format: [size of compressed state diffs u32 || compressed state diffs || (# state diffs: intial + repeated) as u32 || sorted state diffs by ] + let state_diffs_compressed = compress_state_diffs(state_diffs.clone()); + l1_messenger_pubdata.extend(state_diffs_compressed); + l1_messenger_pubdata.extend((state_diffs.len() as u32).to_be_bytes()); + + for state_diff in state_diffs { + l1_messenger_pubdata.extend(state_diff.encode_padded()); + } + + // ABI-encoding the final pubdata + let l1_messenger_abi_encoded_pubdata = + ethabi::encode(&[ethabi::Token::Bytes(l1_messenger_pubdata)]); + + assert!( + l1_messenger_abi_encoded_pubdata.len() % 32 == 0, + "abi encoded bytes array length should be divisible by 32" + ); + + // Need to skip first word as it represents array offset + // while bootloader expects only [len || data] + l1_messenger_abi_encoded_pubdata[32..].to_vec() + } +} + +#[cfg(test)] +mod tests { + use zksync_system_constants::{ACCOUNT_CODE_STORAGE_ADDRESS, BOOTLOADER_ADDRESS}; + use zksync_utils::u256_to_h256; + + use super::*; + + #[test] + fn test_basic_pubdata_building() { + // Just using some constant addresses for tests + let addr1 = BOOTLOADER_ADDRESS; + let addr2 = ACCOUNT_CODE_STORAGE_ADDRESS; + + let user_logs = vec![L1MessengerL2ToL1Log { + l2_shard_id: 0, + is_service: false, + tx_number_in_block: 0, + sender: addr1, + key: 1.into(), + value: 128.into(), + }]; + + let l2_to_l1_messages = vec![hex::decode("deadbeef").unwrap()]; + + let published_bytecodes = vec![hex::decode("aaaabbbb").unwrap()]; + + // For covering more cases, we have two state diffs: + // One with enumeration index present (and so it is a repeated write) and the one without it. + let state_diffs = vec![ + StateDiffRecord { + address: addr2, + key: 155.into(), + derived_key: u256_to_h256(125.into()).0, + enumeration_index: 12, + initial_value: 11.into(), + final_value: 12.into(), + }, + StateDiffRecord { + address: addr2, + key: 156.into(), + derived_key: u256_to_h256(126.into()).0, + enumeration_index: 0, + initial_value: 0.into(), + final_value: 14.into(), + }, + ]; + + let input = PubdataInput { + user_logs, + l2_to_l1_messages, + published_bytecodes, + state_diffs, + }; + + let pubdata = input.build_pubdata(); + + assert_eq!(hex::encode(pubdata), "00000000000000000000000000000000000000000000000000000000000002c700000001000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000100000004deadbeef0000000100000004aaaabbbb0100002a040001000000000000000000000000000000000000000000000000000000000000007e090e0000000c0901000000020000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000007d000000000000000c000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + } +} diff --git a/core/lib/multivm/src/versions/vm_latest/utils/logs.rs b/core/lib/multivm/src/versions/vm_latest/utils/logs.rs index 9f0985447332..a2b7f548684f 100644 --- a/core/lib/multivm/src/versions/vm_latest/utils/logs.rs +++ b/core/lib/multivm/src/versions/vm_latest/utils/logs.rs @@ -6,7 +6,7 @@ use crate::{ vm_latest::old_vm::history_recorder::HistoryMode, vm_latest::types::internals::ZkSyncVmState, }; -pub(crate) fn collect_events_and_l1_logs_after_timestamp( +pub(crate) fn collect_events_and_l1_system_logs_after_timestamp( vm_state: &ZkSyncVmState, batch_env: &L1BatchEnv, from_timestamp: Timestamp, diff --git a/core/lib/multivm/src/versions/vm_latest/vm.rs b/core/lib/multivm/src/versions/vm_latest/vm.rs index 9871b6303b2f..437815a8f829 100644 --- a/core/lib/multivm/src/versions/vm_latest/vm.rs +++ b/core/lib/multivm/src/versions/vm_latest/vm.rs @@ -1,4 +1,5 @@ use zksync_state::{StoragePtr, WriteStorage}; +use zksync_types::l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}; use zksync_types::{event::extract_l2tol1logs_from_l1_messenger, Transaction}; use zksync_utils::bytecode::CompressedBytecodeInfo; @@ -89,7 +90,10 @@ impl Vm { .collect(); let user_l2_to_l1_logs = extract_l2tol1logs_from_l1_messenger(&events); - let system_logs = l1_messages.into_iter().map(|log| log.into()).collect(); + let system_logs = l1_messages + .into_iter() + .map(|log| SystemL2ToL1Log(log.into())) + .collect(); let total_log_queries = self.state.event_sink.get_log_queries() + self .state @@ -104,7 +108,7 @@ impl Vm { used_contract_hashes: self.get_used_contracts(), user_l2_to_l1_logs: user_l2_to_l1_logs .into_iter() - .map(|log| log.into()) + .map(|log| UserL2ToL1Log(log.into())) .collect(), system_logs, total_log_queries, diff --git a/core/lib/multivm/src/versions/vm_m5/legacy_types.rs b/core/lib/multivm/src/versions/vm_m5/legacy_types.rs deleted file mode 100644 index 6b9ba5ac88f6..000000000000 --- a/core/lib/multivm/src/versions/vm_m5/legacy_types.rs +++ /dev/null @@ -1,15 +0,0 @@ -use zksync_types::{l2_to_l1_log::L2ToL1Log, StorageLogQuery, VmEvent}; - -/// -/// Here we insert of the types that used to be present in lib/types at the time when this VM was in use. -/// - -/// Events/storage logs/l2->l1 logs created within transaction execution. -#[derive(Debug, Clone, Default, PartialEq)] -pub struct VmExecutionLogs { - pub storage_logs: Vec, - pub events: Vec, - pub l2_to_l1_logs: Vec, - // This field moved to statistics, but we need to keep it for backward compatibility - pub total_log_queries_count: usize, -} diff --git a/core/lib/multivm/src/versions/vm_m5/mod.rs b/core/lib/multivm/src/versions/vm_m5/mod.rs index 6c57b0e26cb5..c501398ea1df 100644 --- a/core/lib/multivm/src/versions/vm_m5/mod.rs +++ b/core/lib/multivm/src/versions/vm_m5/mod.rs @@ -6,7 +6,6 @@ pub mod event_sink; mod events; pub(crate) mod glue; mod history_recorder; -pub mod legacy_types; pub mod memory; mod oracle_tools; pub mod oracles; diff --git a/core/lib/multivm/src/versions/vm_m5/vm.rs b/core/lib/multivm/src/versions/vm_m5/vm.rs index 9b64a5a8e3df..f7b1ed31de6d 100644 --- a/core/lib/multivm/src/versions/vm_m5/vm.rs +++ b/core/lib/multivm/src/versions/vm_m5/vm.rs @@ -10,7 +10,7 @@ use zk_evm_1_3_1::zkevm_opcode_defs::decoding::{ use zk_evm_1_3_1::zkevm_opcode_defs::definitions::RET_IMPLICIT_RETURNDATA_PARAMS_REGISTER; use zksync_system_constants::MAX_TXS_IN_BLOCK; -use zksync_types::l2_to_l1_log::L2ToL1Log; +use zksync_types::l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log}; use zksync_types::tx::tx_execution_info::TxExecutionStatus; use zksync_types::vm_trace::VmExecutionTrace; use zksync_types::{L1BatchNumber, StorageLogQuery, VmEvent, U256}; @@ -500,7 +500,7 @@ impl VmInstance { VmExecutionLogs { storage_logs, events, - user_l2_to_l1_logs: l2_to_l1_logs, + user_l2_to_l1_logs: l2_to_l1_logs.into_iter().map(UserL2ToL1Log).collect(), system_l2_to_l1_logs: vec![], total_log_queries_count: storage_logs_count + log_queries.len() diff --git a/core/lib/multivm/src/versions/vm_m6/legacy_types.rs b/core/lib/multivm/src/versions/vm_m6/legacy_types.rs deleted file mode 100644 index 6b9ba5ac88f6..000000000000 --- a/core/lib/multivm/src/versions/vm_m6/legacy_types.rs +++ /dev/null @@ -1,15 +0,0 @@ -use zksync_types::{l2_to_l1_log::L2ToL1Log, StorageLogQuery, VmEvent}; - -/// -/// Here we insert of the types that used to be present in lib/types at the time when this VM was in use. -/// - -/// Events/storage logs/l2->l1 logs created within transaction execution. -#[derive(Debug, Clone, Default, PartialEq)] -pub struct VmExecutionLogs { - pub storage_logs: Vec, - pub events: Vec, - pub l2_to_l1_logs: Vec, - // This field moved to statistics, but we need to keep it for backward compatibility - pub total_log_queries_count: usize, -} diff --git a/core/lib/multivm/src/versions/vm_m6/mod.rs b/core/lib/multivm/src/versions/vm_m6/mod.rs index a33002d6fe93..b8a6f6f051d5 100644 --- a/core/lib/multivm/src/versions/vm_m6/mod.rs +++ b/core/lib/multivm/src/versions/vm_m6/mod.rs @@ -6,7 +6,6 @@ pub mod event_sink; mod events; pub(crate) mod glue; mod history_recorder; -pub mod legacy_types; pub mod memory; mod oracle_tools; pub mod oracles; diff --git a/core/lib/multivm/src/versions/vm_m6/vm.rs b/core/lib/multivm/src/versions/vm_m6/vm.rs index 7f3a7fbc0247..7b68ce16b598 100644 --- a/core/lib/multivm/src/versions/vm_m6/vm.rs +++ b/core/lib/multivm/src/versions/vm_m6/vm.rs @@ -9,7 +9,7 @@ use zk_evm_1_3_1::zkevm_opcode_defs::decoding::{ }; use zk_evm_1_3_1::zkevm_opcode_defs::definitions::RET_IMPLICIT_RETURNDATA_PARAMS_REGISTER; use zksync_system_constants::MAX_TXS_IN_BLOCK; -use zksync_types::l2_to_l1_log::L2ToL1Log; +use zksync_types::l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log}; use zksync_types::tx::tx_execution_info::TxExecutionStatus; use zksync_types::vm_trace::{Call, VmExecutionTrace, VmTrace}; use zksync_types::{L1BatchNumber, StorageLogQuery, VmEvent, U256}; @@ -447,7 +447,7 @@ impl VmInstance { VmExecutionLogs { storage_logs, events, - user_l2_to_l1_logs: l2_to_l1_logs, + user_l2_to_l1_logs: l2_to_l1_logs.into_iter().map(UserL2ToL1Log).collect(), system_l2_to_l1_logs: vec![], total_log_queries_count: storage_logs_count + log_queries.len() diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/logs.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/logs.rs index 1f1c7c0982dd..327a054afc09 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/logs.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/logs.rs @@ -1,7 +1,7 @@ use zk_evm_1_3_3::aux_structures::Timestamp; use zksync_state::WriteStorage; -use zksync_types::l2_to_l1_log::L2ToL1Log; +use zksync_types::l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log}; use zksync_types::VmEvent; use crate::interface::types::outputs::VmExecutionLogs; @@ -42,7 +42,7 @@ impl Vm { VmExecutionLogs { storage_logs, events, - user_l2_to_l1_logs: l2_to_l1_logs, + user_l2_to_l1_logs: l2_to_l1_logs.into_iter().map(UserL2ToL1Log).collect(), system_l2_to_l1_logs: vec![], total_log_queries_count, } diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/types/legacy_types.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/types/legacy_types.rs deleted file mode 100644 index 8b137891791f..000000000000 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/types/legacy_types.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/types/mod.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/types/mod.rs index 3d9635ea13b3..a12005734abb 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/types/mod.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/types/mod.rs @@ -1,3 +1,2 @@ pub(crate) mod internals; mod l1_batch; -pub mod legacy_types; diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs index 83feb7774f6d..c9d7d2b06ab5 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs @@ -1,10 +1,10 @@ use zksync_state::{StoragePtr, WriteStorage}; +use zksync_types::l2_to_l1_log::UserL2ToL1Log; use zksync_types::Transaction; use zksync_utils::bytecode::CompressedBytecodeInfo; use crate::vm_refunds_enhancement::old_vm::events::merge_events; use crate::vm_refunds_enhancement::old_vm::history_recorder::{HistoryEnabled, HistoryMode}; -use zksync_types::event::extract_l2tol1logs_from_l1_messenger; use crate::interface::BytecodeCompressionError; use crate::interface::{ @@ -89,8 +89,10 @@ impl Vm { .map(|e| e.into_vm_event(self.batch_env.number)) .collect(); - let user_l2_to_l1_logs = extract_l2tol1logs_from_l1_messenger(&events); - let system_logs = l1_messages.into_iter().map(|log| log.into()).collect(); + let l2_to_l1_logs = l1_messages + .into_iter() + .map(|log| UserL2ToL1Log(log.into())) + .collect(); let total_log_queries = self.state.event_sink.get_log_queries() + self .state @@ -103,11 +105,8 @@ impl Vm { events, storage_log_queries: self.state.storage.get_final_log_queries(), used_contract_hashes: self.get_used_contracts(), - user_l2_to_l1_logs: user_l2_to_l1_logs - .into_iter() - .map(|log| log.into()) - .collect(), - system_logs, + user_l2_to_l1_logs: l2_to_l1_logs, + system_logs: vec![], total_log_queries, cycles_used: self.state.local_state.monotonic_cycle_counter, deduplicated_events_logs, diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/logs.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/logs.rs index c4e34381c435..f67b97ff8753 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/logs.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/logs.rs @@ -2,7 +2,7 @@ use zk_evm_1_3_3::aux_structures::Timestamp; use zksync_state::WriteStorage; use crate::interface::types::outputs::VmExecutionLogs; -use zksync_types::l2_to_l1_log::L2ToL1Log; +use zksync_types::l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log}; use zksync_types::VmEvent; use crate::vm_virtual_blocks::old_vm::events::merge_events; @@ -42,7 +42,7 @@ impl Vm { VmExecutionLogs { storage_logs, events, - user_l2_to_l1_logs: l2_to_l1_logs, + user_l2_to_l1_logs: l2_to_l1_logs.into_iter().map(UserL2ToL1Log).collect(), system_l2_to_l1_logs: vec![], total_log_queries_count, } diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs index 2a9289a565d7..7bb5a6639df8 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs @@ -3,7 +3,7 @@ use crate::interface::{ SystemEnv, VmExecutionMode, VmExecutionResultAndLogs, }; use zksync_state::{StoragePtr, WriteStorage}; -use zksync_types::event::extract_l2tol1logs_from_l1_messenger; +use zksync_types::l2_to_l1_log::UserL2ToL1Log; use zksync_types::Transaction; use zksync_utils::bytecode::CompressedBytecodeInfo; @@ -88,8 +88,10 @@ impl Vm { .map(|e| e.into_vm_event(self.batch_env.number)) .collect(); - let user_l2_to_l1_logs = extract_l2tol1logs_from_l1_messenger(&events); - let system_logs = l1_messages.into_iter().map(|log| log.into()).collect(); + let l2_to_l1_logs = l1_messages + .into_iter() + .map(|log| UserL2ToL1Log(log.into())) + .collect(); let total_log_queries = self.state.event_sink.get_log_queries() + self .state @@ -102,11 +104,8 @@ impl Vm { events, storage_log_queries: self.state.storage.get_final_log_queries(), used_contract_hashes: self.get_used_contracts(), - user_l2_to_l1_logs: user_l2_to_l1_logs - .into_iter() - .map(|log| log.into()) - .collect(), - system_logs, + user_l2_to_l1_logs: l2_to_l1_logs, + system_logs: vec![], total_log_queries, cycles_used: self.state.local_state.monotonic_cycle_counter, deduplicated_events_logs, diff --git a/core/lib/state/Cargo.toml b/core/lib/state/Cargo.toml index 537ba9737cd1..b613266a650f 100644 --- a/core/lib/state/Cargo.toml +++ b/core/lib/state/Cargo.toml @@ -22,8 +22,6 @@ tokio = { version = "1", features = ["rt"] } tracing = "0.1" itertools = "0.10.3" -metrics = "0.21" - [dev-dependencies] rand = "0.8.5" tempfile = "3.0.2" diff --git a/core/lib/types/src/block.rs b/core/lib/types/src/block.rs index c41fdd93ed98..1896fe0eb50c 100644 --- a/core/lib/types/src/block.rs +++ b/core/lib/types/src/block.rs @@ -7,9 +7,10 @@ use zksync_basic_types::{H2048, H256, U256}; use zksync_contracts::BaseSystemContractsHashes; use crate::{ - l2_to_l1_log::L2ToL1Log, priority_op_onchain_data::PriorityOpOnchainData, - web3::signing::keccak256, AccountTreeId, Address, L1BatchNumber, MiniblockNumber, - ProtocolVersionId, Transaction, + l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, + priority_op_onchain_data::PriorityOpOnchainData, + web3::signing::keccak256, + AccountTreeId, Address, L1BatchNumber, MiniblockNumber, ProtocolVersionId, Transaction, }; /// Represents a successfully deployed smart contract. @@ -46,7 +47,7 @@ pub struct L1BatchHeader { /// The data of the processed priority operations hash which must be sent to the smart contract. pub priority_ops_onchain_data: Vec, /// All user generated L2 -> L1 logs in the block. - pub l2_to_l1_logs: Vec, + pub l2_to_l1_logs: Vec, /// Preimages of the hashes that were sent as value of L2 logs by special system L2 contract. pub l2_to_l1_messages: Vec>, /// Bloom filter for the event logs in the block. @@ -61,7 +62,7 @@ pub struct L1BatchHeader { pub l2_fair_gas_price: u64, pub base_system_contracts_hashes: BaseSystemContractsHashes, /// System logs are those emitted as part of the Vm excecution. - pub system_logs: Vec, + pub system_logs: Vec, /// Version of protocol used for the L1 batch. pub protocol_version: Option, } diff --git a/core/lib/types/src/commitment.rs b/core/lib/types/src/commitment.rs index 61dc9bf421c7..088e83202224 100644 --- a/core/lib/types/src/commitment.rs +++ b/core/lib/types/src/commitment.rs @@ -16,7 +16,7 @@ use zksync_system_constants::ZKPORTER_IS_AVAILABLE; use crate::{ block::L1BatchHeader, ethabi::Token, - l2_to_l1_log::L2ToL1Log, + l2_to_l1_log::{L2ToL1Log, SystemL2ToL1Log, UserL2ToL1Log}, web3::signing::keccak256, writes::{ compress_state_diffs, InitialStorageWrite, RepeatedStorageWrite, StateDiffRecord, @@ -34,9 +34,7 @@ pub trait SerializeCommitment { fn serialize_commitment(&self, buffer: &mut [u8]); } -/// Serialize elements for commitment. The results consist of: -/// 1. Number of elements (4 bytes) -/// 2. Serialized elements +/// Serialize elements for commitment. The result consists of packed serialized elements. pub fn serialize_commitments(values: &[I]) -> Vec { let final_len = values.len() * I::SERIALIZED_SIZE; let mut input = vec![0_u8; final_len]; @@ -100,12 +98,13 @@ impl L1BatchWithMetadata { unsorted_factory_deps: &'a HashMap>, ) -> impl Iterator + 'a { header.l2_to_l1_logs.iter().filter_map(move |log| { - if log.sender == KNOWN_CODES_STORAGE_ADDRESS { - let bytecode = unsorted_factory_deps.get(&log.key).unwrap_or_else(|| { + let inner = &log.0; + if inner.sender == KNOWN_CODES_STORAGE_ADDRESS { + let bytecode = unsorted_factory_deps.get(&inner.key).unwrap_or_else(|| { panic!( "Failed to get bytecode that was marked as known: bytecode_hash {:?}, \ L1 batch number {:?}", - log.key, header.number + inner.key, header.number ); }); Some(bytecode.as_slice()) @@ -211,7 +210,7 @@ impl L1BatchWithMetadata { // Process and Pack Logs res.extend((self.header.l2_to_l1_logs.len() as u32).to_be_bytes()); for l2_to_l1_log in &self.header.l2_to_l1_logs { - res.extend(l2_to_l1_log.to_bytes()); + res.extend(l2_to_l1_log.0.to_bytes()); } // Process and Pack Msgs @@ -248,6 +247,22 @@ impl SerializeCommitment for L2ToL1Log { } } +impl SerializeCommitment for UserL2ToL1Log { + const SERIALIZED_SIZE: usize = L2ToL1Log::SERIALIZED_SIZE; + + fn serialize_commitment(&self, buffer: &mut [u8]) { + self.0.serialize_commitment(buffer); + } +} + +impl SerializeCommitment for SystemL2ToL1Log { + const SERIALIZED_SIZE: usize = L2ToL1Log::SERIALIZED_SIZE; + + fn serialize_commitment(&self, buffer: &mut [u8]) { + self.0.serialize_commitment(buffer); + } +} + impl SerializeCommitment for InitialStorageWrite { const SERIALIZED_SIZE: usize = 64; @@ -279,7 +294,7 @@ impl SerializeCommitment for StateDiffRecord { struct L1BatchAuxiliaryOutput { // We use initial fields for debugging #[allow(dead_code)] - l2_l1_logs: Vec, + l2_l1_logs: Vec, #[allow(dead_code)] initial_writes: Vec, #[allow(dead_code)] @@ -312,10 +327,10 @@ struct L1BatchAuxiliaryOutput { impl L1BatchAuxiliaryOutput { fn new( - l2_l1_logs: Vec, + l2_l1_logs: Vec, initial_writes: Vec, repeated_writes: Vec, - system_logs: Vec, + system_logs: Vec, state_diffs: Vec, bootloader_heap_hash: H256, events_state_queue_hash: H256, @@ -335,8 +350,8 @@ impl L1BatchAuxiliaryOutput { let state_diffs_hash = H256::from(keccak256(&(state_diffs_packed))); let merkle_tree_leaves = l2_l1_logs_compressed - .chunks(L2ToL1Log::SERIALIZED_SIZE) - .map(|chunk| <[u8; L2ToL1Log::SERIALIZED_SIZE]>::try_from(chunk).unwrap()); + .chunks(UserL2ToL1Log::SERIALIZED_SIZE) + .map(|chunk| <[u8; UserL2ToL1Log::SERIALIZED_SIZE]>::try_from(chunk).unwrap()); // ^ Skip first 4 bytes of the serialized logs (i.e., the number of logs). let min_tree_size = Some(L2ToL1Log::LEGACY_LIMIT_PER_L1_BATCH); let l2_l1_logs_merkle_root = @@ -453,14 +468,14 @@ pub struct L1BatchCommitmentHash { impl L1BatchCommitment { #[allow(clippy::too_many_arguments)] pub fn new( - l2_to_l1_logs: Vec, + l2_to_l1_logs: Vec, rollup_last_leaf_index: u64, rollup_root_hash: H256, initial_writes: Vec, repeated_writes: Vec, bootloader_code_hash: H256, default_aa_code_hash: H256, - system_logs: Vec, + system_logs: Vec, state_diffs: Vec, bootloader_heap_hash: H256, events_state_queue_hash: H256, @@ -565,7 +580,7 @@ mod tests { use crate::commitment::{ L1BatchAuxiliaryOutput, L1BatchCommitment, L1BatchMetaParameters, L1BatchPassThroughData, }; - use crate::l2_to_l1_log::L2ToL1Log; + use crate::l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log}; use crate::writes::{InitialStorageWrite, RepeatedStorageWrite}; use crate::{H256, U256}; @@ -638,7 +653,12 @@ mod tests { }) .collect(); let auxiliary_output = L1BatchAuxiliaryOutput::new( - commitment_test.auxiliary_input.l2_l1_logs.clone(), + commitment_test + .auxiliary_input + .l2_l1_logs + .into_iter() + .map(UserL2ToL1Log) + .collect(), initial_writes, commitment_test.auxiliary_input.repeated_writes.clone(), vec![], diff --git a/core/lib/types/src/event.rs b/core/lib/types/src/event.rs index fccd5a43ac22..c901ac8b0f43 100644 --- a/core/lib/types/src/event.rs +++ b/core/lib/types/src/event.rs @@ -66,12 +66,12 @@ static L1_MESSAGE_EVENT_SIGNATURE: Lazy = Lazy::new(|| { /// ``` #[derive(Debug, Default, Clone, PartialEq)] pub struct L1MessengerL2ToL1Log { - l2_shard_id: u8, - is_service: bool, - tx_number_in_block: u16, - sender: Address, - key: U256, - value: U256, + pub l2_shard_id: u8, + pub is_service: bool, + pub tx_number_in_block: u16, + pub sender: Address, + pub key: U256, + pub value: U256, } impl L1MessengerL2ToL1Log { diff --git a/core/lib/types/src/l2_to_l1_log.rs b/core/lib/types/src/l2_to_l1_log.rs index 13aa5c559fd0..1e2278bd4532 100644 --- a/core/lib/types/src/l2_to_l1_log.rs +++ b/core/lib/types/src/l2_to_l1_log.rs @@ -15,6 +15,17 @@ pub struct L2ToL1Log { pub value: H256, } +/// A struct representing a "user" L2->L1 log, i.e. the one that has been emitted by using the L1Messenger. +/// It is identical to the SystemL2ToL1Log struct, but +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq)] +pub struct UserL2ToL1Log(pub L2ToL1Log); + +/// A struct representing a "user" L2->L1 log, i.e. the one that has been emitted by using the L1Messenger. +/// It is identical to the SystemL2ToL1Log struct, but + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, Eq)] +pub struct SystemL2ToL1Log(pub L2ToL1Log); + impl L2ToL1Log { /// Legacy upper bound of L2-to-L1 logs per single L1 batch. This is not used as a limit now, /// but still determines the minimum number of items in the Merkle tree built from L2-to-L1 logs diff --git a/core/lib/types/src/tx/tx_execution_info.rs b/core/lib/types/src/tx/tx_execution_info.rs index 206f0d8c43bc..91d9ed2c0a33 100644 --- a/core/lib/types/src/tx/tx_execution_info.rs +++ b/core/lib/types/src/tx/tx_execution_info.rs @@ -83,8 +83,10 @@ impl ExecutionMetrics { self.l2_to_l1_logs * L2ToL1Log::SERIALIZED_SIZE + self.l2_l1_long_messages + self.published_bytecode_bytes - // TODO: refactor this constant - // It represents the need to store the length's of messages as well as bytecodes + // TODO(PLA-648): refactor this constant + // It represents the need to store the length's of messages as well as bytecodes. + // It works due to the fact that each bytecode/L2->L1 long message is accompanied by a corresponding + // user L2->L1 log. + self.l2_to_l1_logs * 4 } } diff --git a/core/lib/zksync_core/src/lib.rs b/core/lib/zksync_core/src/lib.rs index e55110050859..2e35cf573a94 100644 --- a/core/lib/zksync_core/src/lib.rs +++ b/core/lib/zksync_core/src/lib.rs @@ -12,6 +12,7 @@ use zksync_circuit_breaker::{ CircuitBreakerChecker, CircuitBreakerError, }; use zksync_config::configs::api::MerkleTreeApiConfig; +use zksync_config::configs::contracts::ProverAtGenesis; use zksync_config::configs::{ api::{HealthCheckConfig, Web3JsonRpcConfig}, chain::{ @@ -129,45 +130,48 @@ pub async fn genesis_init( // Select the first prover to be used during genesis. // Later we can change provers using the system upgrades, but for genesis // we should select one using the environment config. - let first_l1_verifier_config = if contracts_config.prover_at_genesis == "fri" { - let l1_verifier_config = L1VerifierConfig { - params: VerifierParams { - recursion_node_level_vk_hash: contracts_config.fri_recursion_node_level_vk_hash, - recursion_leaf_level_vk_hash: contracts_config.fri_recursion_leaf_level_vk_hash, - recursion_circuits_set_vks_hash: zksync_types::H256::zero(), - }, - recursion_scheduler_level_vk_hash: contracts_config.snark_wrapper_vk_hash, - }; + let first_l1_verifier_config = + if matches!(contracts_config.prover_at_genesis, ProverAtGenesis::Fri) { + let l1_verifier_config = L1VerifierConfig { + params: VerifierParams { + recursion_node_level_vk_hash: contracts_config.fri_recursion_node_level_vk_hash, + recursion_leaf_level_vk_hash: contracts_config.fri_recursion_leaf_level_vk_hash, + recursion_circuits_set_vks_hash: zksync_types::H256::zero(), + }, + recursion_scheduler_level_vk_hash: contracts_config.snark_wrapper_vk_hash, + }; - let eth_client = QueryClient::new(eth_client_url)?; - let vk_hash: zksync_types::H256 = eth_client - .call_contract_function( - "verificationKeyHash", - (), - None, - Default::default(), - None, - contracts_config.verifier_addr, - zksync_contracts::verifier_contract(), - ) - .await?; + let eth_client = QueryClient::new(eth_client_url)?; + let vk_hash: zksync_types::H256 = eth_client + .call_contract_function( + "verificationKeyHash", + (), + None, + Default::default(), + None, + contracts_config.verifier_addr, + zksync_contracts::verifier_contract(), + ) + .await?; - assert_eq!( - vk_hash, l1_verifier_config.recursion_scheduler_level_vk_hash, - "L1 verifier key does not match the one in the config" - ); + assert_eq!( + vk_hash, l1_verifier_config.recursion_scheduler_level_vk_hash, + "L1 verifier key does not match the one in the config" + ); - l1_verifier_config - } else { - L1VerifierConfig { - params: VerifierParams { - recursion_node_level_vk_hash: contracts_config.recursion_node_level_vk_hash, - recursion_leaf_level_vk_hash: contracts_config.recursion_leaf_level_vk_hash, - recursion_circuits_set_vks_hash: contracts_config.recursion_circuits_set_vks_hash, - }, - recursion_scheduler_level_vk_hash: contracts_config.recursion_scheduler_level_vk_hash, - } - }; + l1_verifier_config + } else { + L1VerifierConfig { + params: VerifierParams { + recursion_node_level_vk_hash: contracts_config.recursion_node_level_vk_hash, + recursion_leaf_level_vk_hash: contracts_config.recursion_leaf_level_vk_hash, + recursion_circuits_set_vks_hash: contracts_config + .recursion_circuits_set_vks_hash, + }, + recursion_scheduler_level_vk_hash: contracts_config + .recursion_scheduler_level_vk_hash, + } + }; genesis::ensure_genesis_state( &mut storage, diff --git a/core/lib/zksync_core/src/proof_data_handler/request_processor.rs b/core/lib/zksync_core/src/proof_data_handler/request_processor.rs index 3fb41f3c2fc3..0e3505ec3511 100644 --- a/core/lib/zksync_core/src/proof_data_handler/request_processor.rs +++ b/core/lib/zksync_core/src/proof_data_handler/request_processor.rs @@ -154,13 +154,6 @@ impl RequestProcessor { let mut storage = self.pool.access_storage().await.unwrap(); - // let header = storage - // .blocks_dal() - // .get_l1_batch_header(l1_batch_number) - // .await - // .unwrap() - // .expect("Proved block without a header"); - let l1_batch = storage .blocks_dal() .get_l1_batch_metadata(l1_batch_number) @@ -183,8 +176,9 @@ impl RequestProcessor { .header .system_logs .into_iter() - .find(|elem| elem.key == u256_to_h256(2.into())) + .find(|elem| elem.0.key == u256_to_h256(2.into())) .expect("No state diff hash key") + .0 .value; if events_queue_state != events_queue_state_from_prover @@ -195,7 +189,10 @@ impl RequestProcessor { { let server_values = format!("{system_logs_hash} {state_diff_hash} {events_queue_state} {bootloader_heap_initial_content}"); let prover_values = format!("{system_logs_hash_from_prover} {state_diff_hash_from_prover} {events_queue_state_from_prover} {bootloader_heap_initial_content_from_prover}"); - tracing::error!("Auxilary output doesn't match, server values: {server_values} prover values: {prover_values}"); + panic!( + "Auxilary output doesn't match, server values: {} prover values: {}", + server_values, prover_values + ); } storage .proof_generation_dal() diff --git a/core/lib/zksync_core/src/state_keeper/io/seal_logic.rs b/core/lib/zksync_core/src/state_keeper/io/seal_logic.rs index c4d3ff70e5b9..ca2dc6419098 100644 --- a/core/lib/zksync_core/src/state_keeper/io/seal_logic.rs +++ b/core/lib/zksync_core/src/state_keeper/io/seal_logic.rs @@ -11,12 +11,13 @@ use multivm::interface::{FinishedL1Batch, L1BatchEnv}; use zksync_dal::StorageProcessor; use zksync_system_constants::ACCOUNT_CODE_STORAGE_ADDRESS; use zksync_types::{ - block::unpack_block_info, CURRENT_VIRTUAL_BLOCK_INFO_POSITION, SYSTEM_CONTEXT_ADDRESS, + block::unpack_block_info, + l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, + CURRENT_VIRTUAL_BLOCK_INFO_POSITION, SYSTEM_CONTEXT_ADDRESS, }; use zksync_types::{ block::{L1BatchHeader, MiniblockHeader}, event::{extract_added_tokens, extract_long_l2_to_l1_messages}, - l2_to_l1_log::L2ToL1Log, storage_writes_deduplicator::{ModifiedSlot, StorageWritesDeduplicator}, tx::{ tx_execution_info::DeduplicatedWritesMetrics, IncludedTxLocation, @@ -399,7 +400,7 @@ impl MiniblockSealCommand { let progress = MINIBLOCK_METRICS.start(MiniblockSealStage::InsertL2ToL1Logs, is_fictive); transaction .events_dal() - .save_l2_to_l1_logs(miniblock_number, &user_l2_to_l1_logs) + .save_user_l2_to_l1_logs(miniblock_number, &user_l2_to_l1_logs) .await; progress.observe(user_l2_to_l1_log_count); @@ -540,18 +541,18 @@ impl MiniblockSealCommand { fn extract_system_l2_to_l1_logs( &self, is_fictive: bool, - ) -> Vec<(IncludedTxLocation, Vec<&L2ToL1Log>)> { + ) -> Vec<(IncludedTxLocation, Vec<&SystemL2ToL1Log>)> { self.group_by_tx_location(&self.miniblock.system_l2_to_l1_logs, is_fictive, |log| { - u32::from(log.tx_number_in_block) + u32::from(log.0.tx_number_in_block) }) } fn extract_user_l2_to_l1_logs( &self, is_fictive: bool, - ) -> Vec<(IncludedTxLocation, Vec<&L2ToL1Log>)> { + ) -> Vec<(IncludedTxLocation, Vec<&UserL2ToL1Log>)> { self.group_by_tx_location(&self.miniblock.user_l2_to_l1_logs, is_fictive, |log| { - u32::from(log.tx_number_in_block) + u32::from(log.0.tx_number_in_block) }) } diff --git a/core/lib/zksync_core/src/state_keeper/updates/miniblock_updates.rs b/core/lib/zksync_core/src/state_keeper/updates/miniblock_updates.rs index 128832decb81..d0a4f035f514 100644 --- a/core/lib/zksync_core/src/state_keeper/updates/miniblock_updates.rs +++ b/core/lib/zksync_core/src/state_keeper/updates/miniblock_updates.rs @@ -1,11 +1,11 @@ use multivm::interface::{ExecutionResult, L2BlockEnv, VmExecutionResultAndLogs}; use multivm::vm_latest::TransactionVmExt; use std::collections::HashMap; +use zksync_types::l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}; use zksync_types::{ block::{legacy_miniblock_hash, miniblock_hash, BlockGasCount}, event::extract_bytecodes_marked_as_known, - l2_to_l1_log::L2ToL1Log, tx::tx_execution_info::TxExecutionStatus, tx::{ExecutionMetrics, TransactionExecutionResult}, vm_trace::Call, @@ -19,8 +19,8 @@ pub struct MiniblockUpdates { pub executed_transactions: Vec, pub events: Vec, pub storage_logs: Vec, - pub user_l2_to_l1_logs: Vec, - pub system_l2_to_l1_logs: Vec, + pub user_l2_to_l1_logs: Vec, + pub system_l2_to_l1_logs: Vec, pub new_factory_deps: HashMap>, /// How much L1 gas will it take to submit this block? pub l1_gas_count: BlockGasCount, diff --git a/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/fee_estimate.yul/fee_estimate.yul.zbin b/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/fee_estimate.yul/fee_estimate.yul.zbin index b0de84dc0764..51ceb18a6876 100644 Binary files a/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/fee_estimate.yul/fee_estimate.yul.zbin and b/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/fee_estimate.yul/fee_estimate.yul.zbin differ diff --git a/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/gas_test.yul/gas_test.yul.zbin b/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/gas_test.yul/gas_test.yul.zbin index ed145c83b18f..95ad9499e13f 100644 Binary files a/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/gas_test.yul/gas_test.yul.zbin and b/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/gas_test.yul/gas_test.yul.zbin differ diff --git a/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/playground_batch.yul/playground_batch.yul.zbin b/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/playground_batch.yul/playground_batch.yul.zbin index 1c67a2941abb..5fb13eaf859b 100644 Binary files a/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/playground_batch.yul/playground_batch.yul.zbin and b/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/playground_batch.yul/playground_batch.yul.zbin differ diff --git a/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/proved_batch.yul/proved_batch.yul.zbin b/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/proved_batch.yul/proved_batch.yul.zbin index 82d318b24560..287180a3a241 100644 Binary files a/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/proved_batch.yul/proved_batch.yul.zbin and b/etc/multivm_bootloaders/vm_virtual_blocks_finish_upgrade_fix/proved_batch.yul/proved_batch.yul.zbin differ diff --git a/etc/system-contracts b/etc/system-contracts index 8f09d7be4f3b..de597eddb794 160000 --- a/etc/system-contracts +++ b/etc/system-contracts @@ -1 +1 @@ -Subproject commit 8f09d7be4f3b67fe8232037daad839d244ed176e +Subproject commit de597eddb79491bb22bb237b8bcc4afea8cda26f