use crate::zkevm_opcode_defs::decoding::encoding_mode_production::EncodingModeProduction;
use crate::zkevm_opcode_defs::decoding::VmEncodingMode;
use crate::zkevm_opcode_defs::ISAVersion;
use super::*;
use crate::flags::Flags;
use crate::zkevm_opcode_defs::decoding::AllowedPcOrImm;
use zk_evm_abstractions::aux::MemoryPage;
use zk_evm_abstractions::aux::PubdataCost;
use zk_evm_abstractions::aux::Timestamp;
pub mod cycle;
pub mod execution_stack;
pub mod helpers;
pub mod mem_ops;
pub use self::cycle::*;
pub use self::execution_stack::*;
pub use self::helpers::*;
pub use self::mem_ops::*;
pub const SUPPORTED_ISA_VERSION: ISAVersion = ISAVersion(2);
const _: () = if SUPPORTED_ISA_VERSION.0 != zkevm_opcode_defs::DEFAULT_ISA_VERSION.0 {
panic!()
};
use crate::zkevm_opcode_defs::{STARTING_BASE_PAGE, STARTING_TIMESTAMP};
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct PrimitiveValue {
pub value: U256,
pub is_pointer: bool,
}
impl PrimitiveValue {
pub const fn empty() -> Self {
Self {
value: U256::zero(),
is_pointer: false,
}
}
pub const fn from_value(value: U256) -> Self {
Self {
value,
is_pointer: false,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct VmLocalState<const N: usize = 8, E: VmEncodingMode<N> = EncodingModeProduction> {
pub previous_code_word: U256,
pub previous_code_memory_page: MemoryPage,
pub registers: [PrimitiveValue; zkevm_opcode_defs::REGISTERS_COUNT],
pub flags: Flags,
pub timestamp: u32,
pub monotonic_cycle_counter: u32,
pub spent_pubdata_counter: u32,
pub memory_page_counter: u32,
pub absolute_execution_step: u32,
pub tx_number_in_block: u16,
pub pending_exception: bool,
pub previous_super_pc: E::PcOrImm,
pub context_u128_register: u128,
pub callstack: Callstack<N, E>,
pub pubdata_revert_counter: PubdataCost,
}
impl<const N: usize, E: VmEncodingMode<N>> VmLocalState<N, E> {
pub fn empty_state() -> Self {
Self {
previous_code_word: U256::zero(),
previous_code_memory_page: MemoryPage(0u32),
registers: [PrimitiveValue::empty(); zkevm_opcode_defs::REGISTERS_COUNT],
flags: Flags::empty(),
timestamp: STARTING_TIMESTAMP,
monotonic_cycle_counter: 0u32,
spent_pubdata_counter: 0u32,
memory_page_counter: STARTING_BASE_PAGE,
absolute_execution_step: 0,
tx_number_in_block: 0,
previous_super_pc: E::PcOrImm::from_u64_clipped(0),
pending_exception: false,
context_u128_register: 0u128,
callstack: Callstack::empty(),
pubdata_revert_counter: PubdataCost(0i32),
}
}
pub fn execution_has_ended(&self) -> bool {
self.callstack.is_empty()
}
pub fn timestamp_for_code_or_src_read(&self) -> Timestamp {
Timestamp(self.timestamp)
}
pub fn callstack_is_full(&self) -> bool {
self.callstack.is_full()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct DelayedLocalStateChanges<
const N: usize = 8,
E: VmEncodingMode<N> = EncodingModeProduction,
> {
pub new_ergs_remaining: Option<u32>,
pub new_previous_code_word: Option<U256>,
pub new_previous_super_pc: Option<E::PcOrImm>,
pub new_pending_exception: Option<bool>,
pub new_previous_code_memory_page: Option<MemoryPage>,
}
impl<const N: usize, E: VmEncodingMode<N>> Default for DelayedLocalStateChanges<N, E> {
fn default() -> Self {
Self {
new_ergs_remaining: None,
new_previous_code_word: None,
new_previous_super_pc: None,
new_pending_exception: None,
new_previous_code_memory_page: None,
}
}
}
impl<const N: usize, E: VmEncodingMode<N>> DelayedLocalStateChanges<N, E> {
pub fn apply(self, local_state: &mut VmLocalState<N, E>) {
if let Some(ergs_remaining) = self.new_ergs_remaining {
local_state.callstack.get_current_stack_mut().ergs_remaining = ergs_remaining;
}
if let Some(previous_code_word) = self.new_previous_code_word {
local_state.previous_code_word = previous_code_word;
}
if let Some(previous_super_pc) = self.new_previous_super_pc {
local_state.previous_super_pc = previous_super_pc;
}
if let Some(new_pending_exception) = self.new_pending_exception {
local_state.pending_exception = new_pending_exception;
}
if let Some(new_previous_code_memory_page) = self.new_previous_code_memory_page {
local_state.previous_code_memory_page = new_previous_code_memory_page;
}
}
}
#[derive(Debug)]
pub struct VmState<
S: zk_evm_abstractions::vm::Storage,
M: zk_evm_abstractions::vm::Memory,
EV: zk_evm_abstractions::vm::EventSink,
PP: zk_evm_abstractions::vm::PrecompilesProcessor,
DP: zk_evm_abstractions::vm::DecommittmentProcessor,
WT: crate::witness_trace::VmWitnessTracer<N, E>,
const N: usize = 8,
E: VmEncodingMode<N> = EncodingModeProduction,
> {
pub local_state: VmLocalState<N, E>,
pub block_properties: crate::block_properties::BlockProperties,
pub storage: S,
pub memory: M,
pub event_sink: EV,
pub precompiles_processor: PP,
pub decommittment_processor: DP,
pub witness_tracer: WT,
pub version: Version,
pub dst1_was_updated_this_cycle: bool,
}
#[non_exhaustive]
#[derive(Debug, PartialEq, PartialOrd)]
pub enum Version {
Initial = 0,
Version27 = 1,
}
impl Version {
pub fn latest() -> Self {
Version::Version27
}
}
impl<
S: zk_evm_abstractions::vm::Storage,
M: zk_evm_abstractions::vm::Memory,
EV: zk_evm_abstractions::vm::EventSink,
PP: zk_evm_abstractions::vm::PrecompilesProcessor,
DP: zk_evm_abstractions::vm::DecommittmentProcessor,
WT: crate::witness_trace::VmWitnessTracer<N, E>,
const N: usize,
E: VmEncodingMode<N>,
> VmState<S, M, EV, PP, DP, WT, N, E>
{
pub fn empty_state(
storage: S,
memory: M,
event_sink: EV,
precompiles_processor: PP,
decommittment_processor: DP,
witness_tracer: WT,
block_properties: crate::block_properties::BlockProperties,
version: Version,
) -> Self {
Self {
local_state: VmLocalState::empty_state(),
storage,
memory,
event_sink,
precompiles_processor,
decommittment_processor,
witness_tracer,
block_properties,
version,
dst1_was_updated_this_cycle: false,
}
}
pub fn reset_flags(&mut self) {
self.local_state.flags.reset();
}
pub fn callstack_is_full(&self) -> bool {
self.local_state.callstack_is_full()
}
pub fn execution_has_ended(&self) -> bool {
self.local_state.execution_has_ended()
}
pub fn compute_if_should_skip_cycle(&mut self) -> bool {
self.execution_has_ended()
}
pub fn timestamp_for_code_or_src_read(&self) -> Timestamp {
self.local_state.timestamp_for_code_or_src_read()
}
pub fn timestamp_for_first_decommit_or_precompile_read(&self) -> Timestamp {
Timestamp(self.local_state.timestamp + 1)
}
pub fn timestamp_for_second_decommit_or_precompile_write(&self) -> Timestamp {
Timestamp(self.local_state.timestamp + 2)
}
pub fn timestamp_for_dst_write(&self) -> Timestamp {
Timestamp(self.local_state.timestamp + 3)
}
pub fn increment_timestamp_after_cycle(&mut self) {
self.local_state.timestamp += zkevm_opcode_defs::TIME_DELTA_PER_CYCLE
}
pub fn new_base_memory_page_on_call(&self) -> MemoryPage {
MemoryPage(self.local_state.memory_page_counter)
}
pub fn increment_memory_pages_on_call(&mut self) {
self.local_state.memory_page_counter += zkevm_opcode_defs::NEW_MEMORY_PAGES_PER_FAR_CALL;
}
}