Skip to content

Commit

Permalink
feat: add vm error tracer (#594)
Browse files Browse the repository at this point in the history
* add vm error tracer
  • Loading branch information
nbaztec committed Sep 26, 2024
1 parent d1b59e9 commit 2aa8fa7
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 10 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions crates/zksync/core/src/vm/inspect.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use alloy_primitives::{hex, Log};
use era_test_node::{
bootloader_debug::{BootloaderDebug, BootloaderDebugTracer},
config::node::ShowCalls,
formatter,
system_contracts::{Options, SystemContracts},
Expand Down Expand Up @@ -43,7 +42,11 @@ use crate::{
db::{ZKVMData, DEFAULT_CHAIN_ID},
env::{create_l1_batch_env, create_system_env},
storage_view::StorageView,
tracer::{CallContext, CheatcodeTracer, CheatcodeTracerContext},
tracers::{
bootloader::{BootloaderDebug, BootloaderDebugTracer},
cheatcode::{CallContext, CheatcodeTracer, CheatcodeTracerContext},
error::ErrorTracer,
},
},
};
use foundry_evm_abi::{
Expand Down Expand Up @@ -437,6 +440,7 @@ fn inspect_inner<S: ReadStorage>(
let is_create = call_ctx.is_create;
let bootloader_debug_tracer_result = Arc::new(OnceCell::default());
let tracers = vec![
ErrorTracer.into_tracer_pointer(),
CallTracer::new(call_tracer_result.clone()).into_tracer_pointer(),
BootloaderDebugTracer { result: bootloader_debug_tracer_result.clone() }
.into_tracer_pointer(),
Expand Down
4 changes: 2 additions & 2 deletions crates/zksync/core/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ mod farcall;
mod inspect;
mod runner;
mod storage_view;
mod tracer;
mod tracers;

pub use inspect::{
batch_factory_dependencies, inspect, inspect_as_batch, ZKVMExecutionResult, ZKVMResult,
};
pub use runner::{balance, call, code_hash, create, encode_create_params, nonce, transact};
pub use tracer::CheatcodeTracerContext;
pub use tracers::cheatcode::CheatcodeTracerContext;
2 changes: 1 addition & 1 deletion crates/zksync/core/src/vm/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
vm::{
db::ZKVMData,
inspect::{inspect, inspect_as_batch, ZKVMExecutionResult, ZKVMResult},
tracer::{CallContext, CheatcodeTracerContext},
tracers::cheatcode::{CallContext, CheatcodeTracerContext},
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@ use zksync_utils::bytecode::hash_bytecode;

use crate::{
convert::{ConvertAddress, ConvertH160, ConvertH256, ConvertU256},
vm::farcall::{CallAction, CallDepth},
vm::farcall::{CallAction, CallDepth, FarCallHandler},
ZkPaymasterData, EMPTY_CODE,
};

use super::farcall::FarCallHandler;

/// Selector for retrieving account version.
/// This is used to override the caller's account version when deploying a contract
/// So non-EOA addresses can also deploy within the VM.
Expand Down
51 changes: 51 additions & 0 deletions crates/zksync/core/src/vm/tracers/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use multivm::{
interface::dyn_tracers::vm_1_5_0::DynTracer,
vm_latest::{HistoryMode, SimpleMemory, VmTracer},
zk_evm_latest::{
tracing::{AfterDecodingData, VmLocalStateData},
vm_state::ErrorFlags,
},
};
use zksync_state::{ReadStorage, WriteStorage};

/// A tracer to allow logging low-level vm errors.
#[derive(Debug, Default)]
pub struct ErrorTracer;

impl<S: ReadStorage, H: HistoryMode> DynTracer<S, SimpleMemory<H>> for ErrorTracer {
fn after_decoding(
&mut self,
_state: VmLocalStateData<'_>,
data: AfterDecodingData,
_memory: &SimpleMemory<H>,
) {
if data.error_flags_accumulated.is_empty() {
return;
}

let errors = parse_error_flags(&data.error_flags_accumulated);
tracing::error!("vm error: {}", errors.join(", "));
}
}

impl<S: WriteStorage, H: HistoryMode> VmTracer<S, H> for ErrorTracer {}

fn parse_error_flags(error_flags: &ErrorFlags) -> Vec<String> {
let mut errors = vec![];
if error_flags.contains(ErrorFlags::INVALID_OPCODE) {
errors.push(String::from("Invalid opcode"));
}
if error_flags.contains(ErrorFlags::NOT_ENOUGH_ERGS) {
errors.push(String::from("Not enough gas"));
}
if error_flags.contains(ErrorFlags::PRIVILAGED_ACCESS_NOT_FROM_KERNEL) {
errors.push(String::from("Unauthorized privileged access"));
}
if error_flags.contains(ErrorFlags::WRITE_IN_STATIC_CONTEXT) {
errors.push(String::from("Write applied in static context"));
}
if error_flags.contains(ErrorFlags::CALLSTACK_IS_FULL) {
errors.push(String::from("Call stack full"));
}
errors
}
7 changes: 7 additions & 0 deletions crates/zksync/core/src/vm/tracers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// Contains tracer implementations for the zkEVM

pub mod bootloader {
pub use era_test_node::bootloader_debug::{BootloaderDebug, BootloaderDebugTracer};
}
pub mod cheatcode;
pub mod error;

0 comments on commit 2aa8fa7

Please sign in to comment.