Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vm): Simplify VM interface #2760

Merged
merged 6 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/bin/system-constants-generator/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use zksync_multivm::{
storage::{InMemoryStorage, StorageView, WriteStorage},
tracer::VmExecutionStopReason,
L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode, VmExecutionMode, VmFactory,
VmInterface,
VmInterface, VmInterfaceExt,
},
tracers::dynamic::vm_1_5_0::DynTracer,
vm_latest::{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ impl GlueFrom<crate::vm_m5::vm_instance::VmPartialExecutionResult>
contracts_used: value.contracts_used,
cycles_used: value.cycles_used,
total_log_queries: value.logs.total_log_queries_count,
gas_remaining: value.gas_remaining,
// There are no such fields in `m5`.
gas_used: 0,
gas_remaining: 0,
computational_gas_used: 0,
pubdata_published: 0,
circuit_statistic: Default::default(),
Expand All @@ -37,10 +37,10 @@ impl GlueFrom<crate::vm_m6::vm_instance::VmPartialExecutionResult>
contracts_used: value.contracts_used,
cycles_used: value.cycles_used,
computational_gas_used: value.computational_gas_used,
gas_remaining: value.gas_remaining,
total_log_queries: value.logs.total_log_queries_count,
// There are no such fields in `m6`.
gas_used: 0,
gas_remaining: 0,
pubdata_published: 0,
circuit_statistic: Default::default(),
},
Expand All @@ -63,10 +63,10 @@ impl GlueFrom<crate::vm_1_3_2::vm_instance::VmPartialExecutionResult>
contracts_used: value.contracts_used,
cycles_used: value.cycles_used,
computational_gas_used: value.computational_gas_used,
gas_remaining: value.gas_remaining,
total_log_queries: value.logs.total_log_queries_count,
// There are no such fields in `1_3_2`.
gas_used: 0,
gas_remaining: 0,
pubdata_published: 0,
circuit_statistic: Default::default(),
},
Expand Down
99 changes: 9 additions & 90 deletions core/lib/multivm/src/versions/shadow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ use zksync_types::{StorageKey, StorageLog, StorageLogWithPreviousValue, Transact
use crate::{
interface::{
storage::{ImmutableStorageView, ReadStorage, StoragePtr, StorageView},
BootloaderMemory, BytecodeCompressionError, CompressedBytecodeInfo, CurrentExecutionState,
FinishedL1Batch, L1BatchEnv, L2BlockEnv, SystemEnv, VmExecutionMode,
VmExecutionResultAndLogs, VmFactory, VmInterface, VmInterfaceHistoryEnabled,
VmMemoryMetrics,
BytecodeCompressionResult, CurrentExecutionState, FinishedL1Batch, L1BatchEnv, L2BlockEnv,
SystemEnv, VmExecutionMode, VmExecutionResultAndLogs, VmFactory, VmInterface,
VmInterfaceHistoryEnabled, VmMemoryMetrics,
},
vm_fast,
};
Expand Down Expand Up @@ -52,18 +51,6 @@ where
self.main.push_transaction(tx);
}

fn execute(&mut self, execution_mode: VmExecutionMode) -> VmExecutionResultAndLogs {
let main_result = self.main.execute(execution_mode);
let shadow_result = self.shadow.execute(execution_mode);
let mut errors = DivergenceErrors::default();
errors.check_results_match(&main_result, &shadow_result);
errors
.into_result()
.with_context(|| format!("executing VM with mode {execution_mode:?}"))
.unwrap();
main_result
}

fn inspect(
&mut self,
dispatcher: Self::TracerDispatcher,
Expand All @@ -80,73 +67,17 @@ where
main_result
}

fn get_bootloader_memory(&self) -> BootloaderMemory {
let main_memory = self.main.get_bootloader_memory();
let shadow_memory = self.shadow.get_bootloader_memory();
DivergenceErrors::single("get_bootloader_memory", &main_memory, &shadow_memory).unwrap();
main_memory
}

fn get_last_tx_compressed_bytecodes(&self) -> Vec<CompressedBytecodeInfo> {
let main_bytecodes = self.main.get_last_tx_compressed_bytecodes();
let shadow_bytecodes = self.shadow.get_last_tx_compressed_bytecodes();
DivergenceErrors::single(
"get_last_tx_compressed_bytecodes",
&main_bytecodes,
&shadow_bytecodes,
)
.unwrap();
main_bytecodes
}

fn start_new_l2_block(&mut self, l2_block_env: L2BlockEnv) {
self.shadow.start_new_l2_block(l2_block_env);
self.main.start_new_l2_block(l2_block_env);
}

fn get_current_execution_state(&self) -> CurrentExecutionState {
let main_state = self.main.get_current_execution_state();
let shadow_state = self.shadow.get_current_execution_state();
DivergenceErrors::single("get_current_execution_state", &main_state, &shadow_state)
.unwrap();
main_state
}

