use std::iter;
use primitive_types::U256;
use zk_evm::{
aux_structures::{MemoryPage, PubdataCost},
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,
World,
};
pub(crate) fn vm2_state_to_zk_evm_state<T: Tracer, W: World<T>>(
state: &State<T, W>,
) -> VmLocalState<8, EncodingModeProduction> {
let mut callframes: Vec<_> = iter::once(CallStackEntry::empty_context())
.chain(
state
.previous_frames
.iter()
.cloned()
.chain(iter::once(state.current_frame.clone()))
.flat_map(vm2_frame_to_zk_evm_frames),
)
.collect();
VmLocalState {
previous_code_word: U256([0, 0, 0, state.current_frame.raw_first_instruction()]),
previous_code_memory_page: MemoryPage(0),
registers: state
.registers
.into_iter()
.enumerate()
.skip(1)
.map(|(i, value)| PrimitiveValue {
value,
is_pointer: state.register_pointer_flags & (1 << i) != 0,
})
.collect::<Vec<_>>()
.try_into()
.unwrap(),
flags: (&state.flags).into(),
timestamp: 0,
monotonic_cycle_counter: 0,
spent_pubdata_counter: 0, memory_page_counter: 3000,
absolute_execution_step: 0,
tx_number_in_block: state.transaction_number,
pending_exception: state.current_frame.pc == spontaneous_panic()
|| state.current_frame.program.raw_first_instruction == 0xBAD,
previous_super_pc: 0, context_u128_register: state.context_u128,
callstack: Callstack {
current: callframes.pop().unwrap(),
inner: callframes,
},
pubdata_revert_counter: PubdataCost(0),
}
}
fn vm2_frame_to_zk_evm_frames<T, W>(
frame: Callframe<T, W>,
) -> impl Iterator<Item = CallStackEntry> {
let far_frame = CallStackEntry {
this_address: frame.address,
msg_sender: frame.caller,
code_address: frame.code_address,
base_memory_page: MemoryPage(frame.heap.as_u32() - 2),
code_page: MemoryPage(0), sp: frame.sp,
pc: 0,
exception_handler_location: frame.exception_handler,
ergs_remaining: frame.gas,
this_shard_id: 0,
caller_shard_id: 0,
code_shard_id: 0,
is_static: frame.is_static,
is_local_frame: false,
context_u128_value: frame.context_u128,
heap_bound: frame.heap_size,
aux_heap_bound: frame.aux_heap_size,
total_pubdata_spent: PubdataCost(0),
stipend: 0,
};
let mut result = vec![far_frame];
for NearCallFrame {
exception_handler,
previous_frame_sp,
previous_frame_gas,
previous_frame_pc,
..
} in frame.near_calls
{
let last = result.last_mut().unwrap();
last.pc = previous_frame_pc;
last.sp = previous_frame_sp;
last.ergs_remaining = previous_frame_gas;
result.push(CallStackEntry {
is_local_frame: true,
exception_handler_location: exception_handler,
..far_frame
});
}
result.into_iter()
}