From 8f7704cf1a9f6dca2e077b4c15edf5c462e5a070 Mon Sep 17 00:00:00 2001 From: Pana Date: Tue, 26 Mar 2024 18:41:19 +0800 Subject: [PATCH 01/11] fix examples->generate_block_traces reuse TracerEip3155.gas_inspector issue --- crates/revm/src/inspector/eip3155.rs | 2 +- examples/generate_block_traces.rs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index fc9ae809cc..1a50334654 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -178,7 +178,7 @@ impl Inspector for TracerEip3155 { 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()), + gas_used: hex_number(context.inner.env().tx.gas_limit - self.gas_inspector.gas_remaining()), pass: outcome.result.is_ok(), time: None, diff --git a/examples/generate_block_traces.rs b/examples/generate_block_traces.rs index 37a1550778..c5fa3b4436 100644 --- a/examples/generate_block_traces.rs +++ b/examples/generate_block_traces.rs @@ -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) => { @@ -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"); @@ -109,6 +110,7 @@ async fn main() -> anyhow::Result<()> { for tx in block.transactions { evm = evm .modify() + .reset_handler_with_external_context(TracerEip3155::new(Box::new(std::io::stdout()), true)) .modify_tx_env(|etx| { etx.caller = Address::from(tx.from.as_fixed_bytes()); etx.gas_limit = tx.gas.as_u64(); @@ -148,6 +150,7 @@ async fn main() -> anyhow::Result<()> { None => TransactTo::create(), }; }) + .append_handler_register(inspector_handle_register) .build(); // Construct the file writer to write the trace to @@ -176,6 +179,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() From cf16da05bb00db8f0cccd6ea640a27978c19e1be Mon Sep 17 00:00:00 2001 From: Pana Date: Tue, 26 Mar 2024 18:44:36 +0800 Subject: [PATCH 02/11] fmt code --- crates/revm/src/inspector/eip3155.rs | 4 +++- examples/generate_block_traces.rs | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index 1a50334654..8e98b53fd7 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -178,7 +178,9 @@ impl Inspector for TracerEip3155 { let value = Summary { state_root: B256::ZERO.to_string(), output: outcome.result.output.to_string(), - gas_used: hex_number(context.inner.env().tx.gas_limit - self.gas_inspector.gas_remaining()), + gas_used: hex_number( + context.inner.env().tx.gas_limit - self.gas_inspector.gas_remaining(), + ), pass: outcome.result.is_ok(), time: None, diff --git a/examples/generate_block_traces.rs b/examples/generate_block_traces.rs index c5fa3b4436..298774f240 100644 --- a/examples/generate_block_traces.rs +++ b/examples/generate_block_traces.rs @@ -110,7 +110,10 @@ async fn main() -> anyhow::Result<()> { for tx in block.transactions { evm = evm .modify() - .reset_handler_with_external_context(TracerEip3155::new(Box::new(std::io::stdout()), true)) + .reset_handler_with_external_context(TracerEip3155::new( + Box::new(std::io::stdout()), + true, + )) .modify_tx_env(|etx| { etx.caller = Address::from(tx.from.as_fixed_bytes()); etx.gas_limit = tx.gas.as_u64(); @@ -179,7 +182,7 @@ 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", From becf63d25ff9e01b3f935e49592a91a8325067b3 Mon Sep 17 00:00:00 2001 From: Pana Date: Wed, 27 Mar 2024 10:18:58 +0800 Subject: [PATCH 03/11] clear the eip3155 tracer state so that it can be used in next transaction --- crates/revm/src/inspector/eip3155.rs | 31 ++++++++++++++++++++++++++++ examples/generate_block_traces.rs | 5 ----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index 8e98b53fd7..728ed5c186 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -95,6 +95,30 @@ impl TracerEip3155 { pub fn set_writer(&mut self, writer: Box) { self.output = writer; } + + /// Resets the Tracer to its initial state of [Self::new]. + /// This makes the inspector ready to be used again. + pub fn fuse(&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 { @@ -173,6 +197,7 @@ impl Inspector 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 { @@ -188,6 +213,12 @@ impl Inspector for TracerEip3155 { }; let _ = self.write_value(&value); } + + // clear the state if we are at the top level + if context.journaled_state.depth() == 0 { + self.fuse(); + } + outcome } } diff --git a/examples/generate_block_traces.rs b/examples/generate_block_traces.rs index 298774f240..1c2c0dad48 100644 --- a/examples/generate_block_traces.rs +++ b/examples/generate_block_traces.rs @@ -110,10 +110,6 @@ async fn main() -> anyhow::Result<()> { for tx in block.transactions { evm = evm .modify() - .reset_handler_with_external_context(TracerEip3155::new( - Box::new(std::io::stdout()), - true, - )) .modify_tx_env(|etx| { etx.caller = Address::from(tx.from.as_fixed_bytes()); etx.gas_limit = tx.gas.as_u64(); @@ -153,7 +149,6 @@ async fn main() -> anyhow::Result<()> { None => TransactTo::create(), }; }) - .append_handler_register(inspector_handle_register) .build(); // Construct the file writer to write the trace to From 61d92f19850a5c82d16c18a780b89f41167804e7 Mon Sep 17 00:00:00 2001 From: Pana Date: Wed, 27 Mar 2024 14:56:48 +0800 Subject: [PATCH 04/11] print summary and clean state when create_end --- crates/revm/src/inspector/eip3155.rs | 57 +++++++++++++++++++++------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index 728ed5c186..d963288280 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -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, }; @@ -142,6 +145,28 @@ impl TracerEip3155 { self.output.write_all(b"\n")?; self.output.flush() } + + fn print_summary( + &mut self, + result: &InterpreterResult, + context: &mut EvmContext, + ) { + 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: 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 Inspector for TracerEip3155 { @@ -198,22 +223,26 @@ impl Inspector for TracerEip3155 { ) -> 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( - context.inner.env().tx.gas_limit - self.gas_inspector.gas_remaining(), - ), - pass: outcome.result.is_ok(), + self.print_summary(&outcome.result, context); - time: None, - fork: Some(spec_name.to_string()), - }; - let _ = self.write_value(&value); + // clear the state if we are at the top level + if context.journaled_state.depth() == 0 { + self.fuse(); } + outcome + } + + fn create_end( + &mut self, + context: &mut EvmContext, + inputs: &CreateInputs, + outcome: CreateOutcome, + ) -> CreateOutcome { + let outcome = self.gas_inspector.create_end(context, inputs, outcome); + + self.print_summary(&outcome.result, context); + // clear the state if we are at the top level if context.journaled_state.depth() == 0 { self.fuse(); From 4b2f5d740ff13c2100b39a788b2166c51b8f9522 Mon Sep 17 00:00:00 2001 From: Pana Date: Thu, 28 Mar 2024 14:36:47 +0800 Subject: [PATCH 05/11] update documentation --- crates/revm/src/inspector/handler_register.rs | 2 +- documentation/src/crates/interpreter/instructions.md | 4 ++-- documentation/src/crates/revm.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index 0598c4f829..ba5fb8e117 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -133,7 +133,7 @@ pub fn inspector_handle_register<'a, DB: Database, EXT: GetInspector>( let call_input_stack = Rc::>>::new(RefCell::new(Vec::new())); let create_input_stack = Rc::>>::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( diff --git a/documentation/src/crates/interpreter/instructions.md b/documentation/src/crates/interpreter/instructions.md index 7835718131..84b5b8a857 100644 --- a/documentation/src/crates/interpreter/instructions.md +++ b/documentation/src/crates/interpreter/instructions.md @@ -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. \ No newline at end of file +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. \ No newline at end of file diff --git a/documentation/src/crates/revm.md b/documentation/src/crates/revm.md index ed17b8d7d5..2ad609f40a 100644 --- a/documentation/src/crates/revm.md +++ b/documentation/src/crates/revm.md @@ -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. @@ -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. From 3a6ea6ccc39b6319ff923bf032723e121ad7d4d1 Mon Sep 17 00:00:00 2001 From: Pana Date: Sun, 31 Mar 2024 09:27:52 +0800 Subject: [PATCH 06/11] fix left nits --- crates/revm/src/inspector/eip3155.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index d963288280..531d650f0b 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -101,7 +101,7 @@ impl TracerEip3155 { /// Resets the Tracer to its initial state of [Self::new]. /// This makes the inspector ready to be used again. - pub fn fuse(&mut self) { + pub fn clear(&mut self) { let Self { gas_inspector, stack, @@ -151,7 +151,7 @@ impl TracerEip3155 { result: &InterpreterResult, context: &mut EvmContext, ) { - if self.print_summary && context.journaled_state.depth() == 0 { + if self.print_summary { let spec_name: &str = context.spec_id().into(); let value = Summary { state_root: B256::ZERO.to_string(), @@ -223,11 +223,10 @@ impl Inspector for TracerEip3155 { ) -> CallOutcome { let outcome = self.gas_inspector.call_end(context, inputs, outcome); - self.print_summary(&outcome.result, context); - - // clear the state if we are at the top level if context.journaled_state.depth() == 0 { - self.fuse(); + self.print_summary(&outcome.result, context); + // clear the state if we are at the top level + self.clear(); } outcome @@ -241,11 +240,11 @@ impl Inspector for TracerEip3155 { ) -> CreateOutcome { let outcome = self.gas_inspector.create_end(context, inputs, outcome); - self.print_summary(&outcome.result, context); - - // clear the state if we are at the top level if context.journaled_state.depth() == 0 { - self.fuse(); + self.print_summary(&outcome.result, context); + + // clear the state if we are at the top level + self.clear(); } outcome From c91d7f3da4911d9fe8a07147c3ddea2f3558acbd Mon Sep 17 00:00:00 2001 From: Pana Date: Tue, 2 Apr 2024 16:00:22 +0800 Subject: [PATCH 07/11] add cancun upgrade block number --- crates/primitives/src/specification.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index c976702839..2762884ace 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -27,7 +27,7 @@ pub enum SpecId { GRAY_GLACIER = 14, // Gray Glacier 15050000 MERGE = 15, // Paris/Merge 15537394 (TTD: 58750000000000000000000) SHANGHAI = 16, // Shanghai 17034870 (TS: 1681338455) - CANCUN = 17, // Cancun TBD + CANCUN = 17, // Cancun 19426587 (Epoch: 269568) #[default] LATEST = u8::MAX, } From 9db495a1c04076f7c91d91e13377d4347dfc3e8e Mon Sep 17 00:00:00 2001 From: Pana Date: Mon, 8 Apr 2024 14:20:20 +0800 Subject: [PATCH 08/11] remove outdated doc --- documentation/src/crates/primitives.md | 8 +------- documentation/src/crates/primitives/log.md | 2 ++ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/documentation/src/crates/primitives.md b/documentation/src/crates/primitives.md index bc058e5a1d..45d57594ef 100644 --- a/documentation/src/crates/primitives.md +++ b/documentation/src/crates/primitives.md @@ -6,12 +6,10 @@ It is set up to be compatible with environments that do not include Rust's stand ### Modules: -- [bits](./primitives/bits.md): This module provides types for handling specific sizes of byte arrays (Address and B256). - [bytecode](./primitives/bytecode.md): This module provides functionality related to EVM bytecode. - [constants](./primitives/constants.md): This module contains constant values used throughout the EVM implementation. - [db](./primitives/database.md): This module contains data structures and functions related to the EVM's database implementation. - [env](./primitives/environment.md): This module contains types and functions related to the EVM's environment, including block headers, and environment values. -- [log](./primitives/log.md): This module provides types and functionality for Ethereum logs. - [precompile](./primitives/precompile.md): This module contains types related to Ethereum's precompiled contracts. - [result](./primitives/result.md): This module provides types for representing execution results and errors in the EVM. - [specification](./primitives/specifications.md): This module defines types related to Ethereum specifications (also known as hard forks). @@ -30,10 +28,6 @@ It is set up to be compatible with environments that do not include Rust's stand - `ruint`: The ruint crate provides types and functions for big unsigned integer arithmetic. - `c-kzg`: A minimal implementation of the Polynomial Commitments API for EIP-4844, written in C. (With rust bindings) -### Type Aliases: - -- `Hash`: An alias for B256, typically used to represent 256-bit hashes or integer values in Ethereum. - ### Re-exported Types: - `Address`: A type representing a 160-bit (or 20-byte) array, typically used for Ethereum addresses. @@ -43,4 +37,4 @@ It is set up to be compatible with environments that do not include Rust's stand - `HashMap` and `HashSet`: High-performance hash map and hash set data structures from the hashbrown crate. Re-exported Modules: -All types, constants, and functions from the `bytecode`, `constants`, `env`, `log`, `precompile`, `result`, `specification`, `state`, `utilities`, `KzgSettings`, `EnvKzgSettings`, `trusted_setup_points` types and methods were all re-exported, allowing users to import these items directly from the `primitives` crate. +All types, constants, and functions from the `bytecode`, `constants`, `env`, `precompile`, `result`, `specification`, `state`, `utilities`, `KzgSettings`, `EnvKzgSettings`, `trusted_setup_points` types and methods were all re-exported, allowing users to import these items directly from the `primitives` crate. diff --git a/documentation/src/crates/primitives/log.md b/documentation/src/crates/primitives/log.md index 6bd7bcc1e9..accd1be6cc 100644 --- a/documentation/src/crates/primitives/log.md +++ b/documentation/src/crates/primitives/log.md @@ -1,5 +1,7 @@ # Log +> NOTE: This module's types have been replaced by [`alloy_primitives`](https://github.com/alloy-rs/core)'s `Log` and `LogData`. + This piece of Rust code defines a structure called Log which represents an Ethereum log entry. These logs are integral parts of the Ethereum network and are typically produced by smart contracts during execution. Each Log has three components: - `address`: This field represents the address of the log originator, typically the smart contract that generated the log. The `Address` data type signifies a 160-bit Ethereum address. From 9f59e73da6eef57f220da2b8a0d4b44a28ac50e4 Mon Sep 17 00:00:00 2001 From: Pana Date: Mon, 8 Apr 2024 14:25:02 +0800 Subject: [PATCH 09/11] remove outdated doc --- documentation/src/SUMMARY.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/documentation/src/SUMMARY.md b/documentation/src/SUMMARY.md index 05a9255851..d40b1b2b61 100644 --- a/documentation/src/SUMMARY.md +++ b/documentation/src/SUMMARY.md @@ -20,10 +20,8 @@ - [result](./crates/primitives/result.md) - [environment](./crates/primitives/environment.md) - [specifications](./crates/primitives/specifications.md) - - [bits](./crates/primitives/bits.md) - [bytecode](./crates/primitives/bytecode.md) - [constants](./crates/primitives/constants.md) - - [log](./crates/primitives/log.md) - [precompile](./crates/primitives/precompile.md) - [state](./crates/primitives/state.md) - [utils](./crates/primitives/utils.md) From 2799e511e464f7a7829a8088476d2a00b718d2d3 Mon Sep 17 00:00:00 2001 From: Pana Date: Mon, 8 Apr 2024 16:02:37 +0800 Subject: [PATCH 10/11] remove empty file --- crates/revm/src/frame/frame_or_result.rs | 0 crates/revm/src/frame/result.rs | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 crates/revm/src/frame/frame_or_result.rs delete mode 100644 crates/revm/src/frame/result.rs diff --git a/crates/revm/src/frame/frame_or_result.rs b/crates/revm/src/frame/frame_or_result.rs deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/crates/revm/src/frame/result.rs b/crates/revm/src/frame/result.rs deleted file mode 100644 index e69de29bb2..0000000000 From 0ee9f5ba4fb56dcad3377b7cd92e6e8c56d0d678 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 8 Apr 2024 14:56:28 +0200 Subject: [PATCH 11/11] TS is unit used to trigger the hardork --- crates/primitives/src/specification.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index 2762884ace..e106e8fd79 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -27,7 +27,7 @@ pub enum SpecId { GRAY_GLACIER = 14, // Gray Glacier 15050000 MERGE = 15, // Paris/Merge 15537394 (TTD: 58750000000000000000000) SHANGHAI = 16, // Shanghai 17034870 (TS: 1681338455) - CANCUN = 17, // Cancun 19426587 (Epoch: 269568) + CANCUN = 17, // Cancun 19426587 (TS: 1710338135) #[default] LATEST = u8::MAX, }