fn execute_transaction_with_bytecode_compression(
&mut self,
tx: Transaction,
with_compression: bool,
) -> (
Result<(), BytecodeCompressionError>,
VmExecutionResultAndLogs,
) {
let tx_hash = tx.hash();
let main_result = self
.main
.execute_transaction_with_bytecode_compression(tx.clone(), with_compression);
let shadow_result = self
.shadow
.execute_transaction_with_bytecode_compression(tx, with_compression);
let mut errors = DivergenceErrors::default();
errors.check_results_match(&main_result.1, &shadow_result.1);
errors
.into_result()
.with_context(|| {
format!("executing transaction {tx_hash:?}, with_compression={with_compression:?}")
})
.unwrap();
main_result
}

fn inspect_transaction_with_bytecode_compression(
&mut self,
tracer: Self::TracerDispatcher,
tx: Transaction,
with_compression: bool,
) -> (
Result<(), BytecodeCompressionError>,
VmExecutionResultAndLogs,
) {
) -> (BytecodeCompressionResult, VmExecutionResultAndLogs) {
let tx_hash = tx.hash();
let main_result = self.main.inspect_transaction_with_bytecode_compression(
tracer,
Expand All @@ -171,13 +102,6 @@ where
self.main.record_vm_memory_metrics()
}

fn gas_remaining(&self) -> u32 {
let main_gas = self.main.gas_remaining();
let shadow_gas = self.shadow.gas_remaining();
DivergenceErrors::single("gas_remaining", &main_gas, &shadow_gas).unwrap();
main_gas
}

fn finish_batch(&mut self) -> FinishedL1Batch {
let main_batch = self.main.finish_batch();
let shadow_batch = self.shadow.finish_batch();
Expand Down Expand Up @@ -216,16 +140,6 @@ where
pub struct DivergenceErrors(Vec<anyhow::Error>);

impl DivergenceErrors {
fn single<T: fmt::Debug + PartialEq>(
context: &str,
main: &T,
shadow: &T,
) -> anyhow::Result<()> {
let mut this = Self::default();
this.check_match(context, main, shadow);
this.into_result()
}

fn check_results_match(
&mut self,
main_result: &VmExecutionResultAndLogs,
Expand All @@ -251,6 +165,11 @@ impl DivergenceErrors {
let shadow_logs = UniqueStorageLogs::new(&shadow_result.logs.storage_logs);
self.check_match("logs.storage_logs", &main_logs, &shadow_logs);
self.check_match("refunds", &main_result.refunds, &shadow_result.refunds);
self.check_match(
"gas_remaining",
&main_result.statistics.gas_remaining,
&shadow_result.statistics.gas_remaining,
);
}

fn check_match<T: fmt::Debug + PartialEq>(&mut self, context: &str, main: &T, shadow: &T) {
Expand Down
102 changes: 14 additions & 88 deletions core/lib/multivm/src/versions/vm_1_3_2/vm.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,25 @@
use std::collections::HashSet;

use circuit_sequencer_api_1_3_3::sort_storage_access::sort_storage_access_queries;
use zksync_types::{
l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log},
Transaction,
};
use zksync_utils::{bytecode::hash_bytecode, h256_to_u256, u256_to_h256};
use zksync_types::Transaction;
use zksync_utils::{bytecode::hash_bytecode, h256_to_u256};

use crate::{
glue::{history_mode::HistoryMode, GlueInto},
interface::{
storage::{StoragePtr, WriteStorage},
BootloaderMemory, BytecodeCompressionError, CompressedBytecodeInfo, CurrentExecutionState,
FinishedL1Batch, L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode, VmExecutionMode,
VmExecutionResultAndLogs, VmFactory, VmInterface, VmInterfaceHistoryEnabled,
VmMemoryMetrics,
BytecodeCompressionError, BytecodeCompressionResult, FinishedL1Batch, L1BatchEnv,
L2BlockEnv, SystemEnv, TxExecutionMode, VmExecutionMode, VmExecutionResultAndLogs,
VmFactory, VmInterface, VmInterfaceHistoryEnabled, VmMemoryMetrics,
},
tracers::old::TracerDispatcher,
utils::bytecode,
vm_1_3_2::{events::merge_events, VmInstance},
vm_1_3_2::VmInstance,
};

#[derive(Debug)]
pub struct Vm<S: WriteStorage, H: HistoryMode> {
pub(crate) vm: VmInstance<S, H::Vm1_3_2Mode>,
pub(crate) system_env: SystemEnv,
pub(crate) batch_env: L1BatchEnv,
pub(crate) last_tx_compressed_bytecodes: Vec<CompressedBytecodeInfo>,
}

impl<S: WriteStorage, H: HistoryMode> VmInterface for Vm<S, H> {
Expand Down Expand Up @@ -81,83 +74,23 @@ impl<S: WriteStorage, H: HistoryMode> VmInterface for Vm<S, H> {
}
}

fn get_bootloader_memory(&self) -> BootloaderMemory {
vec![]
}

fn get_last_tx_compressed_bytecodes(&self) -> Vec<CompressedBytecodeInfo> {
self.last_tx_compressed_bytecodes.clone()
}

fn start_new_l2_block(&mut self, _l2_block_env: L2BlockEnv) {
// Do nothing, because vm 1.3.2 doesn't support L2 blocks
}

fn get_current_execution_state(&self) -> CurrentExecutionState {
let (raw_events, l1_messages) = self.vm.state.event_sink.flatten();
let events = merge_events(raw_events)
.into_iter()
.map(|e| e.into_vm_event(self.batch_env.number))
.collect();
let l2_to_l1_logs = l1_messages
.into_iter()
.map(|m| {
UserL2ToL1Log(L2ToL1Log {
shard_id: m.shard_id,
is_service: m.is_first,
tx_number_in_block: m.tx_number_in_block,
sender: m.address,
key: u256_to_h256(m.key),
value: u256_to_h256(m.value),
})
})
.collect();

let used_contract_hashes = self
.vm
.state
.decommittment_processor
.known_bytecodes
.inner()
.keys()
.cloned()
.collect();

let storage_log_queries = self.vm.state.storage.get_final_log_queries();

let deduped_storage_log_queries =
sort_storage_access_queries(storage_log_queries.iter().map(|log| &log.log_query)).1;

CurrentExecutionState {
events,
deduplicated_storage_logs: deduped_storage_log_queries
.into_iter()
.map(GlueInto::glue_into)
.collect(),
used_contract_hashes,
user_l2_to_l1_logs: l2_to_l1_logs,
system_logs: vec![],
// Fields below are not produced by VM 1.3.2
storage_refunds: vec![],
pubdata_costs: Vec::new(),
}
}

fn inspect_transaction_with_bytecode_compression(
&mut self,
tracer: Self::TracerDispatcher,
tx: Transaction,
with_compression: bool,
) -> (
Result<(), BytecodeCompressionError>,
VmExecutionResultAndLogs,
) {
) -> (BytecodeCompressionResult, VmExecutionResultAndLogs) {
if let Some(storage_invocations) = tracer.storage_invocations {
self.vm
.execution_mode
.set_invocation_limit(storage_invocations);
}
self.last_tx_compressed_bytecodes = vec![];

let compressed_bytecodes: Vec<_>;
let bytecodes = if with_compression {
let deps = &tx.execute.factory_deps;
let mut deps_hashes = HashSet::with_capacity(deps.len());
Expand All @@ -174,18 +107,17 @@ impl<S: WriteStorage, H: HistoryMode> VmInterface for Vm<S, H> {
bytecode::compress(bytecode.clone()).ok()
}
});
let compressed_bytecodes: Vec<_> = filtered_deps.collect();
compressed_bytecodes = filtered_deps.collect();

self.last_tx_compressed_bytecodes
.clone_from(&compressed_bytecodes);
crate::vm_1_3_2::vm_with_bootloader::push_transaction_to_bootloader_memory(
&mut self.vm,
&tx,
self.system_env.execution_mode.glue_into(),
Some(compressed_bytecodes),
Some(compressed_bytecodes.clone()),
);
bytecode_hashes
} else {
compressed_bytecodes = vec![];
crate::vm_1_3_2::vm_with_bootloader::push_transaction_to_bootloader_memory(
&mut self.vm,
&tx,
Expand Down Expand Up @@ -224,7 +156,7 @@ impl<S: WriteStorage, H: HistoryMode> VmInterface for Vm<S, H> {
result,
)
} else {
(Ok(()), result)
(Ok(compressed_bytecodes), result)
}
}

Expand All @@ -245,10 +177,6 @@ impl<S: WriteStorage, H: HistoryMode> VmInterface for Vm<S, H> {
}
}

fn gas_remaining(&self) -> u32 {
self.vm.gas_remaining()
}

fn finish_batch(&mut self) -> FinishedL1Batch {
self.vm
.execute_till_block_end(
Expand All @@ -270,7 +198,7 @@ impl<S: WriteStorage, H: HistoryMode> VmFactory<S> for Vm<S, H> {
let inner_vm: VmInstance<S, H::Vm1_3_2Mode> =
crate::vm_1_3_2::vm_with_bootloader::init_vm_with_gas_limit(
oracle_tools,
batch_env.clone().glue_into(),
batch_env.glue_into(),
block_properties,
system_env.execution_mode.glue_into(),
&system_env.base_system_smart_contracts.clone().glue_into(),
Expand All @@ -279,8 +207,6 @@ impl<S: WriteStorage, H: HistoryMode> VmFactory<S> for Vm<S, H> {
Self {
vm: inner_vm,
system_env,
batch_env,
last_tx_compressed_bytecodes: vec![],
}
}
}
Expand Down
Loading
Loading