-
Notifications
You must be signed in to change notification settings - Fork 153
feat(l1): add BlockAccessListTracer and debug_getBlockAccessList.
#5784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat(l1): add BlockAccessListTracer and debug_getBlockAccessList.
#5784
Conversation
…ambdaclass#5706) **Motivation** * `./hive --sim ethereum/eels/execute-blobs --client ethrex` fails with `execution_testing.rpc.rpc_types.JSONRPCError: JSONRPCError(code=-32603, message=Internal Error: Parent block not found)`. * GetBlobBaseFee is using parents header which causes to get blob base fee for genesis blocks. According to the specs `excess_blob_gas` is **Running total of blob gas consumed in excess of the target, prior to this block.**. That means we need to use latest block header only. **Description** - use latest block header and remove accessing parent header. Co-authored-by: lakshya-sky <lakshya-sky@users.noreply.github.com> Co-authored-by: Edgar <git@edgl.dev>
BlockAccessListTracer and debug_getBlockAccessList.BlockAccessListTracer and debug_getBlockAccessList.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds support for block access list tracing and the Amsterdam fork. The key changes include:
- Introduction of a flexible
Tracertrait with multiple implementations (BlockAccessListTracer,LevmCallTracer,NoOpTracer) - New
debug_getBlockAccessListRPC endpoint for retrieving block access lists - Addition of the Amsterdam fork with
block_access_list_hashin block headers - New
engine_newPayloadV5RPC method supporting block access lists - Refactoring of VM tracer integration from concrete
LevmCallTracerto trait objectRc<RefCell<dyn Tracer>>
Reviewed changes
Copilot reviewed 35 out of 35 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/vm/levm/src/tracing/mod.rs | Defines the new Tracer trait with hooks for state changes and account accesses |
| crates/vm/levm/src/tracing/block_access_list_tracer.rs | Implements tracer that tracks all state changes for generating block access lists |
| crates/vm/levm/src/tracing/call_tracer.rs | Refactors LevmCallTracer to implement the Tracer trait |
| crates/vm/levm/src/vm.rs | Updates VM to use trait object for tracer, adds new call() method |
| crates/vm/levm/src/opcode_handlers/*.rs | Adds tracer notifications throughout opcode handlers |
| crates/vm/levm/src/db/gen_db.rs | Integrates tracer hooks into database operations |
| crates/common/types/block_access_list.rs | Defines data structures for block access lists with RLP encoding/decoding |
| crates/networking/rpc/debug/block_access_list.rs | Implements RPC handler for debug_getBlockAccessList |
| crates/networking/rpc/engine/payload.rs | Adds engine_newPayloadV5 handler with block access list validation |
| crates/common/types/genesis.rs | Adds Amsterdam fork configuration and ordering of fork-checking methods |
| crates/vm/backends/mod.rs | Adds generate_bal flag to control block access list generation |
| crates/blockchain/tracing.rs | Implements trace_block_access_list method for blockchain |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if self.idx == 0 { | ||
| self.idx = self.idx.saturating_add(1); | ||
| } | ||
| } |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tracer index initialization in txn_start is inconsistent. When idx is 0, it increments to 1, but then txn_end always increments. This means the first transaction will have idx=1, but if there are no transactions in a block, idx stays at 0. Consider starting at idx=1 in the constructor or documenting why idx=0 should be skipped.
| let acc = self.get_account_mut(address)?; | ||
| let old_hash = acc.info.code_hash; | ||
| let code_hash = new_bytecode.hash; | ||
| acc.info.code_hash = new_bytecode.hash; | ||
| self.db.codes.entry(code_hash).or_insert(new_bytecode); | ||
| self.db | ||
| .codes | ||
| .entry(code_hash) | ||
| .or_insert(new_bytecode.clone()); | ||
| let old = self.db.get_code(old_hash).cloned()?; | ||
| self.tracer | ||
| .borrow_mut() | ||
| .on_code_change(address, old, new_bytecode, self.db); |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential issue: on_code_change is called in update_account_bytecode, but there's no corresponding on_account_access call for the address before accessing/modifying the account. This is inconsistent with other methods like increase_account_balance and decrease_account_balance which call on_account_access first.
|
|
||
| #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)] | ||
| pub struct CodeChange { | ||
| #[serde(rename = "TxIdx")] |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent serialization naming: CodeChange uses TxIdx (line 139) while other similar structs like NonceChange (line 106), BalanceChange (line 73), and StorageChange (line 14) use txIndex. This should be standardized to txIndex for consistency.
| #[serde(rename = "TxIdx")] | |
| #[serde(rename = "txIndex")] |
| // // Obtain the block's parent state | ||
| // let mut vm = self | ||
| // .rebuild_parent_state(block.header.parent_hash, reexec) | ||
| // .await?; | ||
| // // Run anything necessary before executing the block's transactions (system calls, etc) | ||
| // vm.rerun_block(&block, Some(0))?; | ||
|
|
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead code: There are commented-out lines that reference rebuild_parent_state and rerun_block. If this code is intended for future use, it should be documented with a TODO comment explaining why it's commented out. Otherwise, it should be removed to improve code clarity.
| // // Obtain the block's parent state | |
| // let mut vm = self | |
| // .rebuild_parent_state(block.header.parent_hash, reexec) | |
| // .await?; | |
| // // Run anything necessary before executing the block's transactions (system calls, etc) | |
| // vm.rerun_block(&block, Some(0))?; |
| Fork::BPO3 => SpecId::OSAKA, | ||
| Fork::BPO4 => SpecId::OSAKA, | ||
| Fork::BPO5 => SpecId::OSAKA, | ||
| Fork::Amsterdam => todo!(), |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing implementation: The Fork::Amsterdam mapping to SpecId is left as todo!(). This will cause a panic at runtime if Amsterdam fork tests are executed. The appropriate SpecId should be mapped or at a minimum this should return a proper error rather than panicking.
| let chain_config = context.storage.get_chain_config(); | ||
|
|
||
| if !chain_config.is_amsterdam_activated(block.header.timestamp) { | ||
| return Err(RpcErr::UnsuportedFork(format!( |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in error message: "UnsuportedFork" should be "UnsupportedFork" (missing 'p').
| return Err(RpcErr::UnsuportedFork(format!( | |
| return Err(RpcErr::UnsupportedFork(format!( |
| // This method follows the same specification as `engine_newPayloadV4` additionally | ||
| // rejects payload without block access list |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment in validate_execution_payload_v4 mentions "This method follows the same specification as engine_newPayloadV4" but the function is actually validating payload requirements for V5 (Amsterdam fork with block_access_list). The comment should clarify that this validates V4/V5 payloads, or the function should be renamed to better reflect its purpose.
| // This method follows the same specification as `engine_newPayloadV4` additionally | |
| // rejects payload without block access list | |
| // This method builds on the `engine_newPayloadV3` specification and additionally | |
| // enforces the Amsterdam (V5) requirement that `block_access_list` is present, | |
| // i.e. it validates payloads suitable for Engine API V4/V5. |
| pub fn increment_account_nonce(&mut self, address: Address) -> Result<u64, InternalError> { | ||
| let account = self.get_account_mut(address)?; | ||
| let old = account.info.nonce; | ||
| account.info.nonce = account | ||
| .info | ||
| .nonce | ||
| .checked_add(1) | ||
| .ok_or(InternalError::Overflow)?; | ||
| Ok(account.info.nonce) | ||
| let new = account.info.nonce; | ||
| if old != new { | ||
| self.tracer | ||
| .borrow_mut() | ||
| .on_nonce_change(address, old, new, self.db); | ||
| } | ||
| Ok(new) | ||
| } |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing tracer notification: increment_account_nonce doesn't call on_account_access before accessing the account, which is inconsistent with other account modification methods like increase_account_balance and decrease_account_balance.
| fn txn_end( | ||
| &mut self, | ||
| _gas_used: u64, | ||
| err: Option<String>, |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The err parameter in txn_end is not prefixed with underscore but is unused. This should either be renamed to _err for consistency with other unused parameters, or the error should be handled (e.g., to roll back changes on transaction failure).
| err: Option<String>, | |
| _err: Option<String>, |
| // if self.generate_bal { | ||
| // tracer = Rc::new(RefCell::new()); | ||
| // } |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead code: Commented-out code that suggests generating a BlockAccessList tracer based on self.generate_bal. This should either be implemented properly or removed. The current implementation always uses NoOpTracer which means generate_bal has no effect in this method.
| // if self.generate_bal { | |
| // tracer = Rc::new(RefCell::new()); | |
| // } |
Motivation
Description
Checklist
STORE_SCHEMA_VERSION(crates/storage/lib.rs) if the PR includes breaking changes to theStorerequiring a re-sync.Closes #issue_number