From b26b45e5011865acc48f3f6e5d16c42ccc26c74c Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 13 Mar 2024 18:38:21 +0100 Subject: [PATCH 1/2] perf: use ArrayVec for collecting push bytes --- crates/evm/core/src/debug.rs | 22 ++++++++++---- crates/evm/evm/src/inspectors/debugger.rs | 36 ++++++++++------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/crates/evm/core/src/debug.rs b/crates/evm/core/src/debug.rs index 084d36b904cd..70d94ff9760d 100644 --- a/crates/evm/core/src/debug.rs +++ b/crates/evm/core/src/debug.rs @@ -1,5 +1,6 @@ use crate::opcodes; use alloy_primitives::{Address, Bytes, U256}; +use arrayvec::ArrayVec; use revm::interpreter::OpCode; use revm_inspectors::tracing::types::CallKind; use serde::{Deserialize, Serialize}; @@ -176,8 +177,10 @@ pub struct DebugStep { pub returndata: Bytes, /// Opcode to be executed pub instruction: Instruction, - /// Optional bytes that are being pushed onto the stack - pub push_bytes: Option>, + /// Optional bytes that are being pushed onto the stack. + /// Empty if the opcode is not a push or PUSH0. + #[serde(serialize_with = "hex::serialize", deserialize_with = "deserialize_arrayvec_hex")] + pub push_bytes: ArrayVec, /// The program counter at this step. /// /// Note: To map this step onto source code using a source map, you must convert the program @@ -195,7 +198,7 @@ impl Default for DebugStep { calldata: Default::default(), returndata: Default::default(), instruction: Instruction::OpCode(revm::interpreter::opcode::INVALID), - push_bytes: None, + push_bytes: Default::default(), pc: 0, total_gas_used: 0, } @@ -205,8 +208,8 @@ impl Default for DebugStep { impl DebugStep { /// Pretty print the step's opcode pub fn pretty_opcode(&self) -> String { - if let Some(push_bytes) = &self.push_bytes { - format!("{}(0x{})", self.instruction, hex::encode(push_bytes)) + if !self.push_bytes.is_empty() { + format!("{}(0x{})", self.instruction, hex::encode(&self.push_bytes)) } else { self.instruction.to_string() } @@ -266,3 +269,12 @@ impl Instruction { } } } + +fn deserialize_arrayvec_hex<'de, D: serde::Deserializer<'de>>( + deserializer: D, +) -> Result, D::Error> { + let bytes: Vec = hex::deserialize(deserializer)?; + let mut array = ArrayVec::new(); + array.try_extend_from_slice(&bytes).map_err(serde::de::Error::custom)?; + Ok(array) +} diff --git a/crates/evm/evm/src/inspectors/debugger.rs b/crates/evm/evm/src/inspectors/debugger.rs index 5ec952ac26cb..f6232bd475ed 100644 --- a/crates/evm/evm/src/inspectors/debugger.rs +++ b/crates/evm/evm/src/inspectors/debugger.rs @@ -1,4 +1,5 @@ use alloy_primitives::Address; +use arrayvec::ArrayVec; use foundry_common::{ErrorExt, SELECTOR_LEN}; use foundry_evm_core::{ backend::DatabaseExt, @@ -56,15 +57,16 @@ impl Inspector for Debugger { let opcode_info = &opcode_infos[op as usize]; // Extract the push bytes - let push_size = if opcode_info.is_push() { (op - opcode::PUSH1 + 1) as usize } else { 0 }; - let push_bytes = match push_size { - 0 => None, - n => { - let start = pc + 1; - let end = start + n; - Some(interp.contract.bytecode.bytecode()[start..end].to_vec()) - } - }; + let push_size = if opcode_info.is_push() { (op - opcode::PUSH0) as usize } else { 0 }; + let push_bytes = (push_size > 0).then(|| { + let start = pc + 1; + let end = start + push_size; + let slice = &interp.contract.bytecode.bytecode()[start..end]; + assert!(slice.len() <= 32); + let mut array = ArrayVec::new(); + array.try_extend_from_slice(slice).unwrap(); + array + }); let total_gas_used = gas_used( ecx.spec_id(), @@ -72,20 +74,12 @@ impl Inspector for Debugger { interp.gas.refunded() as u64, ); - // if the previous opcode does __not__ modify memory, we can reuse the memory of - // that step + // Reuse the memory from the previous step if the previous opcode did not modify it. let memory = self.arena.arena[self.head] .steps .last() - .and_then(|step| { - if !step.opcode_modifies_memory() { - // reuse the memory from the previous step, because its opcode did not modify - // memory - Some(step.memory.clone()) - } else { - None - } - }) + .filter(|step| !step.opcode_modifies_memory()) + .map(|step| step.memory.clone()) .unwrap_or_else(|| interp.shared_memory.context_memory().to_vec().into()); self.arena.arena[self.head].steps.push(DebugStep { @@ -95,7 +89,7 @@ impl Inspector for Debugger { calldata: interp.contract().input.clone(), returndata: interp.return_data_buffer.clone(), instruction: Instruction::OpCode(op), - push_bytes, + push_bytes: push_bytes.unwrap_or_default(), total_gas_used, }); } From 84bcec78d9274538b2aa51ac5dbdb586cc63eb48 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 13 Mar 2024 18:46:47 +0100 Subject: [PATCH 2/2] deps --- Cargo.lock | 2 ++ Cargo.toml | 1 + crates/evm/core/Cargo.toml | 1 + crates/evm/evm/Cargo.toml | 1 + 4 files changed, 5 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 5ee659cab83f..19a9bbbe1e68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3385,6 +3385,7 @@ dependencies = [ "alloy-json-abi", "alloy-primitives", "alloy-sol-types", + "arrayvec", "const-hex", "eyre", "foundry-cheatcodes", @@ -3418,6 +3419,7 @@ dependencies = [ "alloy-providers", "alloy-rpc-types", "alloy-sol-types", + "arrayvec", "auto_impl", "const-hex", "derive_more", diff --git a/Cargo.toml b/Cargo.toml index 1831efc1c453..0c39173402b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -186,6 +186,7 @@ alloy-rlp = "0.3.3" solang-parser = "=0.3.3" ## misc +arrayvec = "0.7" base64 = "0.22" chrono = { version = "0.4", default-features = false, features = ["clock", "std"] } color-eyre = "0.6" diff --git a/crates/evm/core/Cargo.toml b/crates/evm/core/Cargo.toml index 5e01c91141f5..7e4ea3c218d2 100644 --- a/crates/evm/core/Cargo.toml +++ b/crates/evm/core/Cargo.toml @@ -37,6 +37,7 @@ revm = { workspace = true, default-features = false, features = [ ] } revm-inspectors.workspace = true +arrayvec.workspace = true auto_impl = "1" derive_more.workspace = true eyre = "0.6" diff --git a/crates/evm/evm/Cargo.toml b/crates/evm/evm/Cargo.toml index 08b1500b4a4e..a1857b303d3a 100644 --- a/crates/evm/evm/Cargo.toml +++ b/crates/evm/evm/Cargo.toml @@ -38,6 +38,7 @@ revm-inspectors.workspace = true itertools.workspace = true +arrayvec.workspace = true eyre = "0.6" hex.workspace = true parking_lot = "0.12"