Skip to content

Commit

Permalink
Merge branch 'master' into aov-pla-1027-brush-up-vm2-repo-for-publish…
Browse files Browse the repository at this point in the history
…ing-release
  • Loading branch information
slowli authored Sep 20, 2024
2 parents bc59dce + 74577d9 commit d4ab3d3
Show file tree
Hide file tree
Showing 12 changed files with 76 additions and 53 deletions.
4 changes: 3 additions & 1 deletion crates/vm2/src/callframe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{mem, ptr};

use primitive_types::H160;
use zkevm_opcode_defs::system_params::{NEW_FRAME_MEMORY_STIPEND, NEW_KERNEL_FRAME_MEMORY_STIPEND};
use zksync_vm2_interface::HeapId;
use zksync_vm2_interface::{HeapId, Tracer};

use crate::{
decommit::is_kernel,
Expand Down Expand Up @@ -105,7 +105,9 @@ impl<T, W> Callframe<T, W> {
world_before_this_frame,
}
}
}

impl<T: Tracer, W> Callframe<T, W> {
pub(crate) fn push_near_call(
&mut self,
gas_to_call: u32,
Expand Down
13 changes: 7 additions & 6 deletions crates/vm2/src/instruction_handlers/heap_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use zksync_vm2_interface::{opcodes, HeapId, OpcodeType, Tracer};
use super::{
common::{boilerplate, full_boilerplate},
monomorphization::{match_boolean, match_reg_imm, monomorphize, parameterize},
ret::spontaneous_panic,
};
use crate::{
addressing_modes::{
Expand Down Expand Up @@ -77,15 +78,15 @@ fn load<T: Tracer, W, H: HeapFromState, In: Source, const INCREMENT: bool>(

let new_bound = address.wrapping_add(32);
if grow_heap::<_, _, H>(&mut vm.state, new_bound).is_err() {
vm.state.current_frame.pc = &*vm.panic;
vm.state.current_frame.pc = spontaneous_panic();
return;
};

// The heap is always grown even when the index nonsensical.
// TODO PLA-974 revert to not growing the heap on failure as soon as zk_evm is fixed
if bigger_than_last_address(pointer) {
let _ = vm.state.use_gas(u32::MAX);
vm.state.current_frame.pc = &*vm.panic;
vm.state.current_frame.pc = spontaneous_panic();
return;
}

Expand Down Expand Up @@ -119,15 +120,15 @@ where

let new_bound = address.wrapping_add(32);
if grow_heap::<_, _, H>(&mut vm.state, new_bound).is_err() {
vm.state.current_frame.pc = &*vm.panic;
vm.state.current_frame.pc = spontaneous_panic();
return ExecutionStatus::Running;
}

// The heap is always grown even when the index nonsensical.
// TODO PLA-974 revert to not growing the heap on failure as soon as zk_evm is fixed
if bigger_than_last_address(pointer) {
let _ = vm.state.use_gas(u32::MAX);
vm.state.current_frame.pc = &*vm.panic;
vm.state.current_frame.pc = spontaneous_panic();
return ExecutionStatus::Running;
}

Expand Down Expand Up @@ -170,7 +171,7 @@ fn load_pointer<T: Tracer, W, const INCREMENT: bool>(
boilerplate::<opcodes::PointerRead, _, _>(vm, world, tracer, |vm, args| {
let (input, input_is_pointer) = Register1::get_with_pointer_flag(args, &mut vm.state);
if !input_is_pointer {
vm.state.current_frame.pc = &*vm.panic;
vm.state.current_frame.pc = spontaneous_panic();
return;
}
let pointer = FatPointer::from(input);
Expand All @@ -179,7 +180,7 @@ fn load_pointer<T: Tracer, W, const INCREMENT: bool>(
// but if offset + 32 is not representable, we panic, even if we could've read some bytes.
// This is not a bug, this is how it must work to be backwards compatible.
if pointer.offset > LAST_ADDRESS {
vm.state.current_frame.pc = &*vm.panic;
vm.state.current_frame.pc = spontaneous_panic();
return;
};

Expand Down
5 changes: 4 additions & 1 deletion crates/vm2/src/instruction_handlers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#[cfg(feature = "single_instruction_test")]
pub(crate) use ret::spontaneous_panic;

pub(crate) use self::{
context::address_into_u256,
heap_access::{AuxHeap, Heap},
ret::{invalid_instruction, RETURN_COST},
ret::invalid_instruction,
};

mod binop;
Expand Down
5 changes: 3 additions & 2 deletions crates/vm2/src/instruction_handlers/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use super::{
monomorphization::{
match_boolean, match_destination, match_source, monomorphize, parameterize,
},
ret::spontaneous_panic,
};
use crate::{
addressing_modes::{
Expand Down Expand Up @@ -39,12 +40,12 @@ fn ptr<T: Tracer, W, Op: PtrOp, In1: Source, Out: Destination, const SWAP: bool>
};

if !a_is_pointer || b_is_pointer {
vm.state.current_frame.pc = &*vm.panic;
vm.state.current_frame.pc = spontaneous_panic();
return;
}

let Some(result) = Op::perform(a, b) else {
vm.state.current_frame.pc = &*vm.panic;
vm.state.current_frame.pc = spontaneous_panic();
return;
};

Expand Down
4 changes: 2 additions & 2 deletions crates/vm2/src/instruction_handlers/precompiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use zkevm_opcode_defs::{
};
use zksync_vm2_interface::{opcodes, CycleStats, HeapId, Tracer};

use super::common::boilerplate_ext;
use super::{common::boilerplate_ext, ret::spontaneous_panic};
use crate::{
addressing_modes::{Arguments, Destination, Register1, Register2, Source},
heap::Heaps,
Expand All @@ -35,7 +35,7 @@ fn precompile_call<T: Tracer, W>(
// This is safe because system contracts are trusted
let aux_data = PrecompileAuxData::from_u256(Register2::get(args, &mut vm.state));
let Ok(()) = vm.state.use_gas(aux_data.extra_ergs_cost) else {
vm.state.current_frame.pc = &*vm.panic;
vm.state.current_frame.pc = spontaneous_panic();
return;
};

Expand Down
40 changes: 33 additions & 7 deletions crates/vm2/src/instruction_handlers/ret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,39 @@ pub(crate) fn panic_from_failed_far_call<T: Tracer, W>(
tracer.after_instruction::<opcodes::Ret<Panic>, _>(vm);
}

/// Panics, burning all available gas.
static INVALID_INSTRUCTION: Instruction<(), ()> = Instruction::from_invalid();
fn invalid<T: Tracer, W>(
vm: &mut VirtualMachine<T, W>,
_: &mut W,
tracer: &mut T,
) -> ExecutionStatus {
vm.state.current_frame.gas = 0;
free_panic(vm, tracer)
}

trait GenericStatics<T, W> {
const PANIC: Instruction<T, W>;
const INVALID: Instruction<T, W>;
}

pub(crate) fn invalid_instruction<'a, T, W>() -> &'a Instruction<T, W> {
// Safety: the handler of an invalid instruction is never read.
unsafe { &*std::ptr::addr_of!(INVALID_INSTRUCTION).cast() }
impl<T: Tracer, W> GenericStatics<T, W> for () {
const PANIC: Instruction<T, W> = Instruction {
handler: ret::<T, W, Panic, false>,
arguments: Arguments::new(Predicate::Always, RETURN_COST, ModeRequirements::none()),
};
const INVALID: Instruction<T, W> = Instruction::from_invalid();
}

// The following functions return references that live for 'static.
// They aren't marked as such because returning any lifetime is more ergonomic.

/// Point the program counter at this instruction when a panic occurs during the logic of and instruction.
pub(crate) fn spontaneous_panic<'a, T: Tracer, W>() -> &'a Instruction<T, W> {
&<()>::PANIC
}

/// Panics, burning all available gas.
pub(crate) fn invalid_instruction<'a, T: Tracer, W>() -> &'a Instruction<T, W> {
&<()>::INVALID
}

pub(crate) const RETURN_COST: u32 = 5;
Expand Down Expand Up @@ -214,8 +241,7 @@ impl<T: Tracer, W> Instruction<T, W> {
/// Creates a *invalid* instruction that will panic by draining all gas.
pub const fn from_invalid() -> Self {
Self {
// This field is never read because the instruction fails at the gas cost stage.
handler: ret::<T, W, Panic, false>,
handler: invalid,
arguments: Arguments::new(
Predicate::Always,
INVALID_INSTRUCTION_COST,
Expand Down
2 changes: 1 addition & 1 deletion crates/vm2/src/single_instruction_test/into_zk_evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn vm2_to_zk_evm<T: Tracer, W: World<T>>(
event_sink.start_frame(zk_evm::aux_structures::Timestamp(0));

VmState {
local_state: vm2_state_to_zk_evm_state(&vm.state, &*vm.panic),
local_state: vm2_state_to_zk_evm_state(&vm.state),
block_properties: BlockProperties {
default_aa_code_hash: U256::from_big_endian(&vm.settings.default_aa_code_hash),
evm_simulator_code_hash: U256::from_big_endian(&vm.settings.evm_interpreter_code_hash),
Expand Down
6 changes: 4 additions & 2 deletions crates/vm2/src/single_instruction_test/print_mock_info.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use zksync_vm2_interface::Tracer;

use crate::{callframe::Callframe, state::State, VirtualMachine};

impl<T, W> VirtualMachine<T, W> {
impl<T: Tracer, W> VirtualMachine<T, W> {
pub fn print_mock_info(&self) {
self.state.print_mock_info();
println!("Events: {:?}", self.world_diff.events());
Expand All @@ -12,7 +14,7 @@ impl<T, W> VirtualMachine<T, W> {
}
}

impl<T, W> State<T, W> {
impl<T: Tracer, W> State<T, W> {
pub(crate) fn print_mock_info(&self) {
if let Some((heap_id, heap)) = self.heaps.read.read_that_happened() {
println!("Heap: {heap_id:?}");
Expand Down
8 changes: 4 additions & 4 deletions crates/vm2/src/single_instruction_test/state_to_zk_evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ use zk_evm::{
vm_state::{execution_stack::CallStackEntry, Callstack, PrimitiveValue, VmLocalState},
};
use zkevm_opcode_defs::decoding::EncodingModeProduction;
use zksync_vm2_interface::Tracer;

use crate::{
callframe::{Callframe, NearCallFrame},
instruction_handlers::spontaneous_panic,
state::State,
Instruction,
};

pub(crate) fn vm2_state_to_zk_evm_state<T, W>(
pub(crate) fn vm2_state_to_zk_evm_state<T: Tracer, W>(
state: &State<T, W>,
panic: &Instruction<T, W>,
) -> VmLocalState<8, EncodingModeProduction> {
// zk_evm requires an unused bottom frame
let mut callframes: Vec<_> = iter::once(CallStackEntry::empty_context())
Expand Down Expand Up @@ -51,7 +51,7 @@ pub(crate) fn vm2_state_to_zk_evm_state<T, W>(
memory_page_counter: 3000,
absolute_execution_step: 0,
tx_number_in_block: state.transaction_number,
pending_exception: state.current_frame.pc == panic,
pending_exception: state.current_frame.pc == spontaneous_panic(),
previous_super_pc: 0, // Same as current pc so the instruction is read from previous_code_word
context_u128_register: state.context_u128,
callstack: Callstack {
Expand Down
8 changes: 2 additions & 6 deletions crates/vm2/src/single_instruction_test/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use zksync_vm2_interface::{HeapId, Tracer};

use super::{heap::Heaps, stack::StackPool};
use crate::{
addressing_modes::Arguments, callframe::Callframe, fat_pointer::FatPointer, state::State,
Instruction, ModeRequirements, Predicate, Settings, VirtualMachine, World, WorldDiff,
callframe::Callframe, fat_pointer::FatPointer, state::State, Settings, VirtualMachine, World,
WorldDiff,
};

impl<T: Tracer, W> VirtualMachine<T, W> {
Expand Down Expand Up @@ -79,10 +79,6 @@ impl<'a, T: Tracer, W: World<T>> Arbitrary<'a> for VirtualMachine<T, W> {
settings: u.arbitrary()?,
world_diff: WorldDiff::default(),
stack_pool: StackPool {},
panic: Box::new(Instruction::from_panic(
None,
Arguments::new(Predicate::Always, 5, ModeRequirements::none()),
)),
snapshot: None,
})
}
Expand Down
20 changes: 11 additions & 9 deletions crates/vm2/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use primitive_types::{H160, U256};
use zksync_vm2_interface::HeapId;
use zksync_vm2_interface::{HeapId, Tracer};

use crate::{
addressing_modes::Addressable,
Expand Down Expand Up @@ -86,6 +86,16 @@ impl<T, W> State<T, W> {
}
}

pub(crate) fn set_context_u128(&mut self, value: u128) {
self.context_u128 = value;
}

pub(crate) fn get_context_u128(&self) -> u128 {
self.current_frame.context_u128
}
}

impl<T: Tracer, W> State<T, W> {
/// Returns the total unspent gas in the VM, including stipends.
pub(crate) fn total_unspent_gas(&self) -> u32 {
self.current_frame.gas
Expand All @@ -96,14 +106,6 @@ impl<T, W> State<T, W> {
.sum::<u32>()
}

pub(crate) fn set_context_u128(&mut self, value: u128) {
self.context_u128 = value;
}

pub(crate) fn get_context_u128(&self) -> u128 {
self.current_frame.context_u128
}

pub(crate) fn snapshot(&self) -> StateSnapshot {
StateSnapshot {
registers: self.registers,
Expand Down
14 changes: 2 additions & 12 deletions crates/vm2/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ use primitive_types::H160;
use zksync_vm2_interface::{opcodes::TypeLevelCallingMode, CallingMode, HeapId, Tracer};

use crate::{
addressing_modes::Arguments,
callframe::{Callframe, FrameRemnant},
decommit::u256_into_address,
instruction::ExecutionStatus,
instruction_handlers::RETURN_COST,
stack::StackPool,
state::{State, StateSnapshot},
world_diff::{ExternalSnapshot, Snapshot, WorldDiff},
ExecutionEnd, Instruction, ModeRequirements, Predicate, Program, World,
ExecutionEnd, Program, World,
};

/// [`VirtualMachine`] settings.
Expand All @@ -33,9 +31,6 @@ pub struct VirtualMachine<T, W> {
pub(crate) state: State<T, W>,
pub(crate) settings: Settings,
pub(crate) stack_pool: StackPool,
/// Instruction that is jumped to when things go wrong while executing another.
/// Boxed, so the pointer isn't invalidated by moves.
pub(crate) panic: Box<Instruction<T, W>>,
pub(crate) snapshot: Option<VmSnapshot>,
}

Expand Down Expand Up @@ -66,10 +61,6 @@ impl<T: Tracer, W: World<T>> VirtualMachine<T, W> {
),
settings,
stack_pool,
panic: Box::new(Instruction::from_panic(
None,
Arguments::new(Predicate::Always, RETURN_COST, ModeRequirements::none()),
)),
snapshot: None,
}
}
Expand Down Expand Up @@ -199,8 +190,7 @@ impl<T: Tracer, W: World<T>> VirtualMachine<T, W> {
}
}

// Private methods. We don't constrain `T` and `W` to ease potential refactoring.
impl<T, W> VirtualMachine<T, W> {
impl<T: Tracer, W> VirtualMachine<T, W> {
#[allow(clippy::too_many_arguments)]
pub(crate) fn push_frame<M: TypeLevelCallingMode>(
&mut self,
Expand Down

0 comments on commit d4ab3d3

Please sign in to comment.