Skip to content

Commit

Permalink
fix(vm): Check protocol version for fast VM (#3080)
Browse files Browse the repository at this point in the history
## What ❔

Fixes a regression introduced by
#2915: The protocol
version is now not checked before instantiating a fast VM.

## Why ❔

Without this check, fast VM can be used with old protocol versions,
which most likely will cause divergencies.

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted via `zk_supervisor fmt` and `zk_supervisor
lint`.
  • Loading branch information
slowli authored Oct 14, 2024
1 parent bd4b9f7 commit a089f3f
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/lib/multivm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub use crate::{
vm_1_3_2, vm_1_4_1, vm_1_4_2, vm_boojum_integration, vm_fast, vm_latest, vm_m5, vm_m6,
vm_refunds_enhancement, vm_virtual_blocks,
},
vm_instance::{FastVmInstance, LegacyVmInstance},
vm_instance::{is_supported_by_fast_vm, FastVmInstance, LegacyVmInstance},
};

mod glue;
Expand Down
7 changes: 7 additions & 0 deletions core/lib/multivm/src/versions/vm_fast/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use crate::{
VmExecutionStatistics, VmFactory, VmInterface, VmInterfaceHistoryEnabled, VmRevertReason,
VmTrackingContracts,
},
is_supported_by_fast_vm,
utils::events::extract_l2tol1logs_from_l1_messenger,
vm_fast::{
bootloader_state::utils::{apply_l2_block, apply_pubdata_to_memory},
Expand Down Expand Up @@ -104,6 +105,12 @@ pub struct Vm<S, Tr = ()> {

impl<S: ReadStorage, Tr: Tracer> Vm<S, Tr> {
pub fn custom(batch_env: L1BatchEnv, system_env: SystemEnv, storage: S) -> Self {
assert!(
is_supported_by_fast_vm(system_env.version),
"Protocol version {:?} is not supported by fast VM",
system_env.version
);

let default_aa_code_hash = system_env
.base_system_smart_contracts
.default_aa
Expand Down
10 changes: 9 additions & 1 deletion core/lib/multivm/src/vm_instance.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::mem;

use zksync_types::{vm::VmVersion, Transaction};
use zksync_types::{vm::VmVersion, ProtocolVersionId, Transaction};
use zksync_vm2::interface::Tracer;

use crate::{
Expand Down Expand Up @@ -328,3 +328,11 @@ impl<S: ReadStorage, Tr: Tracer + Default + 'static> FastVmInstance<S, Tr> {
Self::Shadowed(ShadowedFastVm::new(l1_batch_env, system_env, storage_view))
}
}

/// Checks whether the protocol version is supported by the fast VM.
pub fn is_supported_by_fast_vm(protocol_version: ProtocolVersionId) -> bool {
matches!(
protocol_version.into(),
VmVersion::Vm1_5_0IncreasedBootloaderMemory
)
}
3 changes: 3 additions & 0 deletions core/lib/vm_executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ tokio.workspace = true
anyhow.workspace = true
tracing.workspace = true
vise.workspace = true

[dev-dependencies]
assert_matches.workspace = true
52 changes: 52 additions & 0 deletions core/lib/vm_executor/src/batch/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use zksync_multivm::{
ExecutionResult, FinishedL1Batch, Halt, L1BatchEnv, L2BlockEnv, SystemEnv, VmFactory,
VmInterface, VmInterfaceHistoryEnabled,
},
is_supported_by_fast_vm,
tracers::CallTracer,
vm_fast,
vm_latest::HistoryEnabled,
Expand Down Expand Up @@ -159,6 +160,10 @@ impl<S: ReadStorage, Tr: BatchTracer> BatchVm<S, Tr> {
storage_ptr: StoragePtr<StorageView<S>>,
mode: FastVmMode,
) -> Self {
if !is_supported_by_fast_vm(system_env.version) {
return Self::Legacy(LegacyVmInstance::new(l1_batch_env, system_env, storage_ptr));
}

match mode {
FastVmMode::Old => {
Self::Legacy(LegacyVmInstance::new(l1_batch_env, system_env, storage_ptr))
Expand Down Expand Up @@ -443,3 +448,50 @@ impl<S: ReadStorage + 'static, Tr: BatchTracer> CommandReceiver<S, Tr> {
}
}
}

#[cfg(test)]
mod tests {
use assert_matches::assert_matches;
use zksync_multivm::interface::{storage::InMemoryStorage, TxExecutionMode};
use zksync_types::ProtocolVersionId;

use super::*;
use crate::testonly::{default_l1_batch_env, default_system_env, FAST_VM_MODES};

#[test]
fn selecting_vm_for_execution() {
let l1_batch_env = default_l1_batch_env(1);
let mut system_env = SystemEnv {
version: ProtocolVersionId::Version22,
..default_system_env(TxExecutionMode::VerifyExecute)
};
let storage = StorageView::new(InMemoryStorage::default()).to_rc_ptr();
for mode in FAST_VM_MODES {
let vm = BatchVm::<_, ()>::new(
l1_batch_env.clone(),
system_env.clone(),
storage.clone(),
mode,
);
assert_matches!(vm, BatchVm::Legacy(_));
}

system_env.version = ProtocolVersionId::latest();
let vm = BatchVm::<_, ()>::new(
l1_batch_env.clone(),
system_env.clone(),
storage.clone(),
FastVmMode::Old,
);
assert_matches!(vm, BatchVm::Legacy(_));
let vm = BatchVm::<_, ()>::new(
l1_batch_env.clone(),
system_env.clone(),
storage.clone(),
FastVmMode::New,
);
assert_matches!(vm, BatchVm::Fast(FastVmInstance::Fast(_)));
let vm = BatchVm::<_, ()>::new(l1_batch_env, system_env, storage, FastVmMode::Shadow);
assert_matches!(vm, BatchVm::Fast(FastVmInstance::Shadowed(_)));
}
}
2 changes: 2 additions & 0 deletions core/lib/vm_executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ pub mod batch;
pub mod oneshot;
mod shared;
pub mod storage;
#[cfg(test)]
mod testonly;
45 changes: 45 additions & 0 deletions core/lib/vm_executor/src/testonly.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use once_cell::sync::Lazy;
use zksync_contracts::BaseSystemContracts;
use zksync_multivm::{
interface::{L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode},
vm_latest::constants::BATCH_COMPUTATIONAL_GAS_LIMIT,
};
use zksync_types::{
block::L2BlockHasher, fee_model::BatchFeeInput, vm::FastVmMode, Address, L1BatchNumber,
L2BlockNumber, L2ChainId, ProtocolVersionId, H256, ZKPORTER_IS_AVAILABLE,
};

static BASE_SYSTEM_CONTRACTS: Lazy<BaseSystemContracts> =
Lazy::new(BaseSystemContracts::load_from_disk);

pub(crate) const FAST_VM_MODES: [FastVmMode; 3] =
[FastVmMode::Old, FastVmMode::New, FastVmMode::Shadow];

pub(crate) fn default_system_env(execution_mode: TxExecutionMode) -> SystemEnv {
SystemEnv {
zk_porter_available: ZKPORTER_IS_AVAILABLE,
version: ProtocolVersionId::latest(),
base_system_smart_contracts: BASE_SYSTEM_CONTRACTS.clone(),
bootloader_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT,
execution_mode,
default_validation_computational_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT,
chain_id: L2ChainId::default(),
}
}

pub(crate) fn default_l1_batch_env(number: u32) -> L1BatchEnv {
L1BatchEnv {
previous_batch_hash: Some(H256::zero()),
number: L1BatchNumber(number),
timestamp: number.into(),
fee_account: Address::repeat_byte(0x22),
enforced_base_fee: None,
first_l2_block: L2BlockEnv {
number,
timestamp: number.into(),
prev_block_hash: L2BlockHasher::legacy_hash(L2BlockNumber(number - 1)),
max_virtual_blocks_to_create: 1,
},
fee_input: BatchFeeInput::sensible_l1_pegged_default(),
}
}

0 comments on commit a089f3f

Please sign in to comment.