Skip to content

Commit

Permalink
improve vm tracing
Browse files Browse the repository at this point in the history
  • Loading branch information
ermalkaleci committed Mar 29, 2024
1 parent 3193640 commit 6b15017
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 187 deletions.
181 changes: 20 additions & 161 deletions modules/evm/src/runner/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub enum Event<'a> {
}

pub struct Tracer {
vm: bool,
events: Vec<CallTrace>,
stack: Vec<CallTrace>,
steps: Vec<Step>,
Expand All @@ -96,8 +97,9 @@ pub struct Tracer {
}

impl Tracer {
pub fn new() -> Self {
pub fn new(vm: bool) -> Self {
Self {
vm,
events: Vec::new(),
stack: Vec::new(),
steps: Vec::new(),
Expand Down Expand Up @@ -135,16 +137,24 @@ impl Tracer {
memory,
} => {
self.opcode = Some(opcode);
if !self.vm {
return;
}
self.steps.push(Step {
op: opcode.stringify().as_bytes().to_vec(),
pc: position.clone().unwrap_or_default() as u64,
depth: self.stack.last().map(|x| x.depth).unwrap_or_default(),
gas: if let Some(snapshot) = self.snapshot {
snapshot.gas()
} else {
0
},
stack: stack.data().clone(),
op: opcode,
pc: position.as_ref().map_or(0, |pc| *pc as u32),
depth: self.stack.last().map_or(0, |x| x.depth),
gas: self.snapshot.map_or(0, |s| s.gas()),
stack: stack
.data()
.iter()
.map(|x| {
let slice = x.as_fixed_bytes();
// trim left zeros
let start = slice.iter().position(|x| *x != 0).unwrap_or(31);
slice[start..].to_vec()
})
.collect(),
memory: if memory.is_empty() {
None
} else {
Expand Down Expand Up @@ -373,157 +383,6 @@ trait Stringify {
fn stringify(&self) -> &str;
}

impl Stringify for Opcode {
fn stringify(&self) -> &str {
match self {
&Opcode::STOP => "STOP",
&Opcode::ADD => "ADD",
&Opcode::MUL => "MUL",
&Opcode::SUB => "SUB",
&Opcode::DIV => "DIV",
&Opcode::SDIV => "SDIV",
&Opcode::MOD => "MOD",
&Opcode::SMOD => "SMOD",
&Opcode::ADDMOD => "ADDMOD",
&Opcode::MULMOD => "MULMOD",
&Opcode::EXP => "EXP",
&Opcode::SIGNEXTEND => "SIGNEXTEND",
&Opcode::LT => "LT",
&Opcode::GT => "GT",
&Opcode::SLT => "SLT",
&Opcode::SGT => "SGT",
&Opcode::EQ => "EQ",
&Opcode::ISZERO => "ISZERO",
&Opcode::AND => "AND",
&Opcode::OR => "OR",
&Opcode::XOR => "XOR",
&Opcode::NOT => "NOT",
&Opcode::BYTE => "BYTE",
&Opcode::SHL => "SHL",
&Opcode::SHR => "SHR",
&Opcode::SAR => "SAR",
&Opcode::SHA3 => "SHA3",
&Opcode::ADDRESS => "ADDRESS",
&Opcode::BALANCE => "BALANCE",
&Opcode::ORIGIN => "ORIGIN",
&Opcode::CALLER => "CALLER",
&Opcode::CALLVALUE => "CALLVALUE",
&Opcode::CALLDATALOAD => "CALLDATALOAD",
&Opcode::CALLDATASIZE => "CALLDATASIZE",
&Opcode::CALLDATACOPY => "CALLDATACOPY",
&Opcode::CODESIZE => "CODESIZE",
&Opcode::CODECOPY => "CODECOPY",
&Opcode::GASPRICE => "GASPRICE",
&Opcode::EXTCODESIZE => "EXTCODESIZE",
&Opcode::EXTCODECOPY => "EXTCODECOPY",
&Opcode::RETURNDATASIZE => "RETURNDATASIZE",
&Opcode::RETURNDATACOPY => "RETURNDATACOPY",
&Opcode::EXTCODEHASH => "EXTCODEHASH",
&Opcode::BLOCKHASH => "BLOCKHASH",
&Opcode::COINBASE => "COINBASE",
&Opcode::TIMESTAMP => "TIMESTAMP",
&Opcode::NUMBER => "NUMBER",
&Opcode::DIFFICULTY => "DIFFICULTY",
&Opcode::GASLIMIT => "GASLIMIT",
&Opcode::CHAINID => "CHAINID",
&Opcode::SELFBALANCE => "SELFBALANCE",
&Opcode::POP => "POP",
&Opcode::MLOAD => "MLOAD",
&Opcode::MSTORE => "MSTORE",
&Opcode::MSTORE8 => "MSTORE8",
&Opcode::SLOAD => "SLOAD",
&Opcode::SSTORE => "SSTORE",
&Opcode::JUMP => "JUMP",
&Opcode::JUMPI => "JUMPI",
&Opcode::PC => "PC",
&Opcode::MSIZE => "MSIZE",
&Opcode::GAS => "GAS",
&Opcode::JUMPDEST => "JUMPDEST",
&Opcode::PUSH1 => "PUSH1",
&Opcode::PUSH2 => "PUSH2",
&Opcode::PUSH3 => "PUSH3",
&Opcode::PUSH4 => "PUSH4",
&Opcode::PUSH5 => "PUSH5",
&Opcode::PUSH6 => "PUSH6",
&Opcode::PUSH7 => "PUSH7",
&Opcode::PUSH8 => "PUSH8",
&Opcode::PUSH9 => "PUSH9",
&Opcode::PUSH10 => "PUSH10",
&Opcode::PUSH11 => "PUSH11",
&Opcode::PUSH12 => "PUSH12",
&Opcode::PUSH13 => "PUSH13",
&Opcode::PUSH14 => "PUSH14",
&Opcode::PUSH15 => "PUSH15",
&Opcode::PUSH16 => "PUSH16",
&Opcode::PUSH17 => "PUSH17",
&Opcode::PUSH18 => "PUSH18",
&Opcode::PUSH19 => "PUSH19",
&Opcode::PUSH20 => "PUSH20",
&Opcode::PUSH21 => "PUSH21",
&Opcode::PUSH22 => "PUSH22",
&Opcode::PUSH23 => "PUSH23",
&Opcode::PUSH24 => "PUSH24",
&Opcode::PUSH25 => "PUSH25",
&Opcode::PUSH26 => "PUSH26",
&Opcode::PUSH27 => "PUSH27",
&Opcode::PUSH28 => "PUSH28",
&Opcode::PUSH29 => "PUSH29",
&Opcode::PUSH30 => "PUSH30",
&Opcode::PUSH31 => "PUSH31",
&Opcode::PUSH32 => "PUSH32",
&Opcode::DUP1 => "DUP1",
&Opcode::DUP2 => "DUP2",
&Opcode::DUP3 => "DUP3",
&Opcode::DUP4 => "DUP4",
&Opcode::DUP5 => "DUP5",
&Opcode::DUP6 => "DUP6",
&Opcode::DUP7 => "DUP7",
&Opcode::DUP8 => "DUP8",
&Opcode::DUP9 => "DUP9",
&Opcode::DUP10 => "DUP10",
&Opcode::DUP11 => "DUP11",
&Opcode::DUP12 => "DUP12",
&Opcode::DUP13 => "DUP13",
&Opcode::DUP14 => "DUP14",
&Opcode::DUP15 => "DUP15",
&Opcode::DUP16 => "DUP16",
&Opcode::SWAP1 => "SWAP1",
&Opcode::SWAP2 => "SWAP2",
&Opcode::SWAP3 => "SWAP3",
&Opcode::SWAP4 => "SWAP4",
&Opcode::SWAP5 => "SWAP5",
&Opcode::SWAP6 => "SWAP6",
&Opcode::SWAP7 => "SWAP7",
&Opcode::SWAP8 => "SWAP8",
&Opcode::SWAP9 => "SWAP9",
&Opcode::SWAP10 => "SWAP10",
&Opcode::SWAP11 => "SWAP11",
&Opcode::SWAP12 => "SWAP12",
&Opcode::SWAP13 => "SWAP13",
&Opcode::SWAP14 => "SWAP14",
&Opcode::SWAP15 => "SWAP15",
&Opcode::SWAP16 => "SWAP16",
&Opcode::LOG0 => "LOG0",
&Opcode::LOG1 => "LOG1",
&Opcode::LOG2 => "LOG2",
&Opcode::LOG3 => "LOG3",
&Opcode::LOG4 => "LOG4",
&Opcode::CREATE => "CREATE",
&Opcode::CALL => "CALL",
&Opcode::CALLCODE => "CALLCODE",
&Opcode::RETURN => "RETURN",
&Opcode::DELEGATECALL => "DELEGATECALL",
&Opcode::STATICCALL => "STATICCALL",
&Opcode::REVERT => "REVERT",
&Opcode::INVALID => "INVALID",
&Opcode::CREATE2 => "CREATE2",
&Opcode::EOFMAGIC => "EOFMAGIC",
&Opcode::SUICIDE => "SUICIDE",
_ => "UNKNOWN",
}
}
}

impl Stringify for ExitError {
fn stringify(&self) -> &str {
match self {
Expand Down
10 changes: 4 additions & 6 deletions modules/evm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3026,7 +3026,7 @@ fn tracer_works() {

let alice_account_id = <Runtime as Config>::AddressMapping::get_account_id(&alice());

let mut tracer = crate::runner::tracing::Tracer::new();
let mut tracer = crate::runner::tracing::Tracer::new(true);
crate::runner::tracing::using(&mut tracer, || {
assert_ok!(EVM::call(
RuntimeOrigin::signed(alice_account_id.clone()),
Expand Down Expand Up @@ -3082,7 +3082,7 @@ fn tracer_works() {
assert_eq!(steps.len(), 553);
let step = r#"
{
"op": [80, 85, 83, 72, 49],
"op": 96,
"pc": 0,
"depth": 0,
"gas": 978796,
Expand All @@ -3092,20 +3092,18 @@ fn tracer_works() {
"#;
let step = serde_json::from_str::<crate::runner::tracing::Step>(step).unwrap();
assert_eq!(steps.first().unwrap(), &step);
assert_eq!(String::from_utf8_lossy(&step.op), "PUSH1");

let step = r#"
{
"op": [83, 84, 79, 80],
"op": 0,
"pc": 194,
"depth": 0,
"gas": 949994,
"stack": ["0x00000000000000000000000000000000000000000000000000000000da1385d5"],
"stack": [[218, 19, 133, 213]],
"memory": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 131, 74, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
}
"#;
let step = serde_json::from_str::<crate::runner::tracing::Step>(step).unwrap();
assert_eq!(steps.last().unwrap(), &step);
assert_eq!(String::from_utf8_lossy(&step.op), "STOP");
})
}
11 changes: 6 additions & 5 deletions primitives/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,10 @@ pub use convert::*;

#[cfg(feature = "tracing")]
pub mod tracing {
use module_evm_utility::evm::Opcode;
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_core::{H160, H256, U256};
use sp_core::{H160, U256};
use sp_runtime::RuntimeDebug;
use sp_std::vec::Vec;

Expand Down Expand Up @@ -422,14 +423,14 @@ pub mod tracing {
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
pub struct Step {
pub op: Vec<u8>,
pub op: Opcode,
#[codec(compact)]
pub pc: u64,
pub pc: u32,
#[codec(compact)]
pub depth: u32,
#[codec(compact)]
pub gas: u64,
pub stack: Vec<H256>,
pub stack: Vec<Vec<u8>>,
pub memory: Option<Vec<u8>>,
}

Expand All @@ -439,7 +440,7 @@ pub mod tracing {
pub struct VMTrace {
#[codec(compact)]
pub gas: u64,
pub return_value: H256,
pub return_value: Vec<u8>,
pub struct_logs: Vec<Step>,
}
}
9 changes: 4 additions & 5 deletions runtime/acala/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2240,7 +2240,7 @@ sp_api::impl_runtime_apis! {
storage_limit: u32,
access_list: Option<Vec<AccessListItem>>,
) -> Result<Vec<module_evm::runner::tracing::CallTrace>, sp_runtime::DispatchError> {
let mut tracer = module_evm::runner::tracing::Tracer::new();
let mut tracer = module_evm::runner::tracing::Tracer::new(false);
module_evm::runner::tracing::using(&mut tracer, || {
if to == H160::zero() {
<Runtime as module_evm::Config>::Runner::rpc_create(
Expand Down Expand Up @@ -2277,9 +2277,8 @@ sp_api::impl_runtime_apis! {
storage_limit: u32,
access_list: Option<Vec<AccessListItem>>,
) -> Result<module_evm::runner::tracing::VMTrace, sp_runtime::DispatchError> {
use sp_core::H256;
use sp_runtime::traits::UniqueSaturatedInto;
let mut tracer = module_evm::runner::tracing::Tracer::new();
let mut tracer = module_evm::runner::tracing::Tracer::new(true);
module_evm::runner::tracing::using(&mut tracer, || {
if to == H160::zero() {
<Runtime as module_evm::Config>::Runner::rpc_create(
Expand All @@ -2290,7 +2289,7 @@ sp_api::impl_runtime_apis! {
storage_limit,
access_list.unwrap_or_default().into_iter().map(|v| (v.address, v.storage_keys)).collect(),
<Runtime as module_evm::Config>::config(),
).map(|res| (H256::from(res.value), UniqueSaturatedInto::<u64>::unique_saturated_into(res.used_gas)))
).map(|res| (res.value.as_bytes().to_vec(), UniqueSaturatedInto::<u64>::unique_saturated_into(res.used_gas)))
} else {
<Runtime as module_evm::Config>::Runner::rpc_call(
from,
Expand All @@ -2302,7 +2301,7 @@ sp_api::impl_runtime_apis! {
storage_limit,
access_list.unwrap_or_default().into_iter().map(|v| (v.address, v.storage_keys)).collect(),
<Runtime as module_evm::Config>::config(),
).map(|res| (H256::from_slice(&res.value), UniqueSaturatedInto::<u64>::unique_saturated_into(res.used_gas)))
).map(|res| (res.value, UniqueSaturatedInto::<u64>::unique_saturated_into(res.used_gas)))
}
}).map(|(return_value, gas) | module_evm::runner::tracing::VMTrace {
gas,
Expand Down
9 changes: 4 additions & 5 deletions runtime/karura/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2242,7 +2242,7 @@ impl_runtime_apis! {
storage_limit: u32,
access_list: Option<Vec<AccessListItem>>,
) -> Result<Vec<module_evm::runner::tracing::CallTrace>, sp_runtime::DispatchError> {
let mut tracer = module_evm::runner::tracing::Tracer::new();
let mut tracer = module_evm::runner::tracing::Tracer::new(false);
module_evm::runner::tracing::using(&mut tracer, || {
if to == H160::zero() {
<Runtime as module_evm::Config>::Runner::rpc_create(
Expand Down Expand Up @@ -2279,9 +2279,8 @@ impl_runtime_apis! {
storage_limit: u32,
access_list: Option<Vec<AccessListItem>>,
) -> Result<module_evm::runner::tracing::VMTrace, sp_runtime::DispatchError> {
use sp_core::H256;
use sp_runtime::traits::UniqueSaturatedInto;
let mut tracer = module_evm::runner::tracing::Tracer::new();
let mut tracer = module_evm::runner::tracing::Tracer::new(true);
module_evm::runner::tracing::using(&mut tracer, || {
if to == H160::zero() {
<Runtime as module_evm::Config>::Runner::rpc_create(
Expand All @@ -2292,7 +2291,7 @@ impl_runtime_apis! {
storage_limit,
access_list.unwrap_or_default().into_iter().map(|v| (v.address, v.storage_keys)).collect(),
<Runtime as module_evm::Config>::config(),
).map(|res| (H256::from(res.value), UniqueSaturatedInto::<u64>::unique_saturated_into(res.used_gas)))
).map(|res| (res.value.as_bytes().to_vec(), UniqueSaturatedInto::<u64>::unique_saturated_into(res.used_gas)))
} else {
<Runtime as module_evm::Config>::Runner::rpc_call(
from,
Expand All @@ -2304,7 +2303,7 @@ impl_runtime_apis! {
storage_limit,
access_list.unwrap_or_default().into_iter().map(|v| (v.address, v.storage_keys)).collect(),
<Runtime as module_evm::Config>::config(),
).map(|res| (H256::from_slice(&res.value), UniqueSaturatedInto::<u64>::unique_saturated_into(res.used_gas)))
).map(|res| (res.value, UniqueSaturatedInto::<u64>::unique_saturated_into(res.used_gas)))
}
}).map(|(return_value, gas) | module_evm::runner::tracing::VMTrace {
gas,
Expand Down
Loading

0 comments on commit 6b15017

Please sign in to comment.