From f9e4c90a20b7d493f8521bbfa3ad5224902a0db7 Mon Sep 17 00:00:00 2001 From: perekopskiy Date: Tue, 8 Oct 2024 16:41:29 +0300 Subject: [PATCH] rework pubdata approach --- Cargo.lock | 3 +- .../system-constants-generator/src/utils.rs | 32 +- core/lib/multivm/Cargo.toml | 1 - core/lib/multivm/src/utils/events.rs | 56 +-- core/lib/multivm/src/versions/testonly.rs | 13 +- core/lib/multivm/src/versions/tests.rs | 29 +- core/lib/multivm/src/versions/vm_1_3_2/vm.rs | 10 +- .../vm_1_4_1/tracers/pubdata_tracer.rs | 3 +- .../vm_1_4_1/types/internals/pubdata.rs | 2 +- core/lib/multivm/src/versions/vm_1_4_1/vm.rs | 10 +- .../vm_1_4_2/tracers/pubdata_tracer.rs | 3 +- .../vm_1_4_2/types/internals/pubdata.rs | 2 +- core/lib/multivm/src/versions/vm_1_4_2/vm.rs | 10 +- .../tracers/pubdata_tracer.rs | 3 +- .../types/internals/pubdata.rs | 2 +- .../src/versions/vm_boojum_integration/vm.rs | 10 +- .../multivm/src/versions/vm_fast/pubdata.rs | 2 +- core/lib/multivm/src/versions/vm_fast/vm.rs | 4 +- .../vm_latest/bootloader_state/state.rs | 59 ++- .../vm_latest/bootloader_state/utils.rs | 116 +++--- .../vm_latest/implementation/execution.rs | 1 - .../src/versions/vm_latest/tests/block_tip.rs | 4 +- .../vm_latest/tests/tester/vm_tester.rs | 32 +- .../vm_latest/tracers/pubdata_tracer.rs | 20 +- .../versions/vm_latest/types/internals/mod.rs | 2 - .../vm_latest/types/internals/pubdata.rs | 339 ------------------ .../vm_latest/types/internals/vm_state.rs | 10 +- core/lib/multivm/src/versions/vm_latest/vm.rs | 17 +- core/lib/multivm/src/versions/vm_m5/vm.rs | 10 +- core/lib/multivm/src/versions/vm_m6/vm.rs | 10 +- .../src/versions/vm_refunds_enhancement/vm.rs | 10 +- .../src/versions/vm_virtual_blocks/vm.rs | 10 +- core/lib/multivm/src/vm_instance.rs | 70 +++- core/lib/prover_interface/src/inputs.rs | 5 +- core/lib/tee_verifier/src/lib.rs | 10 +- core/lib/vm_executor/src/batch/factory.rs | 36 +- core/lib/vm_executor/src/oneshot/block.rs | 8 +- core/lib/vm_executor/src/oneshot/mod.rs | 2 + core/lib/vm_executor/src/storage.rs | 8 +- core/lib/vm_interface/Cargo.toml | 2 + core/lib/vm_interface/src/executor.rs | 3 +- core/lib/vm_interface/src/lib.rs | 1 + core/lib/vm_interface/src/pubdata/mod.rs | 122 +++++++ core/lib/vm_interface/src/pubdata/rollup.rs | 136 +++++++ core/lib/vm_interface/src/pubdata/tests.rs | 121 +++++++ core/lib/vm_interface/src/pubdata/utils.rs | 70 ++++ core/lib/vm_interface/src/pubdata/validium.rs | 103 ++++++ core/lib/vm_interface/src/types/inputs/mod.rs | 5 +- .../src/types/inputs/system_env.rs | 4 +- core/lib/vm_interface/src/utils/dump.rs | 37 +- core/lib/vm_interface/src/utils/shadow.rs | 26 +- core/lib/vm_interface/src/vm.rs | 13 +- core/node/node_sync/src/external_io.rs | 4 +- core/node/proof_data_handler/src/tests.rs | 2 +- .../state_keeper/src/executor/tests/tester.rs | 30 +- core/node/state_keeper/src/io/common/mod.rs | 4 +- core/node/state_keeper/src/io/common/tests.rs | 8 +- core/node/state_keeper/src/io/mempool.rs | 41 +-- core/node/state_keeper/src/io/mod.rs | 3 +- core/node/state_keeper/src/io/persistence.rs | 3 +- core/node/state_keeper/src/io/tests/mod.rs | 4 +- core/node/state_keeper/src/keeper.rs | 25 +- core/node/state_keeper/src/testonly/mod.rs | 7 +- .../src/testonly/test_batch_executor.rs | 6 +- core/node/state_keeper/src/tests/mod.rs | 5 +- core/node/state_keeper/src/updates/mod.rs | 8 +- .../tee_verifier_input_producer/src/lib.rs | 3 +- core/node/vm_runner/src/process.rs | 1 + core/node/vm_runner/src/storage.rs | 9 +- .../vm_runner/src/tests/output_handler.rs | 1 - core/tests/vm-benchmark/src/vm.rs | 14 +- prover/Cargo.lock | 3 +- 72 files changed, 1097 insertions(+), 701 deletions(-) delete mode 100644 core/lib/multivm/src/versions/vm_latest/types/internals/pubdata.rs create mode 100644 core/lib/vm_interface/src/pubdata/mod.rs create mode 100644 core/lib/vm_interface/src/pubdata/rollup.rs create mode 100644 core/lib/vm_interface/src/pubdata/tests.rs create mode 100644 core/lib/vm_interface/src/pubdata/utils.rs create mode 100644 core/lib/vm_interface/src/pubdata/validium.rs diff --git a/Cargo.lock b/Cargo.lock index b1ead7e44bd..16c2d9033cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10484,7 +10484,6 @@ dependencies = [ "zk_evm 0.150.5", "zksync_contracts", "zksync_eth_signer", - "zksync_mini_merkle_tree", "zksync_system_constants", "zksync_test_account", "zksync_types", @@ -11342,8 +11341,10 @@ dependencies = [ "thiserror", "tracing", "zksync_contracts", + "zksync_mini_merkle_tree", "zksync_system_constants", "zksync_types", + "zksync_utils", ] [[package]] diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index 084c8037e2c..fd2a6422237 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -7,6 +7,7 @@ use zksync_contracts::{ }; use zksync_multivm::{ interface::{ + pubdata::pubdata_params_to_builder, storage::{InMemoryStorage, StorageView, WriteStorage}, tracer::VmExecutionStopReason, L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode, VmExecutionMode, VmFactory, @@ -21,11 +22,12 @@ use zksync_multivm::{ zk_evm_latest::aux_structures::Timestamp, }; use zksync_types::{ - block::L2BlockHasher, ethabi::Token, fee::Fee, fee_model::BatchFeeInput, l1::L1Tx, l2::L2Tx, - utils::storage_key_for_eth_balance, AccountTreeId, Address, Execute, K256PrivateKey, - L1BatchNumber, L1TxCommonData, L2BlockNumber, L2ChainId, Nonce, ProtocolVersionId, StorageKey, - Transaction, BOOTLOADER_ADDRESS, SYSTEM_CONTEXT_ADDRESS, SYSTEM_CONTEXT_GAS_PRICE_POSITION, - SYSTEM_CONTEXT_TX_ORIGIN_POSITION, U256, ZKPORTER_IS_AVAILABLE, + block::L2BlockHasher, commitment::PubdataParams, ethabi::Token, fee::Fee, + fee_model::BatchFeeInput, l1::L1Tx, l2::L2Tx, utils::storage_key_for_eth_balance, + AccountTreeId, Address, Execute, K256PrivateKey, L1BatchNumber, L1TxCommonData, L2BlockNumber, + L2ChainId, Nonce, ProtocolVersionId, StorageKey, Transaction, BOOTLOADER_ADDRESS, + SYSTEM_CONTEXT_ADDRESS, SYSTEM_CONTEXT_GAS_PRICE_POSITION, SYSTEM_CONTEXT_TX_ORIGIN_POSITION, + U256, ZKPORTER_IS_AVAILABLE, }; use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, u256_to_h256}; @@ -231,7 +233,6 @@ pub(super) fn execute_internal_transfer_test() -> u32 { execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT, chain_id: L2ChainId::default(), - pubdata_params: Default::default(), }; let eth_token_sys_contract = load_sys_contract("L2BaseToken"); @@ -262,7 +263,14 @@ pub(super) fn execute_internal_transfer_test() -> u32 { output: tracer_result.clone(), } .into_tracer_pointer(); - let mut vm: Vm<_, HistoryEnabled> = Vm::new(l1_batch, system_env, storage_view.to_rc_ptr()); + + let pubdata_builder = pubdata_params_to_builder(PubdataParams::default()); + let mut vm: Vm<_, HistoryEnabled> = Vm::new( + l1_batch, + system_env, + storage_view.to_rc_ptr(), + Some(pubdata_builder), + ); let result = vm.inspect(&mut tracer.into(), VmExecutionMode::Bootloader); assert!(!result.result.is_failed(), "The internal call has reverted"); @@ -314,11 +322,15 @@ pub(super) fn execute_user_txs_in_test_gas_vm( execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT, chain_id: L2ChainId::default(), - pubdata_params: Default::default(), }; + let pubdata_builder = pubdata_params_to_builder(PubdataParams::default()); - let mut vm: Vm<_, HistoryEnabled> = - Vm::new(l1_batch, system_env, Rc::new(RefCell::new(storage_view))); + let mut vm: Vm<_, HistoryEnabled> = Vm::new( + l1_batch, + system_env, + Rc::new(RefCell::new(storage_view)), + Some(pubdata_builder), + ); let mut total_gas_refunded = 0; for tx in txs { diff --git a/core/lib/multivm/Cargo.toml b/core/lib/multivm/Cargo.toml index 3bb8fd9b11f..2c2cd4f044b 100644 --- a/core/lib/multivm/Cargo.toml +++ b/core/lib/multivm/Cargo.toml @@ -28,7 +28,6 @@ zksync_types.workspace = true zksync_contracts.workspace = true zksync_utils.workspace = true zksync_system_constants.workspace = true -zksync_mini_merkle_tree.workspace = true zksync_vm_interface.workspace = true anyhow.workspace = true diff --git a/core/lib/multivm/src/utils/events.rs b/core/lib/multivm/src/utils/events.rs index 9720cb77914..d84651989e7 100644 --- a/core/lib/multivm/src/utils/events.rs +++ b/core/lib/multivm/src/utils/events.rs @@ -1,59 +1,10 @@ use zksync_system_constants::L1_MESSENGER_ADDRESS; use zksync_types::{ ethabi::{self, Token}, - l2_to_l1_log::L2ToL1Log, - Address, H256, U256, + H256, U256, }; -use zksync_utils::{u256_to_bytes_be, u256_to_h256}; -use crate::interface::VmEvent; - -/// Corresponds to the following solidity event: -/// ```solidity -/// struct L2ToL1Log { -/// uint8 l2ShardId; -/// bool isService; -/// uint16 txNumberInBlock; -/// address sender; -/// bytes32 key; -/// bytes32 value; -/// } -/// ``` -#[derive(Debug, Default, Clone, PartialEq)] -pub(crate) struct L1MessengerL2ToL1Log { - 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 { - pub fn packed_encoding(&self) -> Vec { - let mut res: Vec = vec![]; - res.push(self.l2_shard_id); - res.push(self.is_service as u8); - res.extend_from_slice(&self.tx_number_in_block.to_be_bytes()); - res.extend_from_slice(self.sender.as_bytes()); - res.extend(u256_to_bytes_be(&self.key)); - res.extend(u256_to_bytes_be(&self.value)); - res - } -} - -impl From for L2ToL1Log { - fn from(log: L1MessengerL2ToL1Log) -> Self { - L2ToL1Log { - shard_id: log.l2_shard_id, - is_service: log.is_service, - tx_number_in_block: log.tx_number_in_block, - sender: log.sender, - key: u256_to_h256(log.key), - value: u256_to_h256(log.value), - } - } -} +use crate::interface::{pubdata::L1MessengerL2ToL1Log, VmEvent}; #[derive(Debug, PartialEq)] pub(crate) struct L1MessengerBytecodePublicationRequest { @@ -142,7 +93,8 @@ mod tests { use zksync_system_constants::{ BOOTLOADER_ADDRESS, KNOWN_CODES_STORAGE_ADDRESS, L2_BASE_TOKEN_ADDRESS, }; - use zksync_types::L1BatchNumber; + use zksync_types::{Address, L1BatchNumber}; + use zksync_utils::u256_to_h256; use super::*; diff --git a/core/lib/multivm/src/versions/testonly.rs b/core/lib/multivm/src/versions/testonly.rs index 6d3ee557177..c498959e27b 100644 --- a/core/lib/multivm/src/versions/testonly.rs +++ b/core/lib/multivm/src/versions/testonly.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use zksync_contracts::BaseSystemContracts; use zksync_test_account::Account; use zksync_types::{ @@ -8,10 +10,18 @@ use zksync_types::{ use zksync_utils::{bytecode::hash_bytecode, u256_to_h256}; use crate::{ - interface::{storage::InMemoryStorage, L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode}, + interface::{ + pubdata::{rollup::RollupPubdataBuilder, PubdataBuilder}, + storage::InMemoryStorage, + L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode, + }, vm_latest::constants::BATCH_COMPUTATIONAL_GAS_LIMIT, }; +pub(super) fn default_pubdata_builder() -> Rc { + Rc::new(RollupPubdataBuilder::new(Address::zero())) +} + pub(super) fn default_system_env() -> SystemEnv { SystemEnv { zk_porter_available: false, @@ -21,7 +31,6 @@ pub(super) fn default_system_env() -> SystemEnv { execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT, chain_id: L2ChainId::from(270), - pubdata_params: Default::default(), } } diff --git a/core/lib/multivm/src/versions/tests.rs b/core/lib/multivm/src/versions/tests.rs index c2a04c155fe..1c438eb5a1c 100644 --- a/core/lib/multivm/src/versions/tests.rs +++ b/core/lib/multivm/src/versions/tests.rs @@ -22,7 +22,8 @@ use crate::{ }, utils::get_max_gas_per_pubdata_byte, versions::testonly::{ - default_l1_batch, default_system_env, make_account_rich, ContractToDeploy, + default_l1_batch, default_pubdata_builder, default_system_env, make_account_rich, + ContractToDeploy, }, vm_fast, vm_latest::{self, HistoryEnabled}, @@ -206,12 +207,13 @@ where { let system_env = default_system_env(); let l1_batch_env = default_l1_batch(L1BatchNumber(1)); + let pubdata_builder = default_pubdata_builder(); let mut storage = InMemoryStorage::with_system_contracts(hash_bytecode); let mut harness = Harness::new(&l1_batch_env); harness.setup_storage(&mut storage); let storage = StorageView::new(storage).to_rc_ptr(); - let mut vm = Vm::new(l1_batch_env, system_env, storage); + let mut vm = Vm::new(l1_batch_env, system_env, storage, Some(pubdata_builder)); harness.execute_on_vm(&mut vm); (vm, harness) } @@ -230,6 +232,7 @@ fn sanity_check_harness_on_new_vm() { fn sanity_check_shadow_vm() { let system_env = default_system_env(); let l1_batch_env = default_l1_batch(L1BatchNumber(1)); + let pubdata_builder = default_pubdata_builder(); let mut storage = InMemoryStorage::with_system_contracts(hash_bytecode); let mut harness = Harness::new(&l1_batch_env); harness.setup_storage(&mut storage); @@ -242,6 +245,7 @@ fn sanity_check_shadow_vm() { system_env, main_storage, shadow_storage, + Some(pubdata_builder), ); harness.execute_on_vm(&mut vm); } @@ -261,16 +265,17 @@ fn shadow_vm_basics() { harness.setup_storage(&mut storage); let storage = StorageView::new(storage).to_rc_ptr(); - let vm = dump - .clone() - .play_back_custom(|l1_batch_env, system_env, dump_storage| { - ShadowVm::<_, ReferenceVm, ReferenceVm<_>>::with_custom_shadow( - l1_batch_env, - system_env, - storage, - dump_storage, - ) - }); + let vm = + dump.clone() + .play_back_custom(|l1_batch_env, system_env, dump_storage, pubdata_builder| { + ShadowVm::<_, ReferenceVm, ReferenceVm<_>>::with_custom_shadow( + l1_batch_env, + system_env, + storage, + dump_storage, + pubdata_builder, + ) + }); let new_dump = vm.dump_state(); pretty_assertions::assert_eq!(new_dump, dump); } 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 5692f103da3..afbe55780da 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 @@ -1,7 +1,8 @@ -use std::collections::HashSet; +use std::{collections::HashSet, rc::Rc}; use zksync_types::Transaction; use zksync_utils::{bytecode::hash_bytecode, h256_to_u256}; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::{history_mode::HistoryMode, GlueInto}, @@ -187,7 +188,12 @@ impl VmInterface for Vm { } impl VmFactory for Vm { - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self { + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + _pubdata_builder: Option>, + ) -> Self { let oracle_tools = crate::vm_1_3_2::OracleTools::new(storage.clone()); let block_properties = crate::vm_1_3_2::BlockProperties { default_aa_code_hash: h256_to_u256( diff --git a/core/lib/multivm/src/versions/vm_1_4_1/tracers/pubdata_tracer.rs b/core/lib/multivm/src/versions/vm_1_4_1/tracers/pubdata_tracer.rs index 238804bc7fc..6f927c5c99a 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/tracers/pubdata_tracer.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/tracers/pubdata_tracer.rs @@ -10,6 +10,7 @@ use zksync_utils::{h256_to_u256, u256_to_bytes_be, u256_to_h256}; use crate::{ interface::{ + pubdata::L1MessengerL2ToL1Log, storage::{StoragePtr, WriteStorage}, tracer::{TracerExecutionStatus, TracerExecutionStopReason}, L1BatchEnv, VmEvent, VmExecutionMode, @@ -17,7 +18,7 @@ use crate::{ tracers::dynamic::vm_1_4_1::DynTracer, utils::events::{ extract_bytecode_publication_requests_from_l1_messenger, - extract_l2tol1logs_from_l1_messenger, L1MessengerL2ToL1Log, + extract_l2tol1logs_from_l1_messenger, }, vm_1_4_1::{ bootloader_state::{utils::apply_pubdata_to_memory, BootloaderState}, diff --git a/core/lib/multivm/src/versions/vm_1_4_1/types/internals/pubdata.rs b/core/lib/multivm/src/versions/vm_1_4_1/types/internals/pubdata.rs index d07732ae435..c1ca93152a0 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/types/internals/pubdata.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/types/internals/pubdata.rs @@ -1,6 +1,6 @@ use zksync_types::writes::{compress_state_diffs, StateDiffRecord}; -use crate::utils::events::L1MessengerL2ToL1Log; +use crate::interface::pubdata::L1MessengerL2ToL1Log; /// Struct based on which the pubdata blob is formed #[derive(Debug, Clone, Default)] diff --git a/core/lib/multivm/src/versions/vm_1_4_1/vm.rs b/core/lib/multivm/src/versions/vm_1_4_1/vm.rs index 68c8e92a03a..75f3c64052c 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/vm.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/vm.rs @@ -1,8 +1,11 @@ +use std::rc::Rc; + use circuit_sequencer_api_1_4_1::sort_storage_access::sort_storage_access_queries; use zksync_types::{ l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, Transaction, }; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::GlueInto, @@ -148,7 +151,12 @@ impl VmInterface for Vm { } impl VmFactory for Vm { - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self { + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + _pubdata_builder: Option>, + ) -> Self { let (state, bootloader_state) = new_vm_state(storage.clone(), &system_env, &batch_env); Self { bootloader_state, diff --git a/core/lib/multivm/src/versions/vm_1_4_2/tracers/pubdata_tracer.rs b/core/lib/multivm/src/versions/vm_1_4_2/tracers/pubdata_tracer.rs index ffe65b5e050..6c4f737f9e9 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/tracers/pubdata_tracer.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/tracers/pubdata_tracer.rs @@ -10,6 +10,7 @@ use zksync_utils::{h256_to_u256, u256_to_bytes_be, u256_to_h256}; use crate::{ interface::{ + pubdata::L1MessengerL2ToL1Log, storage::{StoragePtr, WriteStorage}, tracer::{TracerExecutionStatus, TracerExecutionStopReason}, L1BatchEnv, VmEvent, VmExecutionMode, @@ -17,7 +18,7 @@ use crate::{ tracers::dynamic::vm_1_4_1::DynTracer, utils::events::{ extract_bytecode_publication_requests_from_l1_messenger, - extract_l2tol1logs_from_l1_messenger, L1MessengerL2ToL1Log, + extract_l2tol1logs_from_l1_messenger, }, vm_1_4_2::{ bootloader_state::{utils::apply_pubdata_to_memory, BootloaderState}, diff --git a/core/lib/multivm/src/versions/vm_1_4_2/types/internals/pubdata.rs b/core/lib/multivm/src/versions/vm_1_4_2/types/internals/pubdata.rs index d07732ae435..c1ca93152a0 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/types/internals/pubdata.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/types/internals/pubdata.rs @@ -1,6 +1,6 @@ use zksync_types::writes::{compress_state_diffs, StateDiffRecord}; -use crate::utils::events::L1MessengerL2ToL1Log; +use crate::interface::pubdata::L1MessengerL2ToL1Log; /// Struct based on which the pubdata blob is formed #[derive(Debug, Clone, Default)] diff --git a/core/lib/multivm/src/versions/vm_1_4_2/vm.rs b/core/lib/multivm/src/versions/vm_1_4_2/vm.rs index d6e1fbc68a8..4f5d6caa697 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/vm.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/vm.rs @@ -1,10 +1,11 @@ -use std::mem; +use std::{mem, rc::Rc}; use circuit_sequencer_api_1_4_2::sort_storage_access::sort_storage_access_queries; use zksync_types::{ l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, Transaction, }; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::GlueInto, @@ -155,7 +156,12 @@ impl VmInterface for Vm { } impl VmFactory for Vm { - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self { + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + _pubdata_builder: Option>, + ) -> Self { let (state, bootloader_state) = new_vm_state(storage.clone(), &system_env, &batch_env); Self { bootloader_state, diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/tracers/pubdata_tracer.rs b/core/lib/multivm/src/versions/vm_boojum_integration/tracers/pubdata_tracer.rs index 326a5789612..2f7d141cb0a 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/tracers/pubdata_tracer.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/tracers/pubdata_tracer.rs @@ -10,6 +10,7 @@ use zksync_utils::{h256_to_u256, u256_to_bytes_be, u256_to_h256}; use crate::{ interface::{ + pubdata::L1MessengerL2ToL1Log, storage::{StoragePtr, WriteStorage}, tracer::{TracerExecutionStatus, TracerExecutionStopReason}, L1BatchEnv, VmEvent, VmExecutionMode, @@ -17,7 +18,7 @@ use crate::{ tracers::dynamic::vm_1_4_0::DynTracer, utils::events::{ extract_bytecode_publication_requests_from_l1_messenger, - extract_l2tol1logs_from_l1_messenger, L1MessengerL2ToL1Log, + extract_l2tol1logs_from_l1_messenger, }, vm_boojum_integration::{ bootloader_state::{utils::apply_pubdata_to_memory, BootloaderState}, diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/pubdata.rs b/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/pubdata.rs index 9df9009831f..152ccad2fbc 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/pubdata.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/pubdata.rs @@ -1,6 +1,6 @@ use zksync_types::writes::{compress_state_diffs, StateDiffRecord}; -use crate::utils::events::L1MessengerL2ToL1Log; +use crate::interface::pubdata::L1MessengerL2ToL1Log; /// Struct based on which the pubdata blob is formed #[derive(Debug, Clone, Default)] diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/vm.rs b/core/lib/multivm/src/versions/vm_boojum_integration/vm.rs index 17ce8365a0a..b3b75352dfb 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/vm.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/vm.rs @@ -1,8 +1,11 @@ +use std::rc::Rc; + use circuit_sequencer_api_1_4_0::sort_storage_access::sort_storage_access_queries; use zksync_types::{ l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, Transaction, }; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::GlueInto, @@ -149,7 +152,12 @@ impl VmInterface for Vm { } impl VmFactory for Vm { - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self { + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + _pubdata_builder: Option>, + ) -> Self { let (state, bootloader_state) = new_vm_state(storage.clone(), &system_env, &batch_env); Self { bootloader_state, diff --git a/core/lib/multivm/src/versions/vm_fast/pubdata.rs b/core/lib/multivm/src/versions/vm_fast/pubdata.rs index d07732ae435..c1ca93152a0 100644 --- a/core/lib/multivm/src/versions/vm_fast/pubdata.rs +++ b/core/lib/multivm/src/versions/vm_fast/pubdata.rs @@ -1,6 +1,6 @@ use zksync_types::writes::{compress_state_diffs, StateDiffRecord}; -use crate::utils::events::L1MessengerL2ToL1Log; +use crate::interface::pubdata::L1MessengerL2ToL1Log; /// Struct based on which the pubdata blob is formed #[derive(Debug, Clone, Default)] diff --git a/core/lib/multivm/src/versions/vm_fast/vm.rs b/core/lib/multivm/src/versions/vm_fast/vm.rs index 36698de105c..a11c305f4ce 100644 --- a/core/lib/multivm/src/versions/vm_fast/vm.rs +++ b/core/lib/multivm/src/versions/vm_fast/vm.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fmt, mem}; +use std::{collections::HashMap, fmt, mem, rc::Rc}; use zk_evm_1_5_0::zkevm_opcode_defs::system_params::INITIAL_FRAME_FORMAL_EH_LOCATION; use zksync_contracts::SystemContractCode; @@ -19,6 +19,7 @@ use zksync_vm2::{ interface::{CallframeInterface, HeapId, StateInterface, Tracer}, ExecutionEnd, FatPointer, Program, Settings, VirtualMachine, }; +use zksync_vm_interface::pubdata::PubdataBuilder; use super::{ bootloader_state::{BootloaderState, BootloaderStateSnapshot}, @@ -501,6 +502,7 @@ where batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr>, + _pubdata_builder: Option>, ) -> Self { let storage = ImmutableStorageView::new(storage); Self::custom(batch_env, system_env, storage) 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 b2cb50c653e..863ed6cd40b 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 @@ -1,14 +1,15 @@ -use std::cmp::Ordering; +use std::{cmp::Ordering, rc::Rc}; use once_cell::sync::OnceCell; -use zksync_types::{commitment::PubdataParams, L2ChainId, U256}; +use zksync_types::{L2ChainId, ProtocolVersionId, U256}; +use zksync_vm_interface::pubdata::PubdataBuilder; -use super::{ - tx::BootloaderTx, - utils::{apply_pubdata_to_memory, get_encoded_pubdata}, -}; +use super::{tx::BootloaderTx, utils::apply_pubdata_to_memory}; use crate::{ - interface::{BootloaderMemory, CompressedBytecodeInfo, L2BlockEnv, TxExecutionMode}, + interface::{ + pubdata::PubdataInput, BootloaderMemory, CompressedBytecodeInfo, L2BlockEnv, + TxExecutionMode, + }, vm_latest::{ bootloader_state::{ l2_block::BootloaderL2Block, @@ -16,9 +17,8 @@ use crate::{ utils::{apply_l2_block, apply_tx_to_memory}, }, constants::TX_DESCRIPTION_OFFSET, - types::internals::{PubdataInput, TransactionData}, + types::internals::TransactionData, utils::l2_blocks::assert_next_block, - MultiVMSubversion, }, }; @@ -49,10 +49,10 @@ pub struct BootloaderState { free_tx_offset: usize, /// Information about the the pubdata that will be needed to supply to the L1Messenger pubdata_information: OnceCell, - /// Params related to how the pubdata should be processed by the bootloader in the batch - pubdata_params: PubdataParams, - /// VM subversion - subversion: MultiVMSubversion, + /// Protocol version. + protocol_version: ProtocolVersionId, + /// Pubdata builder which is used to convert pubdata input to bytes. + pubdata_builder: Rc, } impl BootloaderState { @@ -60,8 +60,8 @@ impl BootloaderState { execution_mode: TxExecutionMode, initial_memory: BootloaderMemory, first_l2_block: L2BlockEnv, - pubdata_params: PubdataParams, - subversion: MultiVMSubversion, + protocol_version: ProtocolVersionId, + pubdata_builder: Rc, ) -> Self { let l2_block = BootloaderL2Block::new(first_l2_block, 0); Self { @@ -72,8 +72,8 @@ impl BootloaderState { execution_mode, free_tx_offset: 0, pubdata_information: Default::default(), - pubdata_params, - subversion, + protocol_version, + pubdata_builder, } } @@ -154,22 +154,15 @@ impl BootloaderState { .expect("Pubdata information is not set") } - pub(crate) fn get_encoded_pubdata(&self) -> Vec { + pub(crate) fn settlement_layer_pubdata(&self) -> Vec { let pubdata_information = self .pubdata_information .get() .expect("Pubdata information is not set") .clone(); - match self.subversion { - MultiVMSubversion::SmallBootloaderMemory - | MultiVMSubversion::IncreasedBootloaderMemory => { - pubdata_information.build_pubdata_pre_gateway(false) - } - MultiVMSubversion::Gateway => { - get_encoded_pubdata(pubdata_information, self.pubdata_params, false) - } - } + self.pubdata_builder + .settlement_layer_pubdata(pubdata_information, self.protocol_version) } fn last_mut_l2_block(&mut self) -> &mut BootloaderL2Block { @@ -211,9 +204,9 @@ impl BootloaderState { apply_pubdata_to_memory( &mut initial_memory, + self.pubdata_builder.clone(), pubdata_information, - self.pubdata_params, - self.subversion, + self.protocol_version, ); initial_memory } @@ -328,11 +321,11 @@ impl BootloaderState { } } - pub(crate) fn get_pubdata_params(&self) -> PubdataParams { - self.pubdata_params + pub(crate) fn pubdata_builder(&self) -> Rc { + self.pubdata_builder.clone() } - pub(crate) fn get_vm_subversion(&self) -> MultiVMSubversion { - self.subversion + pub(crate) fn protocol_version(&self) -> ProtocolVersionId { + self.protocol_version } } 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 49807122056..1e43dee1cea 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 @@ -1,12 +1,14 @@ -use zksync_types::{ - commitment::{L1BatchCommitmentMode, PubdataParams}, - ethabi, U256, -}; +use std::rc::Rc; + +use zksync_types::{ethabi, ProtocolVersionId, U256}; use zksync_utils::{bytes_to_be_words, h256_to_u256}; use super::tx::BootloaderTx; use crate::{ - interface::{BootloaderMemory, CompressedBytecodeInfo, TxExecutionMode}, + interface::{ + pubdata::{PubdataBuilder, PubdataInput}, + BootloaderMemory, CompressedBytecodeInfo, TxExecutionMode, + }, utils::bytecode, vm_latest::{ bootloader_state::l2_block::BootloaderL2Block, @@ -17,11 +19,6 @@ use crate::{ TX_DESCRIPTION_OFFSET, TX_OPERATOR_L2_BLOCK_INFO_OFFSET, TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO, TX_OVERHEAD_OFFSET, TX_TRUSTED_GAS_LIMIT_OFFSET, }, - types::internals::{ - pubdata::{PubdataBuilder, RollupPubdataBuilder, ValidiumPubdataBuilder}, - PubdataInput, - }, - MultiVMSubversion, }, }; @@ -131,73 +128,46 @@ fn apply_l2_block_inner( ]) } -pub(crate) fn get_encoded_pubdata( - pubdata_information: PubdataInput, - pubdata_params: PubdataParams, - l2_version: bool, -) -> Vec { - let pubdata_bytes: Vec = match pubdata_params.pubdata_type { - L1BatchCommitmentMode::Rollup => { - RollupPubdataBuilder.build_pubdata(pubdata_information, l2_version) - } - L1BatchCommitmentMode::Validium => { - ValidiumPubdataBuilder.build_pubdata(pubdata_information, l2_version) - } - }; - - if l2_version { - ethabi::encode(&[ - ethabi::Token::Address(pubdata_params.l2_da_validator_address), - ethabi::Token::Bytes(pubdata_bytes), - ]) - .to_vec() - } else { - pubdata_bytes - } -} - pub(crate) fn apply_pubdata_to_memory( memory: &mut BootloaderMemory, + pubdata_builder: Rc, pubdata_information: PubdataInput, - pubdata_params: PubdataParams, - subversion: MultiVMSubversion, + protocol_version: ProtocolVersionId, ) { - let (l1_messenger_pubdata_start_slot, pubdata) = match subversion { - MultiVMSubversion::SmallBootloaderMemory | MultiVMSubversion::IncreasedBootloaderMemory => { - // 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; - - // Need to skip first word as it represents array offset - // while bootloader expects only [len || data] - let pubdata = ethabi::encode(&[ethabi::Token::Bytes( - pubdata_information.build_pubdata_pre_gateway(true), - )])[32..] - .to_vec(); - - assert!( - pubdata.len() / 32 <= OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS - 2, - "The encoded pubdata is too big" - ); - - (l1_messenger_pubdata_start_slot, pubdata) - } - MultiVMSubversion::Gateway => { - // Skipping the first slot as it will be filled by the bootloader itself: - // It is for the selector of the call to the L1Messenger. - let l1_messenger_pubdata_start_slot = OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + 1; - - let pubdata = get_encoded_pubdata(pubdata_information, pubdata_params, true); - - assert!( - // Note that unlike the previous version, the difference is `1`, since now it also includes the offset - pubdata.len() / 32 < OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS, - "The encoded pubdata is too big" - ); - - (l1_messenger_pubdata_start_slot, pubdata) - } + let (l1_messenger_pubdata_start_slot, pubdata) = if protocol_version.is_pre_gateway() { + // 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; + + // Need to skip first word as it represents array offset + // while bootloader expects only [len || data] + let pubdata = ethabi::encode(&[ethabi::Token::Bytes( + pubdata_builder.l1_messenger_operator_input(pubdata_information, protocol_version), + )])[32..] + .to_vec(); + + assert!( + pubdata.len() / 32 <= OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS - 2, + "The encoded pubdata is too big" + ); + + (l1_messenger_pubdata_start_slot, pubdata) + } else { + // Skipping the first slot as it will be filled by the bootloader itself: + // It is for the selector of the call to the L1Messenger. + let l1_messenger_pubdata_start_slot = OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + 1; + + let pubdata = + pubdata_builder.bootloader_memory_input(pubdata_information, protocol_version); + + assert!( + // Note that unlike the previous version, the difference is `1`, since now it also includes the offset + pubdata.len() / 32 < OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS, + "The encoded pubdata is too big" + ); + + (l1_messenger_pubdata_start_slot, pubdata) }; pubdata 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 2f23bfb89f0..b8242fa7ca8 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs @@ -64,7 +64,6 @@ impl Vm { self.batch_env.clone(), execution_mode, self.subversion, - self.system_env.version, )) }), self.subversion, diff --git a/core/lib/multivm/src/versions/vm_latest/tests/block_tip.rs b/core/lib/multivm/src/versions/vm_latest/tests/block_tip.rs index 8ce00229332..9909ca24937 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/block_tip.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/block_tip.rs @@ -9,8 +9,7 @@ use zksync_system_constants::{ }; use zksync_types::{ commitment::SerializeCommitment, fee_model::BatchFeeInput, get_code_key, - l2_to_l1_log::L2ToL1Log, writes::StateDiffRecord, Address, Execute, ProtocolVersionId, H256, - U256, + l2_to_l1_log::L2ToL1Log, writes::StateDiffRecord, Address, Execute, H256, U256, }; use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256, u256_to_h256}; @@ -194,7 +193,6 @@ fn execute_test(test_data: L1MessengerTestData) -> TestStatistics { VmExecutionMode::Batch, test_data.state_diffs.clone(), crate::vm_latest::MultiVMSubversion::latest(), - ProtocolVersionId::latest(), ); let result = vm.vm.inspect_inner( diff --git a/core/lib/multivm/src/versions/vm_latest/tests/tester/vm_tester.rs b/core/lib/multivm/src/versions/vm_latest/tests/tester/vm_tester.rs index 91a2a925641..8c776fdbfd3 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/tester/vm_tester.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/tester/vm_tester.rs @@ -1,9 +1,8 @@ -use std::marker::PhantomData; +use std::{marker::PhantomData, rc::Rc}; use zksync_contracts::BaseSystemContracts; use zksync_types::{ block::L2BlockHasher, - commitment::PubdataParams, fee_model::BatchFeeInput, get_code_key, get_is_account_key, helpers::unix_timestamp_ms, @@ -11,6 +10,7 @@ use zksync_types::{ Address, L1BatchNumber, L2BlockNumber, L2ChainId, Nonce, ProtocolVersionId, U256, }; use zksync_utils::{bytecode::hash_bytecode, u256_to_h256}; +use zksync_vm_interface::pubdata::{rollup::RollupPubdataBuilder, PubdataBuilder}; use crate::{ interface::{ @@ -97,7 +97,12 @@ impl VmTester { }; } - let vm = Vm::new(l1_batch, self.vm.system_env.clone(), self.storage.clone()); + let vm = Vm::new( + l1_batch, + self.vm.system_env.clone(), + self.storage.clone(), + Some(self.vm.bootloader_state.pubdata_builder()), + ); if self.test_contract.is_some() { self.deploy_test_contract(); @@ -116,6 +121,7 @@ pub(crate) struct VmTesterBuilder { deployer: Option, rich_accounts: Vec, custom_contracts: Vec, + pubdata_builder: Option>, _phantom: PhantomData, } @@ -128,6 +134,7 @@ impl Clone for VmTesterBuilder { deployer: self.deployer.clone(), rich_accounts: self.rich_accounts.clone(), custom_contracts: self.custom_contracts.clone(), + pubdata_builder: self.pubdata_builder.clone(), _phantom: PhantomData, } } @@ -147,11 +154,11 @@ impl VmTesterBuilder { execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT, chain_id: L2ChainId::from(270), - pubdata_params: Default::default(), }, deployer: None, rich_accounts: vec![], custom_contracts: vec![], + pubdata_builder: None, _phantom: PhantomData, } } @@ -218,8 +225,11 @@ impl VmTesterBuilder { self } - pub(crate) fn with_custom_pubdata_params(mut self, pubdata_params: PubdataParams) -> Self { - self.system_env.pubdata_params = pubdata_params; + pub(crate) fn with_custom_pubdata_builder( + mut self, + pubdata_builder: Rc, + ) -> Self { + self.pubdata_builder = Some(pubdata_builder); self } @@ -239,7 +249,15 @@ impl VmTesterBuilder { } let fee_account = l1_batch_env.fee_account; - let vm = Vm::new(l1_batch_env, self.system_env, storage_ptr.clone()); + let pubdata_builder = self + .pubdata_builder + .unwrap_or_else(|| Rc::new(RollupPubdataBuilder::new(Address::zero()))); + let vm = Vm::new( + l1_batch_env, + self.system_env, + storage_ptr.clone(), + Some(pubdata_builder), + ); VmTester { vm, 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 9e620f96af2..6d8de43bad4 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 @@ -5,14 +5,12 @@ use zk_evm_1_5_0::{ aux_structures::Timestamp, tracing::{BeforeExecutionData, VmLocalStateData}, }; -use zksync_types::{ - l2_to_l1_log::l2_to_l1_logs_tree_size, writes::StateDiffRecord, AccountTreeId, - ProtocolVersionId, StorageKey, L1_MESSENGER_ADDRESS, -}; +use zksync_types::{writes::StateDiffRecord, AccountTreeId, StorageKey, L1_MESSENGER_ADDRESS}; use zksync_utils::{h256_to_u256, u256_to_bytes_be, u256_to_h256}; use crate::{ interface::{ + pubdata::{L1MessengerL2ToL1Log, PubdataInput}, storage::{StoragePtr, WriteStorage}, tracer::{TracerExecutionStatus, TracerExecutionStopReason}, L1BatchEnv, VmEvent, VmExecutionMode, @@ -20,14 +18,14 @@ use crate::{ tracers::dynamic::vm_1_5_0::DynTracer, utils::events::{ extract_bytecode_publication_requests_from_l1_messenger, - extract_l2tol1logs_from_l1_messenger, L1MessengerL2ToL1Log, + extract_l2tol1logs_from_l1_messenger, }, vm_latest::{ bootloader_state::{utils::apply_pubdata_to_memory, BootloaderState}, constants::BOOTLOADER_HEAP_PAGE, old_vm::{history_recorder::HistoryMode, memory::SimpleMemory}, tracers::{traits::VmTracer, utils::VmHook}, - types::internals::{PubdataInput, ZkSyncVmState}, + types::internals::ZkSyncVmState, utils::logs::collect_events_and_l1_system_logs_after_timestamp, vm::MultiVMSubversion, StorageOracle, @@ -44,7 +42,6 @@ pub(crate) struct PubdataTracer { // to the L1Messenger. enforced_state_diffs: Option>, subversion: MultiVMSubversion, - protocol_version: ProtocolVersionId, _phantom_data: PhantomData, } @@ -53,7 +50,6 @@ impl PubdataTracer { l1_batch_env: L1BatchEnv, execution_mode: VmExecutionMode, subversion: MultiVMSubversion, - protocol_version: ProtocolVersionId, ) -> Self { Self { l1_batch_env, @@ -61,7 +57,6 @@ impl PubdataTracer { execution_mode, enforced_state_diffs: None, subversion, - protocol_version, _phantom_data: Default::default(), } } @@ -74,7 +69,6 @@ impl PubdataTracer { execution_mode: VmExecutionMode, forced_state_diffs: Vec, subversion: MultiVMSubversion, - protocol_version: ProtocolVersionId, ) -> Self { Self { l1_batch_env, @@ -82,7 +76,6 @@ impl PubdataTracer { execution_mode, enforced_state_diffs: Some(forced_state_diffs), subversion, - protocol_version, _phantom_data: Default::default(), } } @@ -192,7 +185,6 @@ impl PubdataTracer { 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.storage), - l2_to_l1_logs_tree_size: l2_to_l1_logs_tree_size(self.protocol_version), } } } @@ -238,9 +230,9 @@ impl VmTracer for PubdataTracer { apply_pubdata_to_memory( &mut memory_to_apply, + bootloader_state.pubdata_builder(), pubdata_input, - bootloader_state.get_pubdata_params(), - bootloader_state.get_vm_subversion(), + bootloader_state.protocol_version(), ); state.memory.populate_page( BOOTLOADER_HEAP_PAGE as usize, 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 0b9f704e8db..601b7b8bd01 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,9 +1,7 @@ -pub(crate) use pubdata::PubdataInput; pub(crate) use snapshot::VmSnapshot; pub(crate) use transaction_data::TransactionData; pub(crate) use vm_state::new_vm_state; pub use vm_state::ZkSyncVmState; -pub(crate) mod pubdata; mod snapshot; mod transaction_data; mod vm_state; 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 deleted file mode 100644 index b39e280dc33..00000000000 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/pubdata.rs +++ /dev/null @@ -1,339 +0,0 @@ -use ethabi::ParamType; -use zksync_mini_merkle_tree::MiniMerkleTree; -use zksync_types::{ - ethabi::{self, Token}, - web3::keccak256, - writes::{compress_state_diffs, StateDiffRecord}, -}; -use zksync_utils::bytecode::hash_bytecode; - -use crate::utils::events::L1MessengerL2ToL1Log; - -/// 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, - pub(crate) l2_to_l1_logs_tree_size: usize, -} - -impl PubdataInput { - pub(crate) fn build_pubdata_pre_gateway(self, with_uncompressed_state_diffs: bool) -> 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); - - if with_uncompressed_state_diffs { - 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()); - } - } - - l1_messenger_pubdata - } -} - -pub trait PubdataBuilder { - // when `l2_version` is true it will return the data to be sent to the L1_MESSENGER - // otherwise it returns the array of bytes to be sent to settlement layer inside the operator input. - fn build_pubdata(&self, input: PubdataInput, l2_version: bool) -> Vec; -} - -#[derive(Debug)] -pub struct RollupPubdataBuilder; - -impl PubdataBuilder for RollupPubdataBuilder { - fn build_pubdata(&self, input: PubdataInput, l2_version: bool) -> Vec { - let mut l1_messenger_pubdata = vec![]; - let mut l2_da_header = vec![]; - - let PubdataInput { - user_logs, - l2_to_l1_messages, - published_bytecodes, - state_diffs, - l2_to_l1_logs_tree_size, - } = input; - - if l2_version { - let chained_log_hash = build_chained_log_hash(&user_logs); - let log_root_hash = build_logs_root(&user_logs, l2_to_l1_logs_tree_size); - let chained_msg_hash = build_chained_message_hash(&l2_to_l1_messages); - let chained_bytecodes_hash = build_chained_bytecode_hash(&published_bytecodes); - - l2_da_header.push(Token::FixedBytes(chained_log_hash)); - l2_da_header.push(Token::FixedBytes(log_root_hash)); - l2_da_header.push(Token::FixedBytes(chained_msg_hash)); - l2_da_header.push(Token::FixedBytes(chained_bytecodes_hash)); - } - - l1_messenger_pubdata.extend(encode_user_logs(&user_logs)); - - // 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); - - if l2_version { - 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()); - } - - // Selector of `IL2DAValidator::validatePubdata`. - let func_selector = ethabi::short_signature( - "validatePubdata", - &[ - ParamType::FixedBytes(32), - ParamType::FixedBytes(32), - ParamType::FixedBytes(32), - ParamType::FixedBytes(32), - ParamType::Bytes, - ], - ); - - l2_da_header.push(ethabi::Token::Bytes(l1_messenger_pubdata)); - - l1_messenger_pubdata = [func_selector.to_vec(), ethabi::encode(&l2_da_header)] - .concat() - .to_vec(); - } - - l1_messenger_pubdata - } -} - -#[derive(Debug)] -pub struct ValidiumPubdataBuilder; - -impl PubdataBuilder for ValidiumPubdataBuilder { - fn build_pubdata(&self, input: PubdataInput, l2_version: bool) -> Vec { - let mut l1_messenger_pubdata = vec![]; - let mut l2_da_header = vec![]; - - let PubdataInput { - user_logs, - l2_to_l1_messages, - published_bytecodes, - state_diffs, - l2_to_l1_logs_tree_size, - } = input; - - if l2_version { - let chained_log_hash = build_chained_log_hash(&user_logs); - let log_root_hash = build_logs_root(&user_logs, l2_to_l1_logs_tree_size); - let chained_msg_hash = build_chained_message_hash(&l2_to_l1_messages); - let chained_bytecodes_hash = build_chained_bytecode_hash(&published_bytecodes); - l2_da_header.push(Token::FixedBytes(chained_log_hash)); - l2_da_header.push(Token::FixedBytes(log_root_hash)); - l2_da_header.push(Token::FixedBytes(chained_msg_hash)); - l2_da_header.push(Token::FixedBytes(chained_bytecodes_hash)); - } - - l1_messenger_pubdata.extend(encode_user_logs(&user_logs)); - - if l2_version { - // Selector of `IL2DAValidator::validatePubdata`. - let func_selector = ethabi::short_signature( - "validatePubdata", - &[ - ParamType::FixedBytes(32), - ParamType::FixedBytes(32), - ParamType::FixedBytes(32), - ParamType::FixedBytes(32), - ParamType::Bytes, - ], - ); - - l2_da_header.push(ethabi::Token::Bytes(l1_messenger_pubdata)); - - [func_selector.to_vec(), ethabi::encode(&l2_da_header)] - .concat() - .to_vec() - } else { - let state_diffs_packed = state_diffs - .into_iter() - .flat_map(|diff| diff.encode_padded()) - .collect::>(); - - keccak256(&state_diffs_packed).to_vec() - } - } -} - -fn build_chained_log_hash(user_logs: &[L1MessengerL2ToL1Log]) -> Vec { - let mut chained_log_hash = vec![0u8; 32]; - - for log in user_logs { - let log_bytes = log.packed_encoding(); - let hash = keccak256(&log_bytes); - - chained_log_hash = keccak256(&[chained_log_hash, hash.to_vec()].concat()).to_vec(); - } - - chained_log_hash -} - -fn build_logs_root(user_logs: &[L1MessengerL2ToL1Log], l2_to_l1_logs_tree_size: usize) -> Vec { - let logs = user_logs.iter().map(|log| { - let encoded = log.packed_encoding(); - let mut slice = [0u8; 88]; - slice.copy_from_slice(&encoded); - slice - }); - MiniMerkleTree::new(logs, Some(l2_to_l1_logs_tree_size)) - .merkle_root() - .as_bytes() - .to_vec() -} - -fn build_chained_message_hash(l2_to_l1_messages: &[Vec]) -> Vec { - let mut chained_msg_hash = vec![0u8; 32]; - - for msg in l2_to_l1_messages { - let hash = keccak256(msg); - - chained_msg_hash = keccak256(&[chained_msg_hash, hash.to_vec()].concat()).to_vec(); - } - - chained_msg_hash -} - -fn build_chained_bytecode_hash(published_bytecodes: &[Vec]) -> Vec { - let mut chained_bytecode_hash = vec![0u8; 32]; - - for bytecode in published_bytecodes { - let hash = hash_bytecode(bytecode).to_fixed_bytes(); - - chained_bytecode_hash = - keccak256(&[chained_bytecode_hash, hash.to_vec()].concat()).to_vec(); - } - - chained_bytecode_hash -} - -fn encode_user_logs(user_logs: &[L1MessengerL2ToL1Log]) -> Vec { - // Encoding user L2->L1 logs. - // Format: `[(numberOfL2ToL1Logs as u32) || l2tol1logs[1] || ... || l2tol1logs[n]]` - let mut result = vec![]; - result.extend((user_logs.len() as u32).to_be_bytes()); - for l2tol1log in user_logs { - result.extend(l2tol1log.packed_encoding()); - } - result -} - -#[cfg(test)] -mod tests { - use zksync_system_constants::{ACCOUNT_CODE_STORAGE_ADDRESS, BOOTLOADER_ADDRESS}; - use zksync_types::{l2_to_l1_log::l2_to_l1_logs_tree_size, ProtocolVersionId}; - 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, - l2_to_l1_logs_tree_size: l2_to_l1_logs_tree_size(ProtocolVersionId::latest()), - }; - - let pubdata = - ethabi::encode(&[ethabi::Token::Bytes(input.build_pubdata_pre_gateway(true))])[32..] - .to_vec(); - - assert_eq!(hex::encode(pubdata), "00000000000000000000000000000000000000000000000000000000000002c700000001000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000100000004deadbeef0000000100000004aaaabbbb0100002a040001000000000000000000000000000000000000000000000000000000000000007e090e0000000c0901000000020000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000007d000000000000000c000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - } -} diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs index b6e5e127c85..8aa11aad3cd 100644 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use circuit_sequencer_api_1_3_3::INITIAL_MONOTONIC_CYCLE_COUNTER; use zk_evm_1_5_0::{ aux_structures::{MemoryPage, PubdataCost, Timestamp}, @@ -13,6 +15,7 @@ use zk_evm_1_5_0::{ use zksync_system_constants::BOOTLOADER_ADDRESS; use zksync_types::{block::L2BlockHasher, Address, L2BlockNumber}; use zksync_utils::h256_to_u256; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ interface::{ @@ -33,7 +36,6 @@ use crate::{ oracles::storage::StorageOracle, types::l1_batch::bootloader_initial_memory, utils::l2_blocks::{assert_next_block, load_last_l2_block}, - MultiVMSubversion, }, }; @@ -65,7 +67,7 @@ pub(crate) fn new_vm_state( storage: StoragePtr, system_env: &SystemEnv, l1_batch_env: &L1BatchEnv, - subversion: MultiVMSubversion, + pubdata_builder: Rc, ) -> (ZkSyncVmState, BootloaderState) { let last_l2_block = if let Some(last_l2_block) = load_last_l2_block(&storage) { last_l2_block @@ -183,8 +185,8 @@ pub(crate) fn new_vm_state( system_env.execution_mode, bootloader_initial_memory, first_l2_block, - system_env.pubdata_params, - subversion, + system_env.version, + pubdata_builder, ); (vm, bootloader_state) diff --git a/core/lib/multivm/src/versions/vm_latest/vm.rs b/core/lib/multivm/src/versions/vm_latest/vm.rs index e43dcf31d80..c6371732f81 100644 --- a/core/lib/multivm/src/versions/vm_latest/vm.rs +++ b/core/lib/multivm/src/versions/vm_latest/vm.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use circuit_sequencer_api_1_5_0::sort_storage_access::sort_storage_access_queries; use zksync_types::{ l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, @@ -5,6 +7,7 @@ use zksync_types::{ Transaction, H256, }; use zksync_utils::u256_to_h256; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::GlueInto, @@ -176,7 +179,7 @@ impl VmInterface for Vm { block_tip_execution_result: result, final_execution_state: execution_state, final_bootloader_memory: Some(bootloader_memory), - pubdata_input: Some(self.bootloader_state.get_encoded_pubdata()), + pubdata_input: Some(self.bootloader_state.settlement_layer_pubdata()), state_diffs: Some( self.bootloader_state .get_pubdata_information() @@ -188,12 +191,18 @@ impl VmInterface for Vm { } impl VmFactory for Vm { - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self { + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + pubdata_builder: Option>, + ) -> Self { let vm_version: VmVersion = system_env.version.into(); Self::new_with_subversion( batch_env, system_env, storage, + pubdata_builder, vm_version.try_into().expect("Incorrect 1.5.0 VmVersion"), ) } @@ -204,10 +213,12 @@ impl Vm { batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr, + pubdata_builder: Option>, subversion: MultiVMSubversion, ) -> Self { + let pubdata_builder = pubdata_builder.expect("pubdata_builder is required"); let (state, bootloader_state) = - new_vm_state(storage.clone(), &system_env, &batch_env, subversion); + new_vm_state(storage.clone(), &system_env, &batch_env, pubdata_builder); Self { bootloader_state, state, diff --git a/core/lib/multivm/src/versions/vm_m5/vm.rs b/core/lib/multivm/src/versions/vm_m5/vm.rs index 40f66659f29..47b91700408 100644 --- a/core/lib/multivm/src/versions/vm_m5/vm.rs +++ b/core/lib/multivm/src/versions/vm_m5/vm.rs @@ -1,5 +1,8 @@ +use std::rc::Rc; + use zksync_types::{vm::VmVersion, Transaction}; use zksync_utils::h256_to_u256; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::{history_mode::HistoryMode, GlueInto}, @@ -129,7 +132,12 @@ impl VmInterface for Vm { } impl VmFactory for Vm { - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self { + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + _pubdata_builder: Option>, + ) -> Self { let vm_version: VmVersion = system_env.version.into(); let vm_sub_version = match vm_version { VmVersion::M5WithoutRefunds => MultiVMSubversion::V1, diff --git a/core/lib/multivm/src/versions/vm_m6/vm.rs b/core/lib/multivm/src/versions/vm_m6/vm.rs index 627687a5524..8920cdd88bf 100644 --- a/core/lib/multivm/src/versions/vm_m6/vm.rs +++ b/core/lib/multivm/src/versions/vm_m6/vm.rs @@ -1,7 +1,8 @@ -use std::collections::HashSet; +use std::{collections::HashSet, rc::Rc}; use zksync_types::{vm::VmVersion, Transaction}; use zksync_utils::{bytecode::hash_bytecode, h256_to_u256}; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::{history_mode::HistoryMode, GlueInto}, @@ -213,7 +214,12 @@ impl VmInterface for Vm { } impl VmFactory for Vm { - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self { + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + _pubdata_builder: Option>, + ) -> Self { let vm_version: VmVersion = system_env.version.into(); let vm_sub_version = match vm_version { VmVersion::M6Initial => MultiVMSubversion::V1, 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 735bd29c3b0..1da38c73e7d 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs @@ -1,5 +1,8 @@ +use std::rc::Rc; + use circuit_sequencer_api_1_3_3::sort_storage_access::sort_storage_access_queries; use zksync_types::{l2_to_l1_log::UserL2ToL1Log, Transaction}; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::GlueInto, @@ -137,7 +140,12 @@ impl VmInterface for Vm { } impl VmFactory for Vm { - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self { + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + _pubdata_builder: Option>, + ) -> Self { let (state, bootloader_state) = new_vm_state(storage.clone(), &system_env, &batch_env); Self { bootloader_state, 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 2a9d6eed6c7..4f187553afd 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs @@ -1,5 +1,8 @@ +use std::rc::Rc; + use circuit_sequencer_api_1_3_3::sort_storage_access::sort_storage_access_queries; use zksync_types::{l2_to_l1_log::UserL2ToL1Log, Transaction}; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::GlueInto, @@ -137,7 +140,12 @@ impl VmInterface for Vm { } impl VmFactory for Vm { - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self { + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + _pubdata_builder: Option>, + ) -> Self { let (state, bootloader_state) = new_vm_state(storage.clone(), &system_env, &batch_env); Self { bootloader_state, diff --git a/core/lib/multivm/src/vm_instance.rs b/core/lib/multivm/src/vm_instance.rs index bfb121a740e..6dded13a979 100644 --- a/core/lib/multivm/src/vm_instance.rs +++ b/core/lib/multivm/src/vm_instance.rs @@ -1,7 +1,8 @@ -use std::mem; +use std::{mem, rc::Rc}; use zksync_types::{vm::VmVersion, Transaction}; use zksync_vm2::interface::Tracer; +use zksync_vm_interface::pubdata::PubdataBuilder; use crate::{ glue::history_mode::HistoryMode, @@ -102,10 +103,17 @@ impl VmFactory> for LegacyVmInsta batch_env: L1BatchEnv, system_env: SystemEnv, storage_view: StoragePtr>, + pubdata_builder: Option>, ) -> Self { let protocol_version = system_env.version; let vm_version: VmVersion = protocol_version.into(); - Self::new_with_specific_version(batch_env, system_env, storage_view, vm_version) + Self::new_with_specific_version( + batch_env, + system_env, + storage_view, + vm_version, + pubdata_builder, + ) } } @@ -129,6 +137,7 @@ impl LegacyVmInstance { system_env: SystemEnv, storage_view: StoragePtr>, vm_version: VmVersion, + pubdata_builder: Option>, ) -> Self { match vm_version { VmVersion::M5WithoutRefunds => { @@ -168,29 +177,57 @@ impl LegacyVmInstance { Self::VmM6(vm) } VmVersion::Vm1_3_2 => { - let vm = crate::vm_1_3_2::Vm::new(l1_batch_env, system_env, storage_view); + let vm = crate::vm_1_3_2::Vm::new( + l1_batch_env, + system_env, + storage_view, + pubdata_builder, + ); Self::Vm1_3_2(vm) } VmVersion::VmVirtualBlocks => { - let vm = crate::vm_virtual_blocks::Vm::new(l1_batch_env, system_env, storage_view); + let vm = crate::vm_virtual_blocks::Vm::new( + l1_batch_env, + system_env, + storage_view, + pubdata_builder, + ); Self::VmVirtualBlocks(vm) } VmVersion::VmVirtualBlocksRefundsEnhancement => { - let vm = - crate::vm_refunds_enhancement::Vm::new(l1_batch_env, system_env, storage_view); + let vm = crate::vm_refunds_enhancement::Vm::new( + l1_batch_env, + system_env, + storage_view, + pubdata_builder, + ); Self::VmVirtualBlocksRefundsEnhancement(vm) } VmVersion::VmBoojumIntegration => { - let vm = - crate::vm_boojum_integration::Vm::new(l1_batch_env, system_env, storage_view); + let vm = crate::vm_boojum_integration::Vm::new( + l1_batch_env, + system_env, + storage_view, + pubdata_builder, + ); Self::VmBoojumIntegration(vm) } VmVersion::Vm1_4_1 => { - let vm = crate::vm_1_4_1::Vm::new(l1_batch_env, system_env, storage_view); + let vm = crate::vm_1_4_1::Vm::new( + l1_batch_env, + system_env, + storage_view, + pubdata_builder, + ); Self::Vm1_4_1(vm) } VmVersion::Vm1_4_2 => { - let vm = crate::vm_1_4_2::Vm::new(l1_batch_env, system_env, storage_view); + let vm = crate::vm_1_4_2::Vm::new( + l1_batch_env, + system_env, + storage_view, + pubdata_builder, + ); Self::Vm1_4_2(vm) } VmVersion::Vm1_5_0SmallBootloaderMemory => { @@ -198,6 +235,7 @@ impl LegacyVmInstance { l1_batch_env, system_env, storage_view, + pubdata_builder, crate::vm_latest::MultiVMSubversion::SmallBootloaderMemory, ); Self::Vm1_5_0(vm) @@ -207,6 +245,7 @@ impl LegacyVmInstance { l1_batch_env, system_env, storage_view, + pubdata_builder, crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory, ); Self::Vm1_5_0(vm) @@ -216,6 +255,7 @@ impl LegacyVmInstance { l1_batch_env, system_env, storage_view, + pubdata_builder, crate::vm_latest::MultiVMSubversion::Gateway, ); Self::Vm1_5_0(vm) @@ -323,11 +363,13 @@ impl FastVmInstance { l1_batch_env: L1BatchEnv, system_env: SystemEnv, storage_view: StoragePtr>, + pubdata_builder: Option>, ) -> Self { Self::Fast(crate::vm_fast::Vm::new( l1_batch_env, system_env, storage_view, + pubdata_builder, )) } @@ -336,7 +378,13 @@ impl FastVmInstance { l1_batch_env: L1BatchEnv, system_env: SystemEnv, storage_view: StoragePtr>, + pubdata_builder: Option>, ) -> Self { - Self::Shadowed(ShadowedFastVm::new(l1_batch_env, system_env, storage_view)) + Self::Shadowed(ShadowedFastVm::new( + l1_batch_env, + system_env, + storage_view, + pubdata_builder, + )) } } diff --git a/core/lib/prover_interface/src/inputs.rs b/core/lib/prover_interface/src/inputs.rs index 22a20223c8b..fc661ea27ce 100644 --- a/core/lib/prover_interface/src/inputs.rs +++ b/core/lib/prover_interface/src/inputs.rs @@ -5,7 +5,7 @@ use serde_with::{serde_as, Bytes}; use zksync_multivm::interface::{L1BatchEnv, SystemEnv}; use zksync_object_store::{serialize_using_bincode, Bucket, StoredObject}; use zksync_types::{ - basic_fri_types::Eip4844Blobs, block::L2BlockExecutionData, + basic_fri_types::Eip4844Blobs, block::L2BlockExecutionData, commitment::PubdataParams, witness_block_state::WitnessStorageState, L1BatchNumber, ProtocolVersionId, H256, U256, }; @@ -196,6 +196,7 @@ pub struct V1TeeVerifierInput { pub l1_batch_env: L1BatchEnv, pub system_env: SystemEnv, pub used_contracts: Vec<(H256, Vec)>, + pub pubdata_params: PubdataParams, } impl V1TeeVerifierInput { @@ -205,6 +206,7 @@ impl V1TeeVerifierInput { l1_batch_env: L1BatchEnv, system_env: SystemEnv, used_contracts: Vec<(H256, Vec)>, + pubdata_params: PubdataParams, ) -> Self { V1TeeVerifierInput { witness_input_merkle_paths, @@ -212,6 +214,7 @@ impl V1TeeVerifierInput { l1_batch_env, system_env, used_contracts, + pubdata_params, } } } diff --git a/core/lib/tee_verifier/src/lib.rs b/core/lib/tee_verifier/src/lib.rs index 595480687e9..79ade47a1a0 100644 --- a/core/lib/tee_verifier/src/lib.rs +++ b/core/lib/tee_verifier/src/lib.rs @@ -13,6 +13,7 @@ use zksync_merkle_tree::{ }; use zksync_multivm::{ interface::{ + pubdata::pubdata_params_to_builder, storage::{InMemoryStorage, ReadStorage, StorageView}, FinishedL1Batch, L2BlockEnv, VmFactory, VmInterface, VmInterfaceExt, VmInterfaceHistoryEnabled, @@ -70,7 +71,12 @@ impl Verify for V1TeeVerifierInput { let storage_view = Rc::new(RefCell::new(StorageView::new(&raw_storage))); let batch_number = self.l1_batch_env.number; - let vm = LegacyVmInstance::new(self.l1_batch_env, self.system_env, storage_view); + let vm = LegacyVmInstance::new( + self.l1_batch_env, + self.system_env, + storage_view, + Some(pubdata_params_to_builder(self.pubdata_params)), + ); let vm_out = execute_vm(self.l2_blocks_execution_data, vm)?; @@ -311,9 +317,9 @@ mod tests { execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: 0, chain_id: Default::default(), - pubdata_params: Default::default(), }, vec![(H256([1; 32]), vec![0, 1, 2, 3, 4])], + Default::default(), ); let tvi = TeeVerifierInput::new(tvi); let serialized = ::serialize(&tvi) diff --git a/core/lib/vm_executor/src/batch/factory.rs b/core/lib/vm_executor/src/batch/factory.rs index 146f0bb4e5c..5256dd6077e 100644 --- a/core/lib/vm_executor/src/batch/factory.rs +++ b/core/lib/vm_executor/src/batch/factory.rs @@ -6,6 +6,7 @@ use tokio::sync::mpsc; use zksync_multivm::{ interface::{ executor::{BatchExecutor, BatchExecutorFactory}, + pubdata::{pubdata_params_to_builder, PubdataBuilder}, storage::{ReadStorage, StoragePtr, StorageView, StorageViewStats}, utils::DivergenceHandler, BatchTransactionExecutionResult, BytecodeCompressionError, CompressedBytecodeInfo, @@ -17,7 +18,7 @@ use zksync_multivm::{ vm_latest::HistoryEnabled, FastVmInstance, LegacyVmInstance, MultiVMTracer, }; -use zksync_types::{vm::FastVmMode, Transaction}; +use zksync_types::{commitment::PubdataParams, vm::FastVmMode, Transaction}; use super::{ executor::{Command, MainBatchExecutor}, @@ -115,6 +116,7 @@ impl BatchExecutorFactory storage: S, l1_batch_params: L1BatchEnv, system_env: SystemEnv, + pubdata_params: PubdataParams, ) -> Box> { // Since we process `BatchExecutor` commands one-by-one (the next command is never enqueued // until a previous command is processed), capacity 1 is enough for the commands channel. @@ -129,8 +131,14 @@ impl BatchExecutorFactory _tracer: PhantomData::, }; - let handle = - tokio::task::spawn_blocking(move || executor.run(storage, l1_batch_params, system_env)); + let handle = tokio::task::spawn_blocking(move || { + executor.run( + storage, + l1_batch_params, + system_env, + Some(pubdata_params_to_builder(pubdata_params)), + ) + }); Box::new(MainBatchExecutor::new(handle, commands_sender)) } } @@ -157,19 +165,27 @@ impl BatchVm { l1_batch_env: L1BatchEnv, system_env: SystemEnv, storage_ptr: StoragePtr>, + pubdata_builder: Option>, mode: FastVmMode, ) -> Self { match mode { - FastVmMode::Old => { - Self::Legacy(LegacyVmInstance::new(l1_batch_env, system_env, storage_ptr)) - } - FastVmMode::New => { - Self::Fast(FastVmInstance::fast(l1_batch_env, system_env, storage_ptr)) - } + FastVmMode::Old => Self::Legacy(LegacyVmInstance::new( + l1_batch_env, + system_env, + storage_ptr, + pubdata_builder, + )), + FastVmMode::New => Self::Fast(FastVmInstance::fast( + l1_batch_env, + system_env, + storage_ptr, + pubdata_builder, + )), FastVmMode::Shadow => Self::Fast(FastVmInstance::shadowed( l1_batch_env, system_env, storage_ptr, + pubdata_builder, )), } } @@ -255,6 +271,7 @@ impl CommandReceiver { storage: S, l1_batch_params: L1BatchEnv, system_env: SystemEnv, + pubdata_builder: Option>, ) -> anyhow::Result> { tracing::info!("Starting executing L1 batch #{}", &l1_batch_params.number); @@ -263,6 +280,7 @@ impl CommandReceiver { l1_batch_params, system_env, storage_view.clone(), + pubdata_builder, self.fast_vm_mode, ); let mut batch_finished = false; diff --git a/core/lib/vm_executor/src/oneshot/block.rs b/core/lib/vm_executor/src/oneshot/block.rs index cab64289e5e..1b5d02f41fb 100644 --- a/core/lib/vm_executor/src/oneshot/block.rs +++ b/core/lib/vm_executor/src/oneshot/block.rs @@ -182,7 +182,7 @@ impl OneshotEnvParameters { ) .await?; - let (system, l1_batch) = self.prepare_env( + let (system, l1_batch, pubdata_params) = self.prepare_env( execution_mode, resolved_block_info, next_block, @@ -192,6 +192,7 @@ impl OneshotEnvParameters { Ok(OneshotEnv { system, l1_batch, + pubdata_params, current_block, }) } @@ -203,7 +204,7 @@ impl OneshotEnvParameters { next_block: L2BlockEnv, fee_input: BatchFeeInput, enforced_base_fee: Option, - ) -> (SystemEnv, L1BatchEnv) { + ) -> (SystemEnv, L1BatchEnv, PubdataParams) { let &Self { operator_account, validation_computational_gas_limit, @@ -222,7 +223,6 @@ impl OneshotEnvParameters { execution_mode, default_validation_computational_gas_limit: validation_computational_gas_limit, chain_id, - pubdata_params: resolved_block_info.pubdata_params, }; let l1_batch_env = L1BatchEnv { previous_batch_hash: None, @@ -233,7 +233,7 @@ impl OneshotEnvParameters { enforced_base_fee, first_l2_block: next_block, }; - (system_env, l1_batch_env) + (system_env, l1_batch_env, resolved_block_info.pubdata_params) } } diff --git a/core/lib/vm_executor/src/oneshot/mod.rs b/core/lib/vm_executor/src/oneshot/mod.rs index cb75f396b5d..e13bacbe5f9 100644 --- a/core/lib/vm_executor/src/oneshot/mod.rs +++ b/core/lib/vm_executor/src/oneshot/mod.rs @@ -17,6 +17,7 @@ use once_cell::sync::OnceCell; use zksync_multivm::{ interface::{ executor::{OneshotExecutor, TransactionValidator}, + pubdata::pubdata_params_to_builder, storage::{ReadStorage, StoragePtr, StorageView, WriteStorage}, tracer::{ValidationError, ValidationParams}, ExecutionResult, OneshotEnv, OneshotTracingParams, OneshotTransactionExecutionResult, @@ -217,6 +218,7 @@ impl VmSandbox { env.system, storage_view.clone(), protocol_version.into_api_vm_version(), + Some(pubdata_params_to_builder(env.pubdata_params)), )); Self { diff --git a/core/lib/vm_executor/src/storage.rs b/core/lib/vm_executor/src/storage.rs index 19514bd5fa8..ec574d7e543 100644 --- a/core/lib/vm_executor/src/storage.rs +++ b/core/lib/vm_executor/src/storage.rs @@ -55,7 +55,7 @@ pub fn l1_batch_params( virtual_blocks: u32, chain_id: L2ChainId, pubdata_params: PubdataParams, -) -> (SystemEnv, L1BatchEnv) { +) -> (SystemEnv, L1BatchEnv, PubdataParams) { ( SystemEnv { zk_porter_available: ZKPORTER_IS_AVAILABLE, @@ -65,7 +65,6 @@ pub fn l1_batch_params( execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: validation_computational_gas_limit, chain_id, - pubdata_params, }, L1BatchEnv { previous_batch_hash: Some(previous_batch_hash), @@ -81,6 +80,7 @@ pub fn l1_batch_params( max_virtual_blocks_to_create: virtual_blocks, }, }, + pubdata_params, ) } @@ -266,7 +266,7 @@ impl L1BatchParamsProvider { first_l2_block_in_batch: &FirstL2BlockInBatch, validation_computational_gas_limit: u32, chain_id: L2ChainId, - ) -> anyhow::Result<(SystemEnv, L1BatchEnv)> { + ) -> anyhow::Result<(SystemEnv, L1BatchEnv, PubdataParams)> { anyhow::ensure!( first_l2_block_in_batch.l1_batch_number > L1BatchNumber(0), "Loading params for genesis L1 batch not supported" @@ -346,7 +346,7 @@ impl L1BatchParamsProvider { number: L1BatchNumber, validation_computational_gas_limit: u32, chain_id: L2ChainId, - ) -> anyhow::Result> { + ) -> anyhow::Result> { let first_l2_block = self .load_first_l2_block_in_batch(storage, number) .await diff --git a/core/lib/vm_interface/Cargo.toml b/core/lib/vm_interface/Cargo.toml index 8bff19ddc47..e771bb131e5 100644 --- a/core/lib/vm_interface/Cargo.toml +++ b/core/lib/vm_interface/Cargo.toml @@ -14,6 +14,8 @@ categories.workspace = true zksync_contracts.workspace = true zksync_system_constants.workspace = true zksync_types.workspace = true +zksync_utils.workspace = true +zksync_mini_merkle_tree.workspace = true anyhow.workspace = true async-trait.workspace = true diff --git a/core/lib/vm_interface/src/executor.rs b/core/lib/vm_interface/src/executor.rs index 119f975fecd..60522ba338a 100644 --- a/core/lib/vm_interface/src/executor.rs +++ b/core/lib/vm_interface/src/executor.rs @@ -3,7 +3,7 @@ use std::fmt; use async_trait::async_trait; -use zksync_types::{l2::L2Tx, Transaction}; +use zksync_types::{commitment::PubdataParams, l2::L2Tx, Transaction}; use crate::{ storage::{ReadStorage, StorageView}, @@ -20,6 +20,7 @@ pub trait BatchExecutorFactory: 'static + Send + fmt::Debug { storage: S, l1_batch_params: L1BatchEnv, system_env: SystemEnv, + pubdata_params: PubdataParams, ) -> Box>; } diff --git a/core/lib/vm_interface/src/lib.rs b/core/lib/vm_interface/src/lib.rs index 645e3e7c856..008c9abb75d 100644 --- a/core/lib/vm_interface/src/lib.rs +++ b/core/lib/vm_interface/src/lib.rs @@ -41,6 +41,7 @@ pub use crate::{ }; pub mod executor; +pub mod pubdata; pub mod storage; mod types; pub mod utils; diff --git a/core/lib/vm_interface/src/pubdata/mod.rs b/core/lib/vm_interface/src/pubdata/mod.rs new file mode 100644 index 00000000000..5e05acd9330 --- /dev/null +++ b/core/lib/vm_interface/src/pubdata/mod.rs @@ -0,0 +1,122 @@ +use std::rc::Rc; + +use zksync_types::{ + commitment::{L1BatchCommitmentMode, PubdataParams}, + ethabi, + l2_to_l1_log::L2ToL1Log, + writes::StateDiffRecord, + Address, ProtocolVersionId, U256, +}; +use zksync_utils::{u256_to_bytes_be, u256_to_h256}; + +use crate::pubdata::{rollup::RollupPubdataBuilder, validium::ValidiumPubdataBuilder}; + +pub mod rollup; +pub mod utils; +pub mod validium; + +#[cfg(test)] +mod tests; + +/// Corresponds to the following solidity event: +/// ```solidity +/// struct L2ToL1Log { +/// uint8 l2ShardId; +/// bool isService; +/// uint16 txNumberInBlock; +/// address sender; +/// bytes32 key; +/// bytes32 value; +/// } +/// ``` +#[derive(Debug, Default, Clone, PartialEq)] +pub struct L1MessengerL2ToL1Log { + 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 { + pub fn packed_encoding(&self) -> Vec { + let mut res: Vec = vec![]; + res.push(self.l2_shard_id); + res.push(self.is_service as u8); + res.extend_from_slice(&self.tx_number_in_block.to_be_bytes()); + res.extend_from_slice(self.sender.as_bytes()); + res.extend(u256_to_bytes_be(&self.key)); + res.extend(u256_to_bytes_be(&self.value)); + res + } +} + +impl From for L2ToL1Log { + fn from(log: L1MessengerL2ToL1Log) -> Self { + L2ToL1Log { + shard_id: log.l2_shard_id, + is_service: log.is_service, + tx_number_in_block: log.tx_number_in_block, + sender: log.sender, + key: u256_to_h256(log.key), + value: u256_to_h256(log.value), + } + } +} + +/// Struct based on which the pubdata blob is formed +#[derive(Debug, Clone, Default)] +pub struct PubdataInput { + pub user_logs: Vec, + pub l2_to_l1_messages: Vec>, + pub published_bytecodes: Vec>, + pub state_diffs: Vec, +} + +/// Trait that encapsulates pubdata building logic. It is implemented for rollup and validium cases. +/// If chains needs custom pubdata format then another implementation should be added. +pub trait PubdataBuilder: std::fmt::Debug { + fn pubdata_params(&self) -> Option { + None + } + + fn l2_da_validator(&self) -> Address; + + fn l1_messenger_operator_input( + &self, + input: PubdataInput, + protocol_version: ProtocolVersionId, + ) -> Vec; + + fn settlement_layer_pubdata( + &self, + input: PubdataInput, + protocol_version: ProtocolVersionId, + ) -> Vec; + + fn bootloader_memory_input( + &self, + input: PubdataInput, + protocol_version: ProtocolVersionId, + ) -> Vec { + let l2_da_validator_address = self.l2_da_validator(); + let operator_input = self.l1_messenger_operator_input(input, protocol_version); + + ethabi::encode(&[ + ethabi::Token::Address(l2_da_validator_address), + ethabi::Token::Bytes(operator_input), + ]) + } +} + +pub fn pubdata_params_to_builder(params: PubdataParams) -> Rc { + match params.pubdata_type { + L1BatchCommitmentMode::Rollup => { + Rc::new(RollupPubdataBuilder::new(params.l2_da_validator_address)) + } + L1BatchCommitmentMode::Validium => { + Rc::new(ValidiumPubdataBuilder::new(params.l2_da_validator_address)) + } + } +} diff --git a/core/lib/vm_interface/src/pubdata/rollup.rs b/core/lib/vm_interface/src/pubdata/rollup.rs new file mode 100644 index 00000000000..b7328f1668f --- /dev/null +++ b/core/lib/vm_interface/src/pubdata/rollup.rs @@ -0,0 +1,136 @@ +use zksync_types::{ + commitment::{L1BatchCommitmentMode, PubdataParams}, + ethabi, + ethabi::{ParamType, Token}, + l2_to_l1_log::l2_to_l1_logs_tree_size, + writes::compress_state_diffs, + Address, ProtocolVersionId, +}; + +use super::{PubdataBuilder, PubdataInput}; +use crate::pubdata::utils::{ + build_chained_bytecode_hash, build_chained_log_hash, build_chained_message_hash, + build_logs_root, encode_user_logs, +}; + +#[derive(Debug, Clone, Copy)] +pub struct RollupPubdataBuilder { + pub l2_da_validator: Address, +} + +impl RollupPubdataBuilder { + pub fn new(l2_da_validator: Address) -> Self { + Self { l2_da_validator } + } +} + +impl PubdataBuilder for RollupPubdataBuilder { + fn pubdata_params(&self) -> Option { + Some(PubdataParams { + l2_da_validator_address: self.l2_da_validator, + pubdata_type: L1BatchCommitmentMode::Rollup, + }) + } + + fn l2_da_validator(&self) -> Address { + self.l2_da_validator + } + + fn l1_messenger_operator_input( + &self, + input: PubdataInput, + protocol_version: ProtocolVersionId, + ) -> Vec { + if protocol_version.is_pre_gateway() { + let mut operator_input = vec![]; + extend_from_pubdata_input(&mut operator_input, &input); + + // Extend with uncompressed state diffs. + operator_input.extend((input.state_diffs.len() as u32).to_be_bytes()); + for state_diff in &input.state_diffs { + operator_input.extend(state_diff.encode_padded()); + } + + operator_input + } else { + let mut pubdata = vec![]; + extend_from_pubdata_input(&mut pubdata, &input); + + // Extend with uncompressed state diffs. + pubdata.extend((input.state_diffs.len() as u32).to_be_bytes()); + for state_diff in &input.state_diffs { + pubdata.extend(state_diff.encode_padded()); + } + + let chained_log_hash = build_chained_log_hash(&input.user_logs); + let log_root_hash = + build_logs_root(&input.user_logs, l2_to_l1_logs_tree_size(protocol_version)); + let chained_msg_hash = build_chained_message_hash(&input.l2_to_l1_messages); + let chained_bytecodes_hash = build_chained_bytecode_hash(&input.published_bytecodes); + + let l2_da_header = vec![ + Token::FixedBytes(chained_log_hash), + Token::FixedBytes(log_root_hash), + Token::FixedBytes(chained_msg_hash), + Token::FixedBytes(chained_bytecodes_hash), + Token::Bytes(pubdata), + ]; + + // Selector of `IL2DAValidator::validatePubdata`. + let func_selector = ethabi::short_signature( + "validatePubdata", + &[ + ParamType::FixedBytes(32), + ParamType::FixedBytes(32), + ParamType::FixedBytes(32), + ParamType::FixedBytes(32), + ParamType::Bytes, + ], + ); + + [func_selector.to_vec(), ethabi::encode(&l2_da_header)].concat() + } + } + + fn settlement_layer_pubdata( + &self, + input: PubdataInput, + _protocol_version: ProtocolVersionId, + ) -> Vec { + let mut pubdata = vec![]; + extend_from_pubdata_input(&mut pubdata, &input); + + pubdata + } +} + +fn extend_from_pubdata_input(buffer: &mut Vec, pubdata_input: &PubdataInput) { + let PubdataInput { + user_logs, + l2_to_l1_messages, + published_bytecodes, + state_diffs, + } = pubdata_input; + + // Adding user L2->L1 logs. + buffer.extend(encode_user_logs(user_logs)); + + // Encoding L2->L1 messages + // Format: `[(numberOfMessages as u32) || (messages[1].len() as u32) || messages[1] || ... || (messages[n].len() as u32) || messages[n]]` + buffer.extend((l2_to_l1_messages.len() as u32).to_be_bytes()); + for message in l2_to_l1_messages { + buffer.extend((message.len() as u32).to_be_bytes()); + buffer.extend(message); + } + // Encoding bytecodes + // Format: `[(numberOfBytecodes as u32) || (bytecodes[1].len() as u32) || bytecodes[1] || ... || (bytecodes[n].len() as u32) || bytecodes[n]]` + buffer.extend((published_bytecodes.len() as u32).to_be_bytes()); + for bytecode in published_bytecodes { + buffer.extend((bytecode.len() as u32).to_be_bytes()); + buffer.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()); + buffer.extend(state_diffs_compressed); +} diff --git a/core/lib/vm_interface/src/pubdata/tests.rs b/core/lib/vm_interface/src/pubdata/tests.rs new file mode 100644 index 00000000000..8877116085c --- /dev/null +++ b/core/lib/vm_interface/src/pubdata/tests.rs @@ -0,0 +1,121 @@ +use zksync_system_constants::{ACCOUNT_CODE_STORAGE_ADDRESS, BOOTLOADER_ADDRESS}; +use zksync_types::{writes::StateDiffRecord, Address, ProtocolVersionId}; +use zksync_utils::u256_to_h256; + +use super::{L1MessengerL2ToL1Log, PubdataBuilder, PubdataInput}; +use crate::pubdata::{rollup::RollupPubdataBuilder, validium::ValidiumPubdataBuilder}; + +fn mock_input() -> PubdataInput { + // 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("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").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(), + }, + ]; + + PubdataInput { + user_logs, + l2_to_l1_messages, + published_bytecodes, + state_diffs, + } +} + +#[test] +fn test_rollup_pubdata_building() { + let input = mock_input(); + + let rollup_pubdata_builder = RollupPubdataBuilder::new(Address::zero()); + + let actual = rollup_pubdata_builder + .l1_messenger_operator_input(input.clone(), ProtocolVersionId::Version24); + let expected = "00000001000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000100000004deadbeef0000000100000060bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb0100002a040001000000000000000000000000000000000000000000000000000000000000007e090e0000000c0901000000020000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000007d000000000000000c000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + assert_eq!( + &hex::encode(actual), + expected, + "mismatch for `l1_messenger_operator_input` (pre gateway)" + ); + + let actual = rollup_pubdata_builder + .settlement_layer_pubdata(input.clone(), ProtocolVersionId::Version24); + let expected = "00000001000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000100000004deadbeef0000000100000060bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb0100002a040001000000000000000000000000000000000000000000000000000000000000007e090e0000000c0901"; + assert_eq!( + &hex::encode(actual), + expected, + "mismatch for `settlement_layer_pubdata` (pre gateway)" + ); + + let actual = rollup_pubdata_builder + .l1_messenger_operator_input(input.clone(), ProtocolVersionId::Version26); + let expected = "89f9a07233e608561d90f7c4e7bcea24d718e425a6bd6c8eefb48a334366143694c75fae278944d856d68e33bbd32937cb3a1ea35cbf7d6eeeb1150f500dd0d64d0efe420d6dafe5897eab2fc27b2e47af303397ed285ace146d836d042717b0a3dc4b28a603a33b28ce1d5c52c593a46a15a99f1afa1c1d92715284288958fd54a93de700000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000032300000001000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000100000004deadbeef0000000100000060bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb0100002a040001000000000000000000000000000000000000000000000000000000000000007e090e0000000c0901000000020000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000007d000000000000000c000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + assert_eq!( + &hex::encode(actual), + expected, + "mismatch for `l1_messenger_operator_input` (post gateway)" + ); + + let actual = rollup_pubdata_builder + .settlement_layer_pubdata(input.clone(), ProtocolVersionId::Version26); + let expected = "00000001000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000100000004deadbeef0000000100000060bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb0100002a040001000000000000000000000000000000000000000000000000000000000000007e090e0000000c0901"; + assert_eq!( + &hex::encode(actual), + expected, + "mismatch for `settlement_layer_pubdata` (post gateway)" + ); +} + +#[test] +fn test_validium_pubdata_building() { + let input = mock_input(); + + let validium_pubdata_builder = ValidiumPubdataBuilder::new(Address::zero()); + + let actual = validium_pubdata_builder + .l1_messenger_operator_input(input.clone(), ProtocolVersionId::Version26); + let expected = "89f9a07233e608561d90f7c4e7bcea24d718e425a6bd6c8eefb48a334366143694c75fae278944d856d68e33bbd32937cb3a1ea35cbf7d6eeeb1150f500dd0d64d0efe420d6dafe5897eab2fc27b2e47af303397ed285ace146d836d042717b0a3dc4b28a603a33b28ce1d5c52c593a46a15a99f1afa1c1d92715284288958fd54a93de700000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000005c000000010000000000000000000000000000000000000000000080010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000"; + assert_eq!( + &hex::encode(actual), + expected, + "mismatch for `l1_messenger_operator_input`" + ); + + let actual = validium_pubdata_builder + .settlement_layer_pubdata(input.clone(), ProtocolVersionId::Version26); + let expected = "fa96e2436e6fb4d668f5a06681a7c53fcb199b2747ee624ee52a13e85aac5f1e"; + assert_eq!( + &hex::encode(actual), + expected, + "mismatch for `settlement_layer_pubdata`" + ); +} diff --git a/core/lib/vm_interface/src/pubdata/utils.rs b/core/lib/vm_interface/src/pubdata/utils.rs new file mode 100644 index 00000000000..8ed34962c3a --- /dev/null +++ b/core/lib/vm_interface/src/pubdata/utils.rs @@ -0,0 +1,70 @@ +use zksync_mini_merkle_tree::MiniMerkleTree; +use zksync_types::web3::keccak256; +use zksync_utils::bytecode::hash_bytecode; + +use crate::pubdata::L1MessengerL2ToL1Log; + +pub(crate) fn build_chained_log_hash(user_logs: &[L1MessengerL2ToL1Log]) -> Vec { + let mut chained_log_hash = vec![0u8; 32]; + + for log in user_logs { + let log_bytes = log.packed_encoding(); + let hash = keccak256(&log_bytes); + + chained_log_hash = keccak256(&[chained_log_hash, hash.to_vec()].concat()).to_vec(); + } + + chained_log_hash +} + +pub(crate) fn build_logs_root( + user_logs: &[L1MessengerL2ToL1Log], + l2_to_l1_logs_tree_size: usize, +) -> Vec { + let logs = user_logs.iter().map(|log| { + let encoded = log.packed_encoding(); + let mut slice = [0u8; 88]; + slice.copy_from_slice(&encoded); + slice + }); + MiniMerkleTree::new(logs, Some(l2_to_l1_logs_tree_size)) + .merkle_root() + .as_bytes() + .to_vec() +} + +pub(crate) fn build_chained_message_hash(l2_to_l1_messages: &[Vec]) -> Vec { + let mut chained_msg_hash = vec![0u8; 32]; + + for msg in l2_to_l1_messages { + let hash = keccak256(msg); + + chained_msg_hash = keccak256(&[chained_msg_hash, hash.to_vec()].concat()).to_vec(); + } + + chained_msg_hash +} + +pub(crate) fn build_chained_bytecode_hash(published_bytecodes: &[Vec]) -> Vec { + let mut chained_bytecode_hash = vec![0u8; 32]; + + for bytecode in published_bytecodes { + let hash = hash_bytecode(bytecode).to_fixed_bytes(); + + chained_bytecode_hash = + keccak256(&[chained_bytecode_hash, hash.to_vec()].concat()).to_vec(); + } + + chained_bytecode_hash +} + +pub(crate) fn encode_user_logs(user_logs: &[L1MessengerL2ToL1Log]) -> Vec { + // Encoding user L2->L1 logs. + // Format: `[(numberOfL2ToL1Logs as u32) || l2tol1logs[1] || ... || l2tol1logs[n]]` + let mut result = vec![]; + result.extend((user_logs.len() as u32).to_be_bytes()); + for l2tol1log in user_logs { + result.extend(l2tol1log.packed_encoding()); + } + result +} diff --git a/core/lib/vm_interface/src/pubdata/validium.rs b/core/lib/vm_interface/src/pubdata/validium.rs new file mode 100644 index 00000000000..f0d8c9d0eb9 --- /dev/null +++ b/core/lib/vm_interface/src/pubdata/validium.rs @@ -0,0 +1,103 @@ +use zksync_types::{ + commitment::{L1BatchCommitmentMode, PubdataParams}, + ethabi, + ethabi::{ParamType, Token}, + l2_to_l1_log::l2_to_l1_logs_tree_size, + web3::keccak256, + Address, ProtocolVersionId, +}; + +use crate::pubdata::{ + utils::{ + build_chained_bytecode_hash, build_chained_log_hash, build_chained_message_hash, + build_logs_root, encode_user_logs, + }, + PubdataBuilder, PubdataInput, +}; + +#[derive(Debug, Clone, Copy)] +pub struct ValidiumPubdataBuilder { + pub l2_da_validator: Address, +} + +impl ValidiumPubdataBuilder { + pub fn new(l2_da_validator: Address) -> Self { + Self { l2_da_validator } + } +} + +impl PubdataBuilder for ValidiumPubdataBuilder { + fn pubdata_params(&self) -> Option { + Some(PubdataParams { + l2_da_validator_address: self.l2_da_validator, + pubdata_type: L1BatchCommitmentMode::Validium, + }) + } + + fn l2_da_validator(&self) -> Address { + self.l2_da_validator + } + + fn l1_messenger_operator_input( + &self, + input: PubdataInput, + protocol_version: ProtocolVersionId, + ) -> Vec { + assert!( + !protocol_version.is_pre_gateway(), + "ValidiumPubdataBuilder must not be called for pre gateway" + ); + + let mut pubdata = vec![]; + pubdata.extend(encode_user_logs(&input.user_logs)); + + let chained_log_hash = build_chained_log_hash(&input.user_logs); + let log_root_hash = + build_logs_root(&input.user_logs, l2_to_l1_logs_tree_size(protocol_version)); + let chained_msg_hash = build_chained_message_hash(&input.l2_to_l1_messages); + let chained_bytecodes_hash = build_chained_bytecode_hash(&input.published_bytecodes); + + let l2_da_header = vec![ + Token::FixedBytes(chained_log_hash), + Token::FixedBytes(log_root_hash), + Token::FixedBytes(chained_msg_hash), + Token::FixedBytes(chained_bytecodes_hash), + Token::Bytes(pubdata), + ]; + + // Selector of `IL2DAValidator::validatePubdata`. + let func_selector = ethabi::short_signature( + "validatePubdata", + &[ + ParamType::FixedBytes(32), + ParamType::FixedBytes(32), + ParamType::FixedBytes(32), + ParamType::FixedBytes(32), + ParamType::Bytes, + ], + ); + + [func_selector.to_vec(), ethabi::encode(&l2_da_header)] + .concat() + .to_vec() + } + + fn settlement_layer_pubdata( + &self, + input: PubdataInput, + protocol_version: ProtocolVersionId, + ) -> Vec { + assert!( + !protocol_version.is_pre_gateway(), + "ValidiumPubdataBuilder must not be called for pre gateway" + ); + + let state_diffs_packed = input + .state_diffs + .into_iter() + .flat_map(|diff| diff.encode_padded()) + .collect::>(); + + keccak256(&state_diffs_packed).to_vec() + } +} diff --git a/core/lib/vm_interface/src/types/inputs/mod.rs b/core/lib/vm_interface/src/types/inputs/mod.rs index 24f58ae72f1..78e653a7f26 100644 --- a/core/lib/vm_interface/src/types/inputs/mod.rs +++ b/core/lib/vm_interface/src/types/inputs/mod.rs @@ -1,5 +1,6 @@ use zksync_types::{ - l2::L2Tx, ExecuteTransactionCommon, Nonce, PackedEthSignature, Transaction, U256, + commitment::PubdataParams, l2::L2Tx, ExecuteTransactionCommon, Nonce, PackedEthSignature, + Transaction, U256, }; pub use self::{ @@ -21,6 +22,8 @@ pub struct OneshotEnv { pub system: SystemEnv, /// Part of the environment specific to an L1 batch. pub l1_batch: L1BatchEnv, + /// Pubdata building parameters. + pub pubdata_params: PubdataParams, /// Part of the environment representing the current L2 block. Can be used to override storage slots /// in the system context contract, which are set from `L1BatchEnv.first_l2_block` by default. pub current_block: Option, diff --git a/core/lib/vm_interface/src/types/inputs/system_env.rs b/core/lib/vm_interface/src/types/inputs/system_env.rs index 67d555f9bc0..5a0496752d5 100644 --- a/core/lib/vm_interface/src/types/inputs/system_env.rs +++ b/core/lib/vm_interface/src/types/inputs/system_env.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use serde::{Deserialize, Serialize}; use zksync_contracts::BaseSystemContracts; -use zksync_types::{commitment::PubdataParams, L2ChainId, ProtocolVersionId}; +use zksync_types::{L2ChainId, ProtocolVersionId}; /// Params related to the execution process, not batch it self #[derive(Clone, PartialEq, Serialize, Deserialize)] @@ -15,7 +15,6 @@ pub struct SystemEnv { pub execution_mode: TxExecutionMode, pub default_validation_computational_gas_limit: u32, pub chain_id: L2ChainId, - pub pubdata_params: PubdataParams, } impl Debug for SystemEnv { @@ -34,7 +33,6 @@ impl Debug for SystemEnv { ) .field("execution_mode", &self.execution_mode) .field("chain_id", &self.chain_id) - .field("pubdata_params", &self.pubdata_params) .finish() } } diff --git a/core/lib/vm_interface/src/utils/dump.rs b/core/lib/vm_interface/src/utils/dump.rs index 5dc2351dcf7..034793b0907 100644 --- a/core/lib/vm_interface/src/utils/dump.rs +++ b/core/lib/vm_interface/src/utils/dump.rs @@ -1,9 +1,13 @@ -use std::collections::HashMap; +use std::{collections::HashMap, rc::Rc}; use serde::{Deserialize, Serialize}; -use zksync_types::{block::L2BlockExecutionData, L1BatchNumber, L2BlockNumber, Transaction, H256}; +use zksync_types::{ + block::L2BlockExecutionData, commitment::PubdataParams, L1BatchNumber, L2BlockNumber, + Transaction, H256, +}; use crate::{ + pubdata::{pubdata_params_to_builder, PubdataBuilder}, storage::{ReadStorage, StoragePtr, StorageSnapshot, StorageView}, BytecodeCompressionResult, FinishedL1Batch, L1BatchEnv, L2BlockEnv, SystemEnv, VmExecutionMode, VmExecutionResultAndLogs, VmFactory, VmInterface, VmInterfaceExt, VmInterfaceHistoryEnabled, @@ -54,6 +58,7 @@ pub struct VmDump { pub system_env: SystemEnv, pub l2_blocks: Vec, pub storage: StorageSnapshot, + pub pubdata_params: Option, } impl VmDump { @@ -73,10 +78,20 @@ impl VmDump { #[doc(hidden)] // too low-level pub fn play_back_custom( self, - create_vm: impl FnOnce(L1BatchEnv, SystemEnv, StoragePtr>) -> Vm, + create_vm: impl FnOnce( + L1BatchEnv, + SystemEnv, + StoragePtr>, + Option>, + ) -> Vm, ) -> Vm { let storage = StorageView::new(self.storage).to_rc_ptr(); - let mut vm = create_vm(self.l1_batch_env, self.system_env, storage); + let mut vm = create_vm( + self.l1_batch_env, + self.system_env, + storage, + self.pubdata_params.map(pubdata_params_to_builder), + ); for (i, l2_block) in self.l2_blocks.into_iter().enumerate() { if i > 0 { @@ -118,6 +133,7 @@ pub(super) struct DumpingVm { system_env: SystemEnv, l2_blocks: Vec, l2_blocks_snapshot: Option, + pubdata_builder: Option>, } impl DumpingVm { @@ -135,6 +151,10 @@ impl DumpingVm { system_env: self.system_env.clone(), l2_blocks: self.l2_blocks.clone(), storage: create_storage_snapshot(&self.storage, self.inner.used_contract_hashes()), + pubdata_params: self + .pubdata_builder + .clone() + .map(|p| p.pubdata_params().expect("pubdata builder is not dumpable")), } } } @@ -231,8 +251,14 @@ where l1_batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr>, + pubdata_builder: Option>, ) -> Self { - let inner = Vm::new(l1_batch_env.clone(), system_env.clone(), storage.clone()); + let inner = Vm::new( + l1_batch_env.clone(), + system_env.clone(), + storage.clone(), + pubdata_builder.clone(), + ); let first_block = L2BlockExecutionData { number: L2BlockNumber(l1_batch_env.first_l2_block.number), timestamp: l1_batch_env.first_l2_block.timestamp, @@ -247,6 +273,7 @@ where l2_blocks_snapshot: None, storage, inner, + pubdata_builder, } } } diff --git a/core/lib/vm_interface/src/utils/shadow.rs b/core/lib/vm_interface/src/utils/shadow.rs index 2819e54e9a7..6ebc4edbe21 100644 --- a/core/lib/vm_interface/src/utils/shadow.rs +++ b/core/lib/vm_interface/src/utils/shadow.rs @@ -2,6 +2,7 @@ use std::{ cell::RefCell, collections::{BTreeMap, BTreeSet}, fmt, + rc::Rc, sync::Arc, }; @@ -9,6 +10,7 @@ use zksync_types::{StorageKey, StorageLog, StorageLogWithPreviousValue, Transact use super::dump::{DumpingVm, VmDump}; use crate::{ + pubdata::PubdataBuilder, storage::{ReadStorage, StoragePtr, StorageView}, BytecodeCompressionResult, CurrentExecutionState, FinishedL1Batch, L1BatchEnv, L2BlockEnv, SystemEnv, VmExecutionMode, VmExecutionResultAndLogs, VmFactory, VmInterface, @@ -119,12 +121,23 @@ where system_env: SystemEnv, storage: StoragePtr>, shadow_storage: StoragePtr, + pubdata_builder: Option>, ) -> Self where Shadow: VmFactory, { - let main = DumpingVm::new(batch_env.clone(), system_env.clone(), storage.clone()); - let shadow = Shadow::new(batch_env.clone(), system_env.clone(), shadow_storage); + let main = DumpingVm::new( + batch_env.clone(), + system_env.clone(), + storage, + pubdata_builder.clone(), + ); + let shadow = Shadow::new( + batch_env.clone(), + system_env.clone(), + shadow_storage, + pubdata_builder, + ); let shadow = VmWithReporting { vm: shadow, divergence_handler: DivergenceHandler::default(), @@ -146,8 +159,15 @@ where batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr>, + pubdata_builder: Option>, ) -> Self { - Self::with_custom_shadow(batch_env, system_env, storage.clone(), storage) + Self::with_custom_shadow( + batch_env, + system_env, + storage.clone(), + storage, + pubdata_builder, + ) } } diff --git a/core/lib/vm_interface/src/vm.rs b/core/lib/vm_interface/src/vm.rs index 90ae76be805..52d7264edc8 100644 --- a/core/lib/vm_interface/src/vm.rs +++ b/core/lib/vm_interface/src/vm.rs @@ -11,11 +11,13 @@ //! Generally speaking, in most cases, the tracer dispatcher is a wrapper around `Vec>`, //! where `VmTracer` is a trait implemented for a specific VM version. +use std::rc::Rc; + use zksync_types::{Transaction, H256}; use crate::{ - storage::StoragePtr, BytecodeCompressionResult, FinishedL1Batch, L1BatchEnv, L2BlockEnv, - SystemEnv, VmExecutionMode, VmExecutionResultAndLogs, VmMemoryMetrics, + pubdata::PubdataBuilder, storage::StoragePtr, BytecodeCompressionResult, FinishedL1Batch, + L1BatchEnv, L2BlockEnv, SystemEnv, VmExecutionMode, VmExecutionResultAndLogs, VmMemoryMetrics, }; pub trait VmInterface { @@ -78,7 +80,12 @@ impl VmInterfaceExt for T {} /// Encapsulates creating VM instance based on the provided environment. pub trait VmFactory: VmInterface { /// Creates a new VM instance. - fn new(batch_env: L1BatchEnv, system_env: SystemEnv, storage: StoragePtr) -> Self; + fn new( + batch_env: L1BatchEnv, + system_env: SystemEnv, + storage: StoragePtr, + pubdata_builder: Option>, + ) -> Self; } /// Methods of VM requiring history manipulations. diff --git a/core/node/node_sync/src/external_io.rs b/core/node/node_sync/src/external_io.rs index 6075ff048bf..82c22a6f269 100644 --- a/core/node/node_sync/src/external_io.rs +++ b/core/node/node_sync/src/external_io.rs @@ -185,7 +185,7 @@ impl StateKeeperIO for ExternalIO { pending_l2_block_header.set_protocol_version(protocol_version); } - let (system_env, l1_batch_env) = self + let (system_env, l1_batch_env, pubdata_params) = self .l1_batch_params_provider .load_l1_batch_params( &mut storage, @@ -200,7 +200,7 @@ impl StateKeeperIO for ExternalIO { cursor.l1_batch ) })?; - let data = load_pending_batch(&mut storage, system_env, l1_batch_env) + let data = load_pending_batch(&mut storage, system_env, l1_batch_env, pubdata_params) .await .with_context(|| { format!( diff --git a/core/node/proof_data_handler/src/tests.rs b/core/node/proof_data_handler/src/tests.rs index 4319fce6216..fb6712da4c9 100644 --- a/core/node/proof_data_handler/src/tests.rs +++ b/core/node/proof_data_handler/src/tests.rs @@ -67,9 +67,9 @@ async fn request_tee_proof_inputs() { execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: 0, chain_id: Default::default(), - pubdata_params: Default::default(), }, vec![(H256([1; 32]), vec![0, 1, 2, 3, 4])], + Default::default(), ); let tvi = TeeVerifierInput::V1(tvi); diff --git a/core/node/state_keeper/src/executor/tests/tester.rs b/core/node/state_keeper/src/executor/tests/tester.rs index 7a1871dbfea..4c65953e9fc 100644 --- a/core/node/state_keeper/src/executor/tests/tester.rs +++ b/core/node/state_keeper/src/executor/tests/tester.rs @@ -25,6 +25,7 @@ use zksync_state::{OwnedStorage, ReadStorageFactory, RocksdbStorageOptions}; use zksync_test_account::{Account, DeployContractsTx, TxType}; use zksync_types::{ block::L2BlockHasher, + commitment::PubdataParams, ethabi::Token, protocol_version::ProtocolSemanticVersion, snapshots::{SnapshotRecoveryStatus, SnapshotStorageLog}, @@ -104,10 +105,9 @@ impl Tester { &mut self, storage_type: StorageType, ) -> Box> { - let (l1_batch_env, system_env) = self.default_batch_params(); + let (l1_batch_env, system_env, pubdata_params) = self.default_batch_params(); match storage_type { StorageType::AsyncRocksdbCache => { - let (l1_batch_env, system_env) = self.default_batch_params(); let (state_keeper_storage, task) = AsyncRocksdbCache::new( self.pool(), self.state_keeper_db_path(), @@ -122,6 +122,7 @@ impl Tester { Arc::new(state_keeper_storage), l1_batch_env, system_env, + pubdata_params, ) .await } @@ -133,12 +134,18 @@ impl Tester { )), l1_batch_env, system_env, + pubdata_params, ) .await } StorageType::Postgres => { - self.create_batch_executor_inner(Arc::new(self.pool()), l1_batch_env, system_env) - .await + self.create_batch_executor_inner( + Arc::new(self.pool()), + l1_batch_env, + system_env, + pubdata_params, + ) + .await } } } @@ -148,6 +155,7 @@ impl Tester { storage_factory: Arc, l1_batch_env: L1BatchEnv, system_env: SystemEnv, + pubdata_params: PubdataParams, ) -> Box> { let (_stop_sender, stop_receiver) = watch::channel(false); let storage = storage_factory @@ -158,11 +166,11 @@ impl Tester { if self.config.trace_calls { let mut executor = MainBatchExecutorFactory::::new(false); executor.set_fast_vm_mode(self.config.fast_vm_mode); - executor.init_batch(storage, l1_batch_env, system_env) + executor.init_batch(storage, l1_batch_env, system_env, pubdata_params) } else { let mut executor = MainBatchExecutorFactory::<()>::new(false); executor.set_fast_vm_mode(self.config.fast_vm_mode); - executor.init_batch(storage, l1_batch_env, system_env) + executor.init_batch(storage, l1_batch_env, system_env, pubdata_params) } } @@ -212,7 +220,7 @@ impl Tester { snapshot: &SnapshotRecoveryStatus, ) -> Box> { let current_timestamp = snapshot.l2_block_timestamp + 1; - let (mut l1_batch_env, system_env) = + let (mut l1_batch_env, system_env, pubdata_params) = self.batch_params(snapshot.l1_batch_number + 1, current_timestamp); l1_batch_env.previous_batch_hash = Some(snapshot.l1_batch_root_hash); l1_batch_env.first_l2_block = L2BlockEnv { @@ -222,11 +230,11 @@ impl Tester { max_virtual_blocks_to_create: 1, }; - self.create_batch_executor_inner(storage_factory, l1_batch_env, system_env) + self.create_batch_executor_inner(storage_factory, l1_batch_env, system_env, pubdata_params) .await } - pub(super) fn default_batch_params(&self) -> (L1BatchEnv, SystemEnv) { + pub(super) fn default_batch_params(&self) -> (L1BatchEnv, SystemEnv, PubdataParams) { // Not really important for the batch executor - it operates over a single batch. self.batch_params(L1BatchNumber(1), 100) } @@ -236,7 +244,7 @@ impl Tester { &self, l1_batch_number: L1BatchNumber, timestamp: u64, - ) -> (L1BatchEnv, SystemEnv) { + ) -> (L1BatchEnv, SystemEnv, PubdataParams) { let mut system_params = default_system_env(); if let Some(vm_gas_limit) = self.config.vm_gas_limit { system_params.bootloader_gas_limit = vm_gas_limit; @@ -245,7 +253,7 @@ impl Tester { self.config.validation_computational_gas_limit; let mut batch_params = default_l1_batch_env(l1_batch_number.0, timestamp, self.fee_account); batch_params.previous_batch_hash = Some(H256::zero()); // Not important in this context. - (batch_params, system_params) + (batch_params, system_params, PubdataParams::default()) } /// Performs the genesis in the storage. diff --git a/core/node/state_keeper/src/io/common/mod.rs b/core/node/state_keeper/src/io/common/mod.rs index 6bd881414a2..867ffa7fb37 100644 --- a/core/node/state_keeper/src/io/common/mod.rs +++ b/core/node/state_keeper/src/io/common/mod.rs @@ -3,7 +3,7 @@ use std::time::Duration; use anyhow::Context; use zksync_dal::{Connection, Core, CoreDal}; use zksync_multivm::interface::{L1BatchEnv, SystemEnv}; -use zksync_types::{L1BatchNumber, L2BlockNumber, H256}; +use zksync_types::{commitment::PubdataParams, L1BatchNumber, L2BlockNumber, H256}; use super::PendingBatchData; @@ -85,6 +85,7 @@ pub async fn load_pending_batch( storage: &mut Connection<'_, Core>, system_env: SystemEnv, l1_batch_env: L1BatchEnv, + pubdata_params: PubdataParams, ) -> anyhow::Result { let pending_l2_blocks = storage .transactions_dal() @@ -104,6 +105,7 @@ pub async fn load_pending_batch( Ok(PendingBatchData { l1_batch_env, system_env, + pubdata_params, pending_l2_blocks, }) } diff --git a/core/node/state_keeper/src/io/common/tests.rs b/core/node/state_keeper/src/io/common/tests.rs index b2a24acb495..ec9f906b1cd 100644 --- a/core/node/state_keeper/src/io/common/tests.rs +++ b/core/node/state_keeper/src/io/common/tests.rs @@ -318,7 +318,7 @@ async fn loading_pending_batch_with_genesis() { .await; let provider = L1BatchParamsProvider::new(&mut storage).await.unwrap(); - let (system_env, l1_batch_env) = provider + let (system_env, l1_batch_env, pubdata_params) = provider .load_l1_batch_env( &mut storage, L1BatchNumber(1), @@ -331,7 +331,7 @@ async fn loading_pending_batch_with_genesis() { assert_eq!(l1_batch_env.first_l2_block.number, 1); - let pending_batch = load_pending_batch(&mut storage, system_env, l1_batch_env) + let pending_batch = load_pending_batch(&mut storage, system_env, l1_batch_env, pubdata_params) .await .unwrap(); @@ -396,7 +396,7 @@ async fn loading_pending_batch_after_snapshot_recovery() { .await; let provider = L1BatchParamsProvider::new(&mut storage).await.unwrap(); - let (system_env, l1_batch_env) = provider + let (system_env, l1_batch_env, pubdata_params) = provider .load_l1_batch_env( &mut storage, snapshot_recovery.l1_batch_number + 1, @@ -406,7 +406,7 @@ async fn loading_pending_batch_after_snapshot_recovery() { .await .unwrap() .expect("no L1 batch"); - let pending_batch = load_pending_batch(&mut storage, system_env, l1_batch_env) + let pending_batch = load_pending_batch(&mut storage, system_env, l1_batch_env, pubdata_params) .await .unwrap(); diff --git a/core/node/state_keeper/src/io/mempool.rs b/core/node/state_keeper/src/io/mempool.rs index 1114000e8d1..4c673ba111c 100644 --- a/core/node/state_keeper/src/io/mempool.rs +++ b/core/node/state_keeper/src/io/mempool.rs @@ -101,7 +101,7 @@ impl StateKeeperIO for MempoolIO { L2BlockSealProcess::clear_pending_l2_block(&mut storage, cursor.next_l2_block - 1).await?; - let Some((system_env, l1_batch_env)) = self + let Some((system_env, l1_batch_env, pubdata_params)) = self .l1_batch_params_provider .load_l1_batch_env( &mut storage, @@ -113,38 +113,29 @@ impl StateKeeperIO for MempoolIO { else { return Ok((cursor, None)); }; - let pending_batch_data = load_pending_batch(&mut storage, system_env, l1_batch_env) - .await - .with_context(|| { - format!( - "failed loading data for re-execution for pending L1 batch #{}", - cursor.l1_batch - ) - })?; + let pending_batch_data = + load_pending_batch(&mut storage, system_env, l1_batch_env, pubdata_params) + .await + .with_context(|| { + format!( + "failed loading data for re-execution for pending L1 batch #{}", + cursor.l1_batch + ) + })?; - let PendingBatchData { - l1_batch_env, - system_env, - pending_l2_blocks, - } = pending_batch_data; // Initialize the filter for the transactions that come after the pending batch. // We use values from the pending block to match the filter with one used before the restart. - let (base_fee, gas_per_pubdata) = - derive_base_fee_and_gas_per_pubdata(l1_batch_env.fee_input, system_env.version.into()); + let (base_fee, gas_per_pubdata) = derive_base_fee_and_gas_per_pubdata( + pending_batch_data.l1_batch_env.fee_input, + pending_batch_data.system_env.version.into(), + ); self.filter = L2TxFilter { - fee_input: l1_batch_env.fee_input, + fee_input: pending_batch_data.l1_batch_env.fee_input, fee_per_gas: base_fee, gas_per_pubdata: gas_per_pubdata as u32, }; - Ok(( - cursor, - Some(PendingBatchData { - l1_batch_env, - system_env, - pending_l2_blocks, - }), - )) + Ok((cursor, Some(pending_batch_data))) } async fn wait_for_new_batch_params( diff --git a/core/node/state_keeper/src/io/mod.rs b/core/node/state_keeper/src/io/mod.rs index 947d05ec800..1228b086527 100644 --- a/core/node/state_keeper/src/io/mod.rs +++ b/core/node/state_keeper/src/io/mod.rs @@ -39,6 +39,7 @@ pub struct PendingBatchData { /// (e.g. timestamp) are the same, so transaction would have the same result after re-execution. pub(crate) l1_batch_env: L1BatchEnv, pub(crate) system_env: SystemEnv, + pub(crate) pubdata_params: PubdataParams, /// List of L2 blocks and corresponding transactions that were executed within batch. pub(crate) pending_l2_blocks: Vec, } @@ -82,7 +83,7 @@ impl L1BatchParams { contracts: BaseSystemContracts, cursor: &IoCursor, previous_batch_hash: H256, - ) -> (SystemEnv, L1BatchEnv) { + ) -> (SystemEnv, L1BatchEnv, PubdataParams) { l1_batch_params( cursor.l1_batch, self.operator_address, diff --git a/core/node/state_keeper/src/io/persistence.rs b/core/node/state_keeper/src/io/persistence.rs index 28dd0ba7cc2..d48c4831dcf 100644 --- a/core/node/state_keeper/src/io/persistence.rs +++ b/core/node/state_keeper/src/io/persistence.rs @@ -487,7 +487,8 @@ mod tests { async fn execute_mock_batch(output_handler: &mut OutputHandler) -> H256 { let l1_batch_env = default_l1_batch_env(1, 1, Address::random()); - let mut updates = UpdatesManager::new(&l1_batch_env, &default_system_env()); + let mut updates = + UpdatesManager::new(&l1_batch_env, &default_system_env(), Default::default()); let tx = create_transaction(10, 100); let tx_hash = tx.hash(); diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 4e2f8aa8af3..942a9ddbe02 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -446,13 +446,13 @@ async fn l2_block_processing_after_snapshot_recovery(commitment_mode: L1BatchCom .await .unwrap() .expect("no batch params generated"); - let (system_env, l1_batch_env) = l1_batch_params.into_env( + let (system_env, l1_batch_env, pubdata_params) = l1_batch_params.into_env( L2ChainId::default(), BASE_SYSTEM_CONTRACTS.clone(), &cursor, previous_batch_hash, ); - let mut updates = UpdatesManager::new(&l1_batch_env, &system_env); + let mut updates = UpdatesManager::new(&l1_batch_env, &system_env, pubdata_params); let tx_hash = tx.hash(); updates.extend_from_executed_transaction( diff --git a/core/node/state_keeper/src/keeper.rs b/core/node/state_keeper/src/keeper.rs index d36ceec7d70..408c3e11cb4 100644 --- a/core/node/state_keeper/src/keeper.rs +++ b/core/node/state_keeper/src/keeper.rs @@ -17,8 +17,9 @@ use zksync_multivm::{ use zksync_shared_metrics::{TxStage, APP_METRICS}; use zksync_state::{OwnedStorage, ReadStorageFactory}; use zksync_types::{ - block::L2BlockExecutionData, l2::TransactionType, protocol_upgrade::ProtocolUpgradeTx, - protocol_version::ProtocolVersionId, utils::display_timestamp, L1BatchNumber, Transaction, + block::L2BlockExecutionData, commitment::PubdataParams, l2::TransactionType, + protocol_upgrade::ProtocolUpgradeTx, protocol_version::ProtocolVersionId, + utils::display_timestamp, L1BatchNumber, Transaction, }; use crate::{ @@ -116,6 +117,7 @@ impl ZkSyncStateKeeper { let PendingBatchData { mut l1_batch_env, mut system_env, + mut pubdata_params, pending_l2_blocks, } = match pending_batch_params { Some(params) => { @@ -132,7 +134,7 @@ impl ZkSyncStateKeeper { } None => { tracing::info!("There is no open pending batch, starting a new empty batch"); - let (system_env, l1_batch_env) = self + let (system_env, l1_batch_env, pubdata_params) = self .wait_for_new_batch_env(&cursor) .await .map_err(|e| e.context("wait_for_new_batch_params()"))?; @@ -140,18 +142,19 @@ impl ZkSyncStateKeeper { l1_batch_env, pending_l2_blocks: Vec::new(), system_env, + pubdata_params, } } }; let protocol_version = system_env.version; - let mut updates_manager = UpdatesManager::new(&l1_batch_env, &system_env); + let mut updates_manager = UpdatesManager::new(&l1_batch_env, &system_env, pubdata_params); let mut protocol_upgrade_tx: Option = self .load_protocol_upgrade_tx(&pending_l2_blocks, protocol_version, l1_batch_env.number) .await?; let mut batch_executor = self - .create_batch_executor(l1_batch_env.clone(), system_env.clone()) + .create_batch_executor(l1_batch_env.clone(), system_env.clone(), pubdata_params) .await?; self.restore_state( &mut *batch_executor, @@ -201,10 +204,11 @@ impl ZkSyncStateKeeper { // Start the new batch. next_cursor.l1_batch += 1; - (system_env, l1_batch_env) = self.wait_for_new_batch_env(&next_cursor).await?; - updates_manager = UpdatesManager::new(&l1_batch_env, &system_env); + (system_env, l1_batch_env, pubdata_params) = + self.wait_for_new_batch_env(&next_cursor).await?; + updates_manager = UpdatesManager::new(&l1_batch_env, &system_env, pubdata_params); batch_executor = self - .create_batch_executor(l1_batch_env.clone(), system_env.clone()) + .create_batch_executor(l1_batch_env.clone(), system_env.clone(), pubdata_params) .await?; let version_changed = system_env.version != sealed_batch_protocol_version; @@ -221,6 +225,7 @@ impl ZkSyncStateKeeper { &mut self, l1_batch_env: L1BatchEnv, system_env: SystemEnv, + pubdata_params: PubdataParams, ) -> Result>, Error> { let storage = self .storage_factory @@ -230,7 +235,7 @@ impl ZkSyncStateKeeper { .ok_or(Error::Canceled)?; Ok(self .batch_executor - .init_batch(storage, l1_batch_env, system_env)) + .init_batch(storage, l1_batch_env, system_env, pubdata_params)) } /// This function is meant to be called only once during the state-keeper initialization. @@ -327,7 +332,7 @@ impl ZkSyncStateKeeper { async fn wait_for_new_batch_env( &mut self, cursor: &IoCursor, - ) -> Result<(SystemEnv, L1BatchEnv), Error> { + ) -> Result<(SystemEnv, L1BatchEnv, PubdataParams), Error> { // `io.wait_for_new_batch_params(..)` is not cancel-safe; once we get new batch params, we must hold onto them // until we get the rest of parameters from I/O or receive a stop signal. let params = self.wait_for_new_batch_params(cursor).await?; diff --git a/core/node/state_keeper/src/testonly/mod.rs b/core/node/state_keeper/src/testonly/mod.rs index edcf3ccc4f5..b01d759379b 100644 --- a/core/node/state_keeper/src/testonly/mod.rs +++ b/core/node/state_keeper/src/testonly/mod.rs @@ -14,9 +14,9 @@ use zksync_multivm::interface::{ use zksync_state::OwnedStorage; use zksync_test_account::Account; use zksync_types::{ - fee::Fee, utils::storage_key_for_standard_token_balance, AccountTreeId, Address, Execute, - L1BatchNumber, L2BlockNumber, PriorityOpId, StorageLog, Transaction, L2_BASE_TOKEN_ADDRESS, - SYSTEM_CONTEXT_MINIMAL_BASE_FEE, U256, + commitment::PubdataParams, fee::Fee, utils::storage_key_for_standard_token_balance, + AccountTreeId, Address, Execute, L1BatchNumber, L2BlockNumber, PriorityOpId, StorageLog, + Transaction, L2_BASE_TOKEN_ADDRESS, SYSTEM_CONTEXT_MINIMAL_BASE_FEE, U256, }; use zksync_utils::u256_to_h256; @@ -49,6 +49,7 @@ impl BatchExecutorFactory for MockBatchExecutor { _storage: OwnedStorage, _l1_batch_env: L1BatchEnv, _system_env: SystemEnv, + _pubdata_params: PubdataParams, ) -> Box> { Box::new(Self) } diff --git a/core/node/state_keeper/src/testonly/test_batch_executor.rs b/core/node/state_keeper/src/testonly/test_batch_executor.rs index 4a58e9e0a95..433208e794a 100644 --- a/core/node/state_keeper/src/testonly/test_batch_executor.rs +++ b/core/node/state_keeper/src/testonly/test_batch_executor.rs @@ -27,8 +27,9 @@ use zksync_multivm::{ use zksync_node_test_utils::create_l2_transaction; use zksync_state::{interface::StorageView, OwnedStorage, ReadStorageFactory}; use zksync_types::{ - fee_model::BatchFeeInput, l2_to_l1_log::UserL2ToL1Log, protocol_upgrade::ProtocolUpgradeTx, - Address, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersionId, Transaction, H256, + commitment::PubdataParams, fee_model::BatchFeeInput, l2_to_l1_log::UserL2ToL1Log, + protocol_upgrade::ProtocolUpgradeTx, Address, L1BatchNumber, L2BlockNumber, L2ChainId, + ProtocolVersionId, Transaction, H256, }; use crate::{ @@ -421,6 +422,7 @@ impl BatchExecutorFactory for TestBatchExecutorBuilder { _storage: OwnedStorage, _l1_batch_env: L1BatchEnv, _system_env: SystemEnv, + _pubdata_params: PubdataParams, ) -> Box> { let executor = TestBatchExecutor::new(self.txs.pop_front().unwrap(), self.rollback_set.clone()); diff --git a/core/node/state_keeper/src/tests/mod.rs b/core/node/state_keeper/src/tests/mod.rs index 552e6ec3799..39d3e7c3c60 100644 --- a/core/node/state_keeper/src/tests/mod.rs +++ b/core/node/state_keeper/src/tests/mod.rs @@ -58,8 +58,8 @@ pub(crate) fn pending_batch_data(pending_l2_blocks: Vec) - execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT, chain_id: L2ChainId::from(270), - pubdata_params: Default::default(), }, + pubdata_params: Default::default(), pending_l2_blocks, } } @@ -73,7 +73,6 @@ pub(super) fn default_system_env() -> SystemEnv { execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT, chain_id: L2ChainId::from(270), - pubdata_params: Default::default(), } } @@ -104,7 +103,7 @@ pub(super) fn default_l1_batch_env( pub(super) fn create_updates_manager() -> UpdatesManager { let l1_batch_env = default_l1_batch_env(1, 1, Address::default()); - UpdatesManager::new(&l1_batch_env, &default_system_env()) + UpdatesManager::new(&l1_batch_env, &default_system_env(), Default::default()) } pub(super) fn create_transaction(fee_per_gas: u64, gas_per_pubdata: u64) -> Transaction { diff --git a/core/node/state_keeper/src/updates/mod.rs b/core/node/state_keeper/src/updates/mod.rs index 9996741a626..da69225e17f 100644 --- a/core/node/state_keeper/src/updates/mod.rs +++ b/core/node/state_keeper/src/updates/mod.rs @@ -43,7 +43,11 @@ pub struct UpdatesManager { } impl UpdatesManager { - pub fn new(l1_batch_env: &L1BatchEnv, system_env: &SystemEnv) -> Self { + pub fn new( + l1_batch_env: &L1BatchEnv, + system_env: &SystemEnv, + pubdata_params: PubdataParams, + ) -> Self { let protocol_version = system_env.version; Self { batch_timestamp: l1_batch_env.timestamp, @@ -62,7 +66,7 @@ impl UpdatesManager { ), storage_writes_deduplicator: StorageWritesDeduplicator::new(), storage_view_cache: None, - pubdata_params: system_env.pubdata_params, + pubdata_params, } } diff --git a/core/node/tee_verifier_input_producer/src/lib.rs b/core/node/tee_verifier_input_producer/src/lib.rs index 8a99aa07ae5..f80bf0d002e 100644 --- a/core/node/tee_verifier_input_producer/src/lib.rs +++ b/core/node/tee_verifier_input_producer/src/lib.rs @@ -86,7 +86,7 @@ impl TeeVerifierInputProducer { // This means we don't want to reject any execution, therefore we're using MAX as an allow all. let validation_computational_gas_limit = u32::MAX; - let (system_env, l1_batch_env) = l1_batch_params_provider + let (system_env, l1_batch_env, pubdata_params) = l1_batch_params_provider .load_l1_batch_env( &mut connection, l1_batch_number, @@ -128,6 +128,7 @@ impl TeeVerifierInputProducer { l1_batch_env, system_env, used_contracts, + pubdata_params, ); // TODO (SEC-263): remove these 2 lines after successful testnet runs diff --git a/core/node/vm_runner/src/process.rs b/core/node/vm_runner/src/process.rs index 4f7ac1f9728..dbd218c8dc5 100644 --- a/core/node/vm_runner/src/process.rs +++ b/core/node/vm_runner/src/process.rs @@ -82,6 +82,7 @@ impl VmRunner { storage, batch_data.l1_batch_env.clone(), batch_data.system_env.clone(), + batch_data.pubdata_params, ); let mut output_handler = self .output_handler_factory diff --git a/core/node/vm_runner/src/storage.rs b/core/node/vm_runner/src/storage.rs index 2285455ba24..9ab4ed87b9f 100644 --- a/core/node/vm_runner/src/storage.rs +++ b/core/node/vm_runner/src/storage.rs @@ -13,7 +13,9 @@ use zksync_state::{ AsyncCatchupTask, BatchDiff, OwnedStorage, RocksdbCell, RocksdbStorage, RocksdbStorageBuilder, RocksdbWithMemory, }; -use zksync_types::{block::L2BlockExecutionData, L1BatchNumber, L2ChainId}; +use zksync_types::{ + block::L2BlockExecutionData, commitment::PubdataParams, L1BatchNumber, L2ChainId, +}; use zksync_vm_executor::storage::L1BatchParamsProvider; use zksync_vm_interface::{L1BatchEnv, SystemEnv}; @@ -106,6 +108,8 @@ pub struct BatchExecuteData { pub l1_batch_env: L1BatchEnv, /// Execution process parameters. pub system_env: SystemEnv, + /// Pubdata building parameters. + pub pubdata_params: PubdataParams, /// List of L2 blocks and corresponding transactions that were executed within batch. pub l2_blocks: Vec, } @@ -394,7 +398,7 @@ pub(crate) async fn load_batch_execute_data( l1_batch_params_provider: &L1BatchParamsProvider, chain_id: L2ChainId, ) -> anyhow::Result> { - let Some((system_env, l1_batch_env)) = l1_batch_params_provider + let Some((system_env, l1_batch_env, pubdata_params)) = l1_batch_params_provider .load_l1_batch_env( conn, l1_batch_number, @@ -415,6 +419,7 @@ pub(crate) async fn load_batch_execute_data( Ok(Some(BatchExecuteData { l1_batch_env, system_env, + pubdata_params, l2_blocks, })) } diff --git a/core/node/vm_runner/src/tests/output_handler.rs b/core/node/vm_runner/src/tests/output_handler.rs index 131089d0f79..1bf30effdbe 100644 --- a/core/node/vm_runner/src/tests/output_handler.rs +++ b/core/node/vm_runner/src/tests/output_handler.rs @@ -71,7 +71,6 @@ impl OutputHandlerTester { execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: 0, chain_id: Default::default(), - pubdata_params: Default::default(), }; let mut output_handler = self diff --git a/core/tests/vm-benchmark/src/vm.rs b/core/tests/vm-benchmark/src/vm.rs index 410c0e071b4..ee9b5d1c5e7 100644 --- a/core/tests/vm-benchmark/src/vm.rs +++ b/core/tests/vm-benchmark/src/vm.rs @@ -4,6 +4,7 @@ use once_cell::sync::Lazy; use zksync_contracts::BaseSystemContracts; use zksync_multivm::{ interface::{ + pubdata::{pubdata_params_to_builder, PubdataBuilder}, storage::{InMemoryStorage, StorageView}, ExecutionResult, L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode, VmExecutionMode, VmExecutionResultAndLogs, VmFactory, VmInterface, VmInterfaceExt, @@ -14,9 +15,9 @@ use zksync_multivm::{ zk_evm_latest::ethereum_types::{Address, U256}, }; use zksync_types::{ - block::L2BlockHasher, fee_model::BatchFeeInput, helpers::unix_timestamp_ms, - utils::storage_key_for_eth_balance, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersionId, - Transaction, + block::L2BlockHasher, commitment::PubdataParams, fee_model::BatchFeeInput, + helpers::unix_timestamp_ms, utils::storage_key_for_eth_balance, L1BatchNumber, L2BlockNumber, + L2ChainId, ProtocolVersionId, Transaction, }; use zksync_utils::bytecode::hash_bytecode; @@ -71,6 +72,7 @@ pub trait BenchmarkingVmFactory { batch_env: L1BatchEnv, system_env: SystemEnv, storage: &'static InMemoryStorage, + pubdata_builder: Rc, ) -> Self::Instance; } @@ -87,6 +89,7 @@ impl BenchmarkingVmFactory for Fast { batch_env: L1BatchEnv, system_env: SystemEnv, storage: &'static InMemoryStorage, + _pubdata_builder: Rc, ) -> Self::Instance { vm_fast::Vm::custom(batch_env, system_env, storage) } @@ -105,9 +108,10 @@ impl BenchmarkingVmFactory for Legacy { batch_env: L1BatchEnv, system_env: SystemEnv, storage: &'static InMemoryStorage, + pubdata_builder: Rc, ) -> Self::Instance { let storage = StorageView::new(storage).to_rc_ptr(); - vm_latest::Vm::new(batch_env, system_env, storage) + vm_latest::Vm::new(batch_env, system_env, storage, Some(pubdata_builder)) } } @@ -143,9 +147,9 @@ impl Default for BenchmarkingVm { execution_mode: TxExecutionMode::VerifyExecute, default_validation_computational_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT, chain_id: L2ChainId::from(270), - pubdata_params: Default::default(), }, &STORAGE, + pubdata_params_to_builder(PubdataParams::default()), )) } } diff --git a/prover/Cargo.lock b/prover/Cargo.lock index eb5297ef963..fcd4798c8b4 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -7708,7 +7708,6 @@ dependencies = [ "zk_evm 0.141.0", "zk_evm 0.150.5", "zksync_contracts", - "zksync_mini_merkle_tree", "zksync_system_constants", "zksync_types", "zksync_utils", @@ -8153,8 +8152,10 @@ dependencies = [ "thiserror", "tracing", "zksync_contracts", + "zksync_mini_merkle_tree", "zksync_system_constants", "zksync_types", + "zksync_utils", ] [[package]]