Skip to content

Commit

Permalink
Move result parsing to tracer manager
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcosNicolau committed Aug 23, 2024
1 parent e0a1890 commit 5010795
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 88 deletions.
66 changes: 63 additions & 3 deletions core/lib/multivm/src/versions/era_vm/tracers/manager.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use era_vm::{execution::Execution, opcode::Opcode, state::VMState, tracers::tracer::Tracer};
use era_vm::{
execution::Execution, opcode::Opcode, state::VMState, tracers::tracer::Tracer,
vm::ExecutionOutput,
};
use zksync_state::{ReadStorage, StoragePtr};

use super::{
Expand All @@ -9,10 +12,17 @@ use super::{
result_tracer::ResultTracer,
traits::{ExecutionResult, VmTracer},
};
use crate::{era_vm::vm::Vm, vm_1_4_1::VmExecutionMode};
use crate::{
era_vm::{bootloader_state::utils::apply_l2_block, hook::Hook, vm::Vm},
interface::{Halt, TxRevertReason},
vm_1_4_1::VmExecutionMode,
};

// this tracer manager is the one that gets called when running the vm
// all the logic of hooks and results parsing is managed from here
// the most important tracers are: `result_tracer`, `refund_tracer`, `pubdata_tracer`,
pub struct VmTracerManager<S: ReadStorage> {
execution_mode: VmExecutionMode,
pub dispatcher: TracerDispatcher<S>,
pub result_tracer: ResultTracer,
// This tracer is designed specifically for calculating refunds and saves the results to `VmResultAndLogs`.
Expand All @@ -25,14 +35,15 @@ pub struct VmTracerManager<S: ReadStorage> {
storage: StoragePtr<S>,
}

impl<S: ReadStorage> VmTracerManager<S> {
impl<S: ReadStorage + 'static> VmTracerManager<S> {
pub fn new(
execution_mode: VmExecutionMode,
storage: StoragePtr<S>,
dispatcher: TracerDispatcher<S>,
refund_tracer: Option<RefundsTracer>,
) -> Self {
Self {
execution_mode,
dispatcher,
refund_tracer,
circuits_tracer: CircuitsTracer::new(),
Expand All @@ -41,6 +52,55 @@ impl<S: ReadStorage> VmTracerManager<S> {
storage,
}
}

pub fn after_vm_run(
&mut self,
vm: &mut Vm<S>,
output: ExecutionOutput,
) -> Option<ExecutionResult> {
match output {
ExecutionOutput::Ok(output) => Some(ExecutionResult::Success { output }),
ExecutionOutput::Revert(output) => match TxRevertReason::parse_error(&output) {
TxRevertReason::TxReverted(output) => (Some(ExecutionResult::Revert { output })),
TxRevertReason::Halt(reason) => Some(ExecutionResult::Halt { reason }),
},
ExecutionOutput::Panic => Some(ExecutionResult::Halt {
reason: if vm.inner.execution.gas_left().unwrap() == 0 {
Halt::BootloaderOutOfGas
} else {
Halt::VMPanic
},
}),
ExecutionOutput::SuspendedOnHook {
hook,
pc_to_resume_from,
} => {
vm.suspended_at = pc_to_resume_from;
vm.inner.execution.current_frame_mut().unwrap().pc = vm.suspended_at as u64;
let hook = Hook::from_u32(hook);
match hook {
Hook::TxHasEnded => {
if let VmExecutionMode::OneTx = self.execution_mode {
return self.result_tracer.last_tx_result.take();
}
}
Hook::FinalBatchInfo => self.set_final_batch_info(vm),
_ => {}
}
self.bootloader_hook_call(vm, hook, &vm.get_hook_params());
None
}
}
}

fn set_final_batch_info(&self, vm: &mut Vm<S>) {
// set fictive l2 block
let txs_index = vm.bootloader_state.free_tx_index();
let l2_block = vm.bootloader_state.insert_fictive_l2_block();
let mut memory = vec![];
apply_l2_block(&mut memory, l2_block, txs_index);
vm.write_to_bootloader_heap(memory);
}
}

impl<S: ReadStorage> Tracer for VmTracerManager<S> {
Expand Down
97 changes: 12 additions & 85 deletions core/lib/multivm/src/versions/era_vm/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,92 +150,19 @@ impl<S: ReadStorage + 'static> VmFactory<S> for Vm<S> {
}

impl<S: ReadStorage + 'static> Vm<S> {
pub fn run(
&mut self,
execution_mode: VmExecutionMode,
tracer: &mut impl VmTracer<S>,
) -> ExecutionResult {
let mut last_tx_result = None;

pub fn run(&mut self, tracer: &mut VmTracerManager<S>) -> ExecutionResult {
tracer.before_bootloader_execution(self);
let stop_reason = loop {
let result = self.inner.run_program_with_custom_bytecode(Some(tracer));

let result = match result {
ExecutionOutput::Ok(output) => break (ExecutionResult::Success { output }),
ExecutionOutput::Revert(output) => match TxRevertReason::parse_error(&output) {
TxRevertReason::TxReverted(output) => {
break (ExecutionResult::Revert { output })
}
TxRevertReason::Halt(reason) => break (ExecutionResult::Halt { reason }),
},
ExecutionOutput::Panic => {
break ExecutionResult::Halt {
reason: if self.inner.execution.gas_left().unwrap() == 0 {
Halt::BootloaderOutOfGas
} else {
Halt::VMPanic
},
}
}
ExecutionOutput::SuspendedOnHook {
hook,
pc_to_resume_from,
} => {
self.suspended_at = pc_to_resume_from;
self.inner.execution.current_frame_mut().unwrap().pc = self.suspended_at as u64;
hook
}
};

tracer.bootloader_hook_call(self, Hook::from_u32(result), &self.get_hook_params());

match Hook::from_u32(result) {
Hook::FinalBatchInfo => {
// set fictive l2 block
let txs_index = self.bootloader_state.free_tx_index();
let l2_block = self.bootloader_state.insert_fictive_l2_block();
let mut memory = vec![];
apply_l2_block(&mut memory, l2_block, txs_index);
self.write_to_bootloader_heap(memory);
}
Hook::PostResult => {
let result = self.get_hook_params()[0];
let value = self.get_hook_params()[1];
let pointer = FatPointer::decode(value);
assert_eq!(pointer.offset, 0);

let return_data = self
.inner
.execution
.heaps
.get(pointer.page)
.unwrap()
.read_unaligned_from_pointer(&pointer)
.unwrap();

last_tx_result = Some(if result.is_zero() {
ExecutionResult::Revert {
output: VmRevertReason::from(return_data.as_slice()),
}
} else {
ExecutionResult::Success {
output: return_data,
}
});
}
Hook::TxHasEnded => {
if let VmExecutionMode::OneTx = execution_mode {
break last_tx_result.take().unwrap();
}
}
_ => {}
}
};
loop {
let output = self.inner.run_program_with_custom_bytecode(Some(tracer));

tracer.after_bootloader_execution(self, stop_reason.clone());
let result = tracer.after_vm_run(self, output);

stop_reason
if result.is_some() {
let result = result.unwrap();
tracer.after_bootloader_execution(self, result.clone());
return result;
}
}
}

pub(crate) fn insert_bytecodes<'a>(&mut self, bytecodes: impl IntoIterator<Item = &'a [u8]>) {
Expand All @@ -254,7 +181,7 @@ impl<S: ReadStorage + 'static> Vm<S> {
}
}

fn get_hook_params(&self) -> [U256; 3] {
pub fn get_hook_params(&self) -> [U256; 3] {
let vm_hooks_param_start = get_vm_hook_start_position_latest();
(vm_hooks_param_start..vm_hooks_param_start + VM_HOOK_PARAMS_COUNT)
.map(|word| {
Expand Down Expand Up @@ -404,7 +331,7 @@ impl<S: ReadStorage + 'static> VmInterface for Vm<S> {
);
let snapshot = self.inner.state.snapshot();

let result = self.run(execution_mode, &mut tracer);
let result = self.run(&mut tracer);

let ignore_world_diff = matches!(execution_mode, VmExecutionMode::OneTx)
&& matches!(result, ExecutionResult::Halt { .. });
Expand Down

0 comments on commit 5010795

Please sign in to comment.