Skip to content
This repository has been archived by the owner on Aug 16, 2024. It is now read-only.

Commit

Permalink
mirror 4659a6e2dfe72b6d37e895e9cad7e2564d4ea4dc (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
mm-zk authored May 24, 2024
1 parent 9bbf7ff commit 0c5cdca
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 47 deletions.
2 changes: 0 additions & 2 deletions src/opcodes/execution/far_call.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use super::*;

use crate::zkevm_opcode_defs::definitions::far_call::*;
use crate::zkevm_opcode_defs::system_params::DEPLOYER_SYSTEM_CONTRACT_ADDRESS;
use crate::zkevm_opcode_defs::system_params::STORAGE_AUX_BYTE;

use crate::zkevm_opcode_defs::INITIAL_SP_ON_FAR_CALL;
use zk_evm_abstractions::aux::*;
Expand Down
125 changes: 80 additions & 45 deletions src/vm_state/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,49 @@ pub struct PreState<const N: usize = 8, E: VmEncodingMode<N> = EncodingModeProdu
pub const OPCODES_PER_WORD_LOG_2: usize = 2;
pub const OPCODES_PER_WORD: usize = 1 << OPCODES_PER_WORD_LOG_2;

fn read_and_cache_opcode<
const N: usize,
E: VmEncodingMode<N>,
M: zk_evm_abstractions::vm::Memory,
WT: crate::witness_trace::VmWitnessTracer<N, E>,
>(
local_state: &VmLocalState<N, E>,
memory: &M,
witness_tracer: &mut WT,
super_pc: <E as VmEncodingMode<N>>::PcOrImm,
delayed_changes: &mut DelayedLocalStateChanges<N, E>,
) -> U256 {
// we need to read the code word and select a proper subword
use zk_evm_abstractions::auxiliary::*;
use zk_evm_abstractions::vm::*;

let code_page = local_state.callstack.get_current_stack().code_page;
let location = MemoryLocation {
memory_type: MemoryType::Code,
page: code_page,
index: MemoryIndex(super_pc.as_u64() as u32),
};
let key = MemoryKey {
timestamp: local_state.timestamp_for_code_or_src_read(),
location,
};

assert!(delayed_changes.new_previous_code_memory_page.is_some());

// code read is never pending
let code_query = read_code(
memory,
witness_tracer,
local_state.monotonic_cycle_counter,
key,
);
let u256_word = code_query.value;
delayed_changes.new_previous_code_word = Some(u256_word);
delayed_changes.new_previous_super_pc = Some(super_pc);

u256_word
}

pub fn read_and_decode<
const N: usize,
E: VmEncodingMode<N>,
Expand Down Expand Up @@ -55,64 +98,56 @@ pub fn read_and_decode<
!= local_state.previous_code_memory_page;
let (super_pc, sub_pc) = E::split_pc(pc);

let refresh_opcode_cache = match (code_pages_are_different, previous_super_pc == super_pc) {
(true, _) | (false, false) => true,
_ => false,
};

// if we do not skip cycle then we read memory for a new opcode
let opcode_encoding = if execution_has_ended == false && pending_exception == false {
let raw_opcode_u64 = match (code_pages_are_different, previous_super_pc == super_pc) {
(true, _) | (false, false) => {
// we need to read the code word and select a proper subword
let code_page = local_state.callstack.get_current_stack().code_page;
let location = MemoryLocation {
memory_type: MemoryType::Code,
page: code_page,
index: MemoryIndex(super_pc.as_u64() as u32),
};
let key = MemoryKey {
timestamp: local_state.timestamp_for_code_or_src_read(),
location,
};

delayed_changes.new_previous_code_memory_page = Some(code_page);

// code read is never pending
let code_query = read_code(
memory,
witness_tracer,
local_state.monotonic_cycle_counter,
key,
);
let u256_word = code_query.value;
delayed_changes.new_previous_code_word = Some(u256_word);
delayed_changes.new_previous_super_pc = Some(super_pc);

// our memory is a set of words in storage, and those are only re-interpreted
// as bytes in UMA. But natural storage for code is still bytes.

// to ensure consistency with the future if we allow deployment of raw bytecode
// then for our BE machine we should consider that "first" bytes, that will be
// our integer's "highest" bytes, so to follow bytearray-like enumeration we
// have to use inverse order here
let u256_word = u256_word;
E::integer_representaiton_from_u256(u256_word, sub_pc)
}
(false, true) => {
// use a saved one
let u256_word = local_state.previous_code_word;
E::integer_representaiton_from_u256(u256_word, sub_pc)
}
let raw_opcode_u64 = if refresh_opcode_cache {
// we need to read the code word and select a proper subword
let u256_word = read_and_cache_opcode(
local_state,
memory,
witness_tracer,
super_pc,
&mut delayed_changes,
);
// our memory is a set of words in storage, and those are only re-interpreted
// as bytes in UMA. But natural storage for code is still bytes.

// to ensure consistency with the future if we allow deployment of raw bytecode
// then for our BE machine we should consider that "first" bytes, that will be
// our integer's "highest" bytes, so to follow bytearray-like enumeration we
// have to use inverse order here
let u256_word = u256_word;
E::integer_representaiton_from_u256(u256_word, sub_pc)
} else {
// use a saved one
let u256_word = local_state.previous_code_word;
E::integer_representaiton_from_u256(u256_word, sub_pc)
};

raw_opcode_u64
} else if pending_exception {
// there are no cases that set pending exception and
// simultaneously finish the execution
assert!(execution_has_ended == false);
// if we have an exception then we should still read the word for cache, even if we will have PC later on updated
if refresh_opcode_cache {
let _ = read_and_cache_opcode(
local_state,
memory,
witness_tracer,
super_pc,
&mut delayed_changes,
);
}

// so we can just remove the marker as soon as we are no longer pending
delayed_changes.new_pending_exception = Some(false);

// anyway update super PC
delayed_changes.new_previous_super_pc = Some(super_pc);

E::exception_revert_encoding()
} else {
// we are skipping cycle for some reason, so we do nothing,
Expand Down
1 change: 1 addition & 0 deletions src/vm_state/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ impl<
(self.local_state.pubdata_revert_counter.0, false)
};
assert!(of == false);
assert!(new_revert_counter >= 0); // global counter can not be < 0, only local one can
self.local_state.pubdata_revert_counter = PubdataCost(new_revert_counter);

old_frame
Expand Down

0 comments on commit 0c5cdca

Please sign in to comment.