Skip to content

Commit

Permalink
fix(TracerEip3155): clear Inspector data after transaction. (blueallo…
Browse files Browse the repository at this point in the history
…y#1230)

* fix examples->generate_block_traces reuse TracerEip3155.gas_inspector issue

* fmt code

* clear the eip3155 tracer state so that it can be used in next transaction

* print summary and clean state when create_end

* update documentation

* fix left nits
  • Loading branch information
Pana authored Mar 31, 2024
1 parent 57825ff commit b1ec4eb
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 18 deletions.
85 changes: 73 additions & 12 deletions crates/revm/src/inspector/eip3155.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::{
inspectors::GasInspector,
interpreter::{opcode, CallInputs, CallOutcome, Interpreter},
interpreter::{
opcode, CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter,
InterpreterResult,
},
primitives::{db::Database, hex, HashMap, B256, U256},
EvmContext, Inspector,
};
Expand Down Expand Up @@ -97,6 +100,30 @@ impl TracerEip3155 {
pub fn set_writer(&mut self, writer: Box<dyn Write>) {
self.output = writer;
}

/// Resets the Tracer to its initial state of [Self::new].
/// This makes the inspector ready to be used again.
pub fn clear(&mut self) {
let Self {
gas_inspector,
stack,
pc,
opcode,
gas,
refunded,
mem_size,
skip,
..
} = self;
*gas_inspector = GasInspector::default();
stack.clear();
*pc = 0;
*opcode = 0;
*gas = 0;
*refunded = 0;
*mem_size = 0;
*skip = false;
}
}

impl TracerEip3155 {
Expand Down Expand Up @@ -134,6 +161,28 @@ impl TracerEip3155 {
self.output.write_all(b"\n")?;
self.output.flush()
}

fn print_summary<DB: Database>(
&mut self,
result: &InterpreterResult,
context: &mut EvmContext<DB>,
) {
if self.print_summary {
let spec_name: &str = context.spec_id().into();
let value = Summary {
state_root: B256::ZERO.to_string(),
output: result.output.to_string(),
gas_used: hex_number(
context.inner.env().tx.gas_limit - self.gas_inspector.gas_remaining(),
),
pass: result.is_ok(),

time: None,
fork: Some(spec_name.to_string()),
};
let _ = self.write_value(&value);
}
}
}

impl<DB: Database> Inspector<DB> for TracerEip3155 {
Expand Down Expand Up @@ -194,19 +243,31 @@ impl<DB: Database> Inspector<DB> for TracerEip3155 {
outcome: CallOutcome,
) -> CallOutcome {
let outcome = self.gas_inspector.call_end(context, inputs, outcome);
if self.print_summary && context.journaled_state.depth() == 0 {
let spec_name: &str = context.spec_id().into();
let value = Summary {
state_root: B256::ZERO.to_string(),
output: outcome.result.output.to_string(),
gas_used: hex_number(inputs.gas_limit - self.gas_inspector.gas_remaining()),
pass: outcome.result.is_ok(),

time: None,
fork: Some(spec_name.to_string()),
};
let _ = self.write_value(&value);
if context.journaled_state.depth() == 0 {
self.print_summary(&outcome.result, context);
// clear the state if we are at the top level
self.clear();
}

outcome
}

fn create_end(
&mut self,
context: &mut EvmContext<DB>,
inputs: &CreateInputs,
outcome: CreateOutcome,
) -> CreateOutcome {
let outcome = self.gas_inspector.create_end(context, inputs, outcome);

if context.journaled_state.depth() == 0 {
self.print_summary(&outcome.result, context);

// clear the state if we are at the top level
self.clear();
}

outcome
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/revm/src/inspector/handler_register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ pub fn inspector_handle_register<'a, DB: Database, EXT: GetInspector<DB>>(
let call_input_stack = Rc::<RefCell<Vec<_>>>::new(RefCell::new(Vec::new()));
let create_input_stack = Rc::<RefCell<Vec<_>>>::new(RefCell::new(Vec::new()));

// Create handle
// Create handler
let create_input_stack_inner = create_input_stack.clone();
let old_handle = handler.execution.create.clone();
handler.execution.create = Arc::new(
Expand Down
4 changes: 2 additions & 2 deletions documentation/src/crates/interpreter/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ The `Opcode` enum represents the opcodes that are available in the Ethereum Virt

The `Instruction` struct represents a single instruction in the EVM. It contains the opcode, which is the operation to be performed, and a list of bytes representing the operands for the instruction.

## `execute` Function
## `step` Function

The `execute` function interprets an instruction. It uses the opcode to determine what operation to perform and then performs the operation using the operands in the instruction.
The `step` function interprets an instruction. It uses the opcode to determine what operation to perform and then performs the operation using the operands in the instruction.
4 changes: 2 additions & 2 deletions documentation/src/crates/revm.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The `evm` crate is focused on the implementation of Ethereum Virtual Machine (EV
This crate pulls Primitives, Interpreter and Precompiles together to deliver the rust evm.

The starting point for reading the documentation is [`Evm`](./revm/evm.md), that is main structure of EVM.
Then, I read about the [`EvmBuilder`](./revm/builder.md) that is used to create the `Evm` and modify it.
Then, you can read about the [`EvmBuilder`](./revm/builder.md) that is used to create the `Evm` and modify it.
After, you can read about the [`Handler`](./revm/handler.md) that is used to modify the logic of the Evm, and it will tie with how Evm introspection can be done.
Finally, you can read about the [`Inspector`](./revm/inspector.md), a legacy interface for inspecting execution that is now repurposed as a handler register example.

Expand Down Expand Up @@ -34,6 +34,6 @@ Finally, you can read about the [`Inspector`](./revm/inspector.md), a legacy int

- `Database`, `DatabaseCommit`, `InMemoryDB`: These types from the `db` module are re-exported for handling the database operations.
- `EVM`: The `EVM` struct from the `evm` module is re-exported, serving as the main interface to the EVM implementation.
- `EvmContext`: The `EvmContext` struct from the `evm_impl` module is re-exported, providing data structures to encapsulate EVM execution data.
- `EvmContext`: The `EvmContext` struct from the `context` module is re-exported, providing data structures to encapsulate EVM execution data.
- `JournalEntry`, `JournaledState`: These types from the `journaled_state` module are re-exported, providing the journaling system for the EVM state.
- `inspectors`, `Inspector`: The `Inspector` trait and its implementations from the `inspector` module are re-exported for observing the EVM execution.
5 changes: 4 additions & 1 deletion examples/generate_block_traces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::io::BufWriter;
use std::io::Write;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Instant;

macro_rules! local_fill {
($left:expr, $right:expr, $fun:expr) => {
Expand Down Expand Up @@ -100,7 +101,7 @@ async fn main() -> anyhow::Result<()> {
println!("Found {txs} transactions.");

let console_bar = Arc::new(ProgressBar::new(txs as u64));
let elapsed = std::time::Duration::ZERO;
let start = Instant::now();

// Create the traces directory if it doesn't exist
std::fs::create_dir_all("traces").expect("Failed to create traces directory");
Expand Down Expand Up @@ -176,6 +177,8 @@ async fn main() -> anyhow::Result<()> {
}

console_bar.finish_with_message("Finished all transactions.");

let elapsed = start.elapsed();
println!(
"Finished execution. Total CPU time: {:.6}s",
elapsed.as_secs_f64()
Expand Down

0 comments on commit b1ec4eb

Please sign in to comment.