Skip to content

feat(l1): move getBlockAccessList from debug to eth namespace#6709

Open
edg-l wants to merge 2 commits into
mainfrom
rpc/move-block-access-list-to-eth
Open

feat(l1): move getBlockAccessList from debug to eth namespace#6709
edg-l wants to merge 2 commits into
mainfrom
rpc/move-block-access-list-to-eth

Conversation

@edg-l
Copy link
Copy Markdown
Contributor

@edg-l edg-l commented May 21, 2026

Summary

execution-apis defines getBlockAccessList under the eth_ namespace, not debug_. This PR aligns ethrex with the spec.

  • Rename debug_getBlockAccessListeth_getBlockAccessList.
  • Move rpc/debug/block_access_list.rsrpc/eth/block_access_list.rs; dispatch moves from map_debug_requests to map_eth_requests.
  • Return the structured JSON shape defined by BlockAccessList (array of AccountAccess with camelCase fields, hash32/quantity hex per spec) instead of an RLP-encoded hex string.
  • Fast-path: read from storage.get_block_access_list(hash) (populated at block import in blockchain.rs:1936) before falling back to generate_bal_for_block.
  • Spec conformance: unknown blocks now return null (notFound schema) instead of an Internal RPC error.
  • Update REPL command catalog accordingly.

No back-compat alias for the old debug_ name.

Spec references

  • Method: execution-apis/src/eth/block.yaml:245
  • Schema: execution-apis/src/schemas/block-access-list.yaml

Perf notes

The previous handler always re-executed the full block, which is O(block-execution-time) — hundreds of ms to several seconds per call for a full block. The new fast-path is an RLP decode of the stored BAL when the block was imported in this process lifetime (the common case for post-Amsterdam tip lookups since add_block writes the BAL on import).

The slow re-execute path still applies for:

  • Historical post-Amsterdam blocks that were imported before BAL storage existed.
  • L2's blockchain.add_block path, which does not currently call store_block_access_list (separate follow-up).

A small LRU on top is a possible future optimization but kept out of scope here.

Test plan

  • cargo check -p ethrex-rpc -p ethrex-repl
  • cargo clippy -p ethrex-rpc -p ethrex-repl --no-deps
  • cargo fmt --all -- --check
  • Manual: call eth_getBlockAccessList against a post-Amsterdam block on a devnet and check JSON shape matches the spec example.
  • Manual: call against a pre-Amsterdam block; expect null.
  • Manual: call against an unknown block hash; expect null (not an error).

execution-apis defines this method under `eth_` (src/eth/block.yaml), not
`debug_`. Move the dispatch and module accordingly and return the structured
JSON shape from the spec instead of an RLP-encoded hex string.

- Rename RPC method `debug_getBlockAccessList` -> `eth_getBlockAccessList`.
- Move `rpc/debug/block_access_list.rs` -> `rpc/eth/block_access_list.rs`.
- Return the spec-defined JSON (array of AccountAccess with camelCase fields,
  hash32/quantity hex encodings per execution-apis schema).
- Read from the existing BAL store before re-executing the block.
- Return `null` (notFound) on unknown blocks instead of an Internal error.
- Update REPL command listing.

No back-compat alias for the old `debug_` name.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 21, 2026

⚠️ Known Issues — intentionally skipped tests

Source: docs/known_issues.md

Known Issues

Tests intentionally excluded from CI. Source of truth for the Known
Issues
section the L1 workflow appends to each ef-tests job summary
and posts as a sticky PR comment.

EF Tests — Stateless coverage narrowed to EIP-8025 optional-proofs

make -C tooling/ef_tests/blockchain test calls test-stateless-zkevm
instead of test-stateless. The zkevm@v0.3.3 fixtures are filled against
bal@v5.6.1, out of sync with current bal spec; the broad target trips ~549
fixtures. Re-broaden once the zkevm bundle is regenerated.

Why and resolution path

PR #6527 broadened
test-stateless to extract the entire for_amsterdam/ tree from the
zkevm bundle and run all of it under --features stateless; combined with
this branch's bal-devnet-7 semantics that scope produces ~549
GasUsedMismatch / ReceiptsRootMismatch /
BlockAccessListHashMismatch failures.

test-stateless-zkevm filters cargo to the eip8025_optional_proofs
suite, which still validates the stateless harness without the bal-version
mismatch.

Re-broaden by switching test: back to test-stateless in
tooling/ef_tests/blockchain/Makefile once the zkevm bundle is regenerated
against the current bal spec.

@github-actions github-actions Bot added the L1 Ethereum client label May 21, 2026
@edg-l edg-l marked this pull request as ready for review May 21, 2026 16:17
@edg-l edg-l requested a review from a team as a code owner May 21, 2026 16:17
@ethrex-project-sync ethrex-project-sync Bot moved this to In Review in ethrex_l1 May 21, 2026
@github-actions
Copy link
Copy Markdown

🤖 Kimi Code Review

The PR moves debug_getBlockAccessList to eth_getBlockAccessList (EIP-7928) and refactors the response format from RLP-encoded bytes to structured JSON. Overall, the implementation is solid with proper error handling and efficient caching.

Code Quality & Correctness

  1. crates/networking/rpc/eth/block_access_list.rs:28-42
    The fast-path check against context.storage.get_block_access_list() before falling back to re-execution is an excellent optimization that avoids redundant EVM runs for historical blocks.

  2. crates/networking/rpc/eth/block_access_list.rs:24-26
    Returning Value::Null for unknown blocks instead of RpcErr::Internal correctly implements the execution-apis "notFound" schema.

  3. Hex formatting consistency
    The JSON serialization correctly distinguishes between:

    • Quantities (indices, balances, nonces): "{:#x}" (no leading zeros, e.g., 0x1a)
    • 32-byte values (slots, storage values): "0x{:064x}" (zero-padded)
    • Byte arrays (code): "0x{}", hex::encode(...)
    • Addresses: "{:#x}"

Minor Observations

  • Breaking change acknowledgment: The response format changes significantly (RLP hex → structured JSON). Since the method name changes from debug_* to eth_*, this is acceptable, but ensure release notes document this for any consumers of the debug endpoint.
  • Memory usage: The bal_to_json function allocates multiple intermediate String objects. For blocks with heavy state access, this could be memory-intensive, but this is standard for JSON-RPC implementations.

Security & Safety

  • No unsafe code introduced.
  • Proper error propagation using ? operator for storage errors.
  • No panics introduced; all unwrap-adjacent operations (e.g., header.hash()) are infallible.

Conclusion

The PR correctly implements the EIP-7928 specification with efficient caching and proper JSON-RPC formatting. The code is idiomatic Rust and follows the project's patterns. No changes required.


Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt

@github-actions
Copy link
Copy Markdown

Lines of code report

Total lines added: 110
Total lines removed: 1
Total lines changed: 111

Detailed view
+-------------------------------------------------------+-------+------+
| File                                                  | Lines | Diff |
+-------------------------------------------------------+-------+------+
| ethrex/crates/networking/rpc/debug/mod.rs             | 3     | -1   |
+-------------------------------------------------------+-------+------+
| ethrex/crates/networking/rpc/eth/block_access_list.rs | 109   | +109 |
+-------------------------------------------------------+-------+------+
| ethrex/crates/networking/rpc/eth/mod.rs               | 11    | +1   |
+-------------------------------------------------------+-------+------+

@github-actions
Copy link
Copy Markdown

🤖 Codex Code Review

Findings

  1. High: eth_getBlockAccessList is now on the public eth namespace by default, but a cache miss still does full block re-execution and does not persist the result. On nodes upgraded after Amsterdam, historical BALs will be missing from block_access_lists unless they were imported after this feature landed, so repeated requests for the same block will repeatedly execute the VM. That is a practical CPU DoS vector now that the method is reachable through the default HTTP API. Either keep the expensive fallback behind debug/auth, or store the generated BAL on the slow path. Refs: crates/networking/rpc/eth/block_access_list.rs, crates/blockchain/blockchain.rs, crates/blockchain/blockchain.rs, crates/networking/rpc/lib.rs.

  2. Medium: the new handler accepts extra parameters silently. parse() only rejects the empty case, so eth_getBlockAccessList(block, garbage...) will still execute instead of returning -32602, unlike the surrounding eth_* handlers that enforce exact arity. That is API-spec drift on a newly public method. Refs: crates/networking/rpc/eth/block_access_list.rs.

  3. Low: this is a hard RPC compatibility break for debug_getBlockAccessList. The route is removed rather than aliased/deprecated, so existing clients with debug enabled will start getting MethodNotFound immediately after upgrade. If that break is intentional, it should at least be called out explicitly in release notes; otherwise keep the old debug alias for one release. Refs: crates/networking/rpc/rpc.rs, crates/networking/rpc/rpc.rs.

I did not run a full build: cargo check -p ethrex-rpc --lib failed in this sandbox because rustup could not create temp files under /home/runner/.rustup.


Automated review by OpenAI Codex · gpt-5.4 · custom prompt

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 21, 2026

Greptile Summary

This PR moves getBlockAccessList from the debug_ namespace to eth_ to align with the execution-apis specification, replaces the RLP hex-string response with the structured JSON shape defined by EIP-7928, and adds a fast-path that serves the BAL from storage (populated at block import) before falling back to full block re-execution.

  • Renames debug_getBlockAccessListeth_getBlockAccessList and updates dispatch, module structure, and REPL catalog accordingly.
  • Introduces bal_to_json which serialises BlockAccessList into an array of AccountAccess objects with camelCase fields; unknown or pre-Amsterdam blocks return null per the notFound schema.
  • Adds a fast-path via storage.get_block_access_list(hash) to avoid re-executing the block on every call.

Confidence Score: 3/5

The response serialisation and routing changes are correct, but the parameter parser rejects plain 32-byte block hash strings, which the test plan explicitly exercises.

The parameter parsing uses BlockIdentifier::parse, which calls u64::from_str_radix on the hex payload. A 64-character block hash overflows u64 and returns BadHexFormat instead of a result. The PR's own test plan includes 'call against an unknown block hash; expect null (not an error)', which would fail against the current implementation. All other mechanical changes — dispatch wiring, module moves, REPL catalog updates — are correct.

crates/networking/rpc/eth/block_access_list.rs — parameter parsing and storage-change value encoding both need a second look.

Important Files Changed

Filename Overview
crates/networking/rpc/eth/block_access_list.rs New handler for eth_getBlockAccessList with fast-path (BAL store) + slow-path (block re-execution); has a parameter-parsing bug that rejects plain 32-byte block hash inputs and a potential format mismatch for storage-change values.
crates/networking/rpc/debug/block_access_list.rs Deleted file — old debug_getBlockAccessList handler removed. No issues.
crates/networking/rpc/rpc.rs Routes eth_getBlockAccessList in map_eth_requests and removes debug_getBlockAccessList from map_debug_requests. Clean dispatch change.
tooling/repl/src/commands/eth.rs Adds eth_getBlockAccessList to the REPL command catalog. Straightforward addition.
tooling/repl/src/commands/debug.rs Removes debug_getBlockAccessList from the REPL command catalog. Straightforward deletion.

Sequence Diagram

sequenceDiagram
    participant Client
    participant RPC as map_eth_requests
    participant Handler as BlockAccessListRequest
    participant Storage
    participant Blockchain

    Client->>RPC: eth_getBlockAccessList(param)
    RPC->>Handler: call(req, context)
    Handler->>Storage: resolve_block_number(block_id)
    alt block not found
        Storage-->>Handler: None
        Handler-->>Client: null
    end
    Handler->>Storage: get_block_header(block_number)
    alt header not found
        Storage-->>Handler: None
        Handler-->>Client: null
    end
    Handler->>Storage: get_block_access_list(block_hash)
    alt fast path: BAL in store
        Storage-->>Handler: Some(bal)
        Handler-->>Client: JSON array of AccountAccess
    else slow path: re-execute
        Handler->>Storage: get_block_by_hash(block_hash)
        Storage-->>Handler: Some(block)
        Handler->>Blockchain: generate_bal_for_block(block)
        alt post-Amsterdam block
            Blockchain-->>Handler: Some(bal)
            Handler-->>Client: JSON array of AccountAccess
        else pre-Amsterdam block
            Blockchain-->>Handler: None
            Handler-->>Client: null
        end
    end
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
crates/networking/rpc/eth/block_access_list.rs:18
**Block hash inputs silently rejected**

`BlockIdentifier::parse` attempts `u64::from_str_radix` on the hex payload. Any 32-byte (64-char) block hash string overflows `u64` and returns `RpcErr::BadHexFormat(0)` — so a caller doing `eth_getBlockAccessList("0xd7b7fa3c...")` gets a "Bad hex format" error instead of a result.

The third test in the PR's test plan reads "call against an unknown block hash; expect `null` (not an error)", which implies the spec parameter is a plain `hash32`. Using `BlockIdentifierOrHash::parse` (which supports EIP-1898 `{"blockHash":"0x..."}`) still won't fix a *bare* hash string; a dedicated hash-first parser (or switching to `BlockIdentifierOrHash` that also accepts bare 32-byte strings) is needed to match that test expectation.

### Issue 2 of 2
crates/networking/rpc/eth/block_access_list.rs:73-76
**`storageChanges.value` format inconsistency with other change types**

`post_value` (a `U256` storage slot value) is serialised with 32-byte zero-padding (`"0x{:064x}"`), while `post_balance` and `post_nonce` use quantity encoding (`"{:#x}"`). EIP-7928 defines `StorageValue = uint256`, which in Ethereum JSON-RPC is a `uint` (no leading zeros), consistent with how balance and nonce are encoded. If the execution-apis YAML defines `value` here as `uint`, clients performing strict schema validation will reject the padded form.

```suggestion
                    json!({
                        "index": format!("{:#x}", c.block_access_index),
                        "value": format!("{:#x}", c.post_value),
                    })
```

Reviews (1): Last reviewed commit: "Merge branch 'main' into rpc/move-block-..." | Re-trigger Greptile

@github-actions
Copy link
Copy Markdown

🤖 Claude Code Review

I have enough information to write a thorough review. Here it is:


Code Review: PR #6709feat(l1): move getBlockAccessList from debug to eth namespace

Summary

This PR correctly aligns getBlockAccessList with the execution-apis spec by moving it from the debug_ namespace to eth_, switching from an RLP-hex response to the structured JSON AccountAccess shape, and adding a storage fast-path to avoid redundant block re-execution. The overall direction is sound. A few issues need attention before merge.


Correctness

bal_to_jsonindex field type requires spec verification

In eth/block_access_list.rs, the block_access_index fields (u32) are formatted with "{:#x}":

"index": format!("{:#x}", c.block_access_index),

For value 0, this produces "0x0". Per EIP-7928 / execution-apis, these indices are uint32 quantities (no-leading-zero hex), so {:#x} is correct. However, the value field for StorageChange.post_value (U256) uses zero-padded hash32 format:

"value": format!("0x{:064x}", c.post_value),

While balance and nonce value fields use compact quantity format:

"value": format!("{:#x}", bc.post_balance),
"value": format!("{:#x}", nc.post_nonce),

This asymmetry is intentional (storage values are bytes32, balances/nonces are quantities) and appears correct per spec, but deserves a comment since it's easy to confuse the two encoding rules.

Fast-path / slow-path result equivalence is an untested invariant

storage.get_block_access_list(block_hash) is populated by blockchain.rs:1936 at import time. generate_bal_for_block re-executes the block. If these two paths ever diverge — e.g., due to a bug fix in BAL generation that was deployed after some blocks were stored — clients could see different responses for the same block hash depending on which path is taken. A comment here asserting the invariant (// Invariant: stored BAL == regenerated BAL for the same block) would make this assumption explicit and searchable.

BlockIdentifier vs BlockIdentifierOrHash

BlockIdentifier::parse handles only block tags and block numbers, not raw block hashes. This matches the EIP-7928 method signature (BlockNumberOrTag), so it is spec-correct. However, many other eth_ methods accept block hashes via EIP-1898 ({"blockHash": "0x..."} object form). The PR should explicitly call out that this method intentionally does not support block hash parameters to avoid future confusion.


Missing Coverage

No codeReads field in AccountChanges

EIP-7928 defines a codeReads field in AccountAccess (accounts whose bytecode was read without being changed). The AccountChanges struct has storage_reads: Vec<U256> but no equivalent code_reads. If this field is required by the schema, account_to_json is missing it entirely. This is worth verifying against execution-apis/src/schemas/block-access-list.yaml before shipping.

No unit tests for bal_to_json / account_to_json

The serialization logic spans multiple encoding rules (hash32 vs quantity hex, different field names per entry type). A single unit test with a handcrafted BlockAccessList and an expected serde_json::Value would catch regressions. This is especially important given the manual test plan in the PR.


Observability

Slow path is silent

Re-executing a full block can take hundreds of milliseconds to seconds. When the fast path misses (e.g., for historical blocks not stored in the current process lifetime), the caller has no visibility into why the call was slow. Add a tracing::debug! or tracing::warn! at the slow path entry point:

// Slow path: re-execute the block. Returns None for pre-Amsterdam blocks.
tracing::debug!(block_hash = %block_hash, "BAL cache miss, re-executing block");

Minor

code field in codeChanges — consider 0x for empty bytecode

"code": format!("0x{}", hex::encode(&cc.new_code)),

If new_code is empty (contract self-destructed), this produces "0x". This is valid per the spec (empty bytecode is 0x) but worth a quick mental check.

Breaking change — no deprecation alias

The PR explicitly notes "No back-compat alias for the old debug_ name." This is intentional and reasonable since debug_getBlockAccessList was never part of the spec. Still, it should be called out in release notes for any projects consuming the debug_ endpoint.


What's Good

  • The let-else early returns for unknown/pre-Amsterdam blocks are idiomatic and correct per the notFound schema (returns null, not an error).
  • {:#x} for addresses uses ethereum_types::H160's LowerHex impl, which zero-pads to the full 40 hex chars — no truncation risk for addresses with leading zero bytes.
  • Routing changes in rpc.rs and REPL updates are clean and minimal.
  • The PR description is thorough, citing spec references and noting the L2 follow-up gap — good for reviewers.

Automated review by Claude (Anthropic) · sonnet · custom prompt

if params.is_empty() {
return Err(RpcErr::BadParams("Expected 1 param".to_owned()));
}
let block_id = BlockIdentifier::parse(params[0].clone(), 0)?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Block hash inputs silently rejected

BlockIdentifier::parse attempts u64::from_str_radix on the hex payload. Any 32-byte (64-char) block hash string overflows u64 and returns RpcErr::BadHexFormat(0) — so a caller doing eth_getBlockAccessList("0xd7b7fa3c...") gets a "Bad hex format" error instead of a result.

The third test in the PR's test plan reads "call against an unknown block hash; expect null (not an error)", which implies the spec parameter is a plain hash32. Using BlockIdentifierOrHash::parse (which supports EIP-1898 {"blockHash":"0x..."}) still won't fix a bare hash string; a dedicated hash-first parser (or switching to BlockIdentifierOrHash that also accepts bare 32-byte strings) is needed to match that test expectation.

Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/networking/rpc/eth/block_access_list.rs
Line: 18

Comment:
**Block hash inputs silently rejected**

`BlockIdentifier::parse` attempts `u64::from_str_radix` on the hex payload. Any 32-byte (64-char) block hash string overflows `u64` and returns `RpcErr::BadHexFormat(0)` — so a caller doing `eth_getBlockAccessList("0xd7b7fa3c...")` gets a "Bad hex format" error instead of a result.

The third test in the PR's test plan reads "call against an unknown block hash; expect `null` (not an error)", which implies the spec parameter is a plain `hash32`. Using `BlockIdentifierOrHash::parse` (which supports EIP-1898 `{"blockHash":"0x..."}`) still won't fix a *bare* hash string; a dedicated hash-first parser (or switching to `BlockIdentifierOrHash` that also accepts bare 32-byte strings) is needed to match that test expectation.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +73 to +76
json!({
"index": format!("{:#x}", c.block_access_index),
"value": format!("0x{:064x}", c.post_value),
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 storageChanges.value format inconsistency with other change types

post_value (a U256 storage slot value) is serialised with 32-byte zero-padding ("0x{:064x}"), while post_balance and post_nonce use quantity encoding ("{:#x}"). EIP-7928 defines StorageValue = uint256, which in Ethereum JSON-RPC is a uint (no leading zeros), consistent with how balance and nonce are encoded. If the execution-apis YAML defines value here as uint, clients performing strict schema validation will reject the padded form.

Suggested change
json!({
"index": format!("{:#x}", c.block_access_index),
"value": format!("0x{:064x}", c.post_value),
})
json!({
"index": format!("{:#x}", c.block_access_index),
"value": format!("{:#x}", c.post_value),
})
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/networking/rpc/eth/block_access_list.rs
Line: 73-76

Comment:
**`storageChanges.value` format inconsistency with other change types**

`post_value` (a `U256` storage slot value) is serialised with 32-byte zero-padding (`"0x{:064x}"`), while `post_balance` and `post_nonce` use quantity encoding (`"{:#x}"`). EIP-7928 defines `StorageValue = uint256`, which in Ethereum JSON-RPC is a `uint` (no leading zeros), consistent with how balance and nonce are encoded. If the execution-apis YAML defines `value` here as `uint`, clients performing strict schema validation will reject the padded form.

```suggestion
                    json!({
                        "index": format!("{:#x}", c.block_access_index),
                        "value": format!("{:#x}", c.post_value),
                    })
```

How can I resolve this? If you propose a fix, please make it concise.

/// camelCase fields and per-spec hex encodings (hash32 = full 32-byte hex,
/// quantities = no-leading-zero hex).
fn bal_to_json(bal: &BlockAccessList) -> Value {
Value::Array(bal.accounts().iter().map(account_to_json).collect())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth a unit test against the BlockAccessList → JSON conversion. The whole point of this PR is wire-shape conformance to execution-apis, and bal_to_json is where any drift would land. A small test would catch every format mistake before deploy:

#[test]
fn bal_to_json_matches_spec_shape() {
    use ethrex_common::types::block_access_list::{AccountChanges, BalanceChange, BlockAccessList, NonceChange, SlotChange, StorageChange};
    let mut acc = AccountChanges::new(Address::from_low_u64_be(0x42));
    acc.balance_changes.push(BalanceChange::new(1, U256::from(1_000)));
    acc.nonce_changes.push(NonceChange::new(2, 7));
    acc.storage_reads.push(U256::from(5));
    let mut sc = SlotChange::new(U256::from(3));
    sc.slot_changes.push(StorageChange::new(4, U256::from(0xdead)));
    acc.storage_changes.push(sc);
    let bal = BlockAccessList::new(vec![acc]);

    let j = bal_to_json(&bal);
    assert_eq!(j[0]["address"], "0x0000000000000000000000000000000000000042");
    assert_eq!(j[0]["balanceChanges"][0], json!({"index": "0x1", "value": "0x3e8"}));
    assert_eq!(j[0]["nonceChanges"][0], json!({"index": "0x2", "value": "0x7"}));
    assert_eq!(j[0]["storageReads"][0], "0x0000000000000000000000000000000000000000000000000000000000000005");
    assert_eq!(j[0]["storageChanges"][0]["key"], "0x0000000000000000000000000000000000000000000000000000000000000003");
    assert_eq!(j[0]["storageChanges"][0]["changes"][0]["value"], "0x000000000000000000000000000000000000000000000000000000000000dead");
}

This is the cheap version of every checkbox in the PR test plan. Re-runs forever and doesn't need a devnet.

let bal = context
.blockchain
.generate_bal_for_block(&block)
.map_err(|e| RpcErr::Internal(format!("Failed to generate BAL: {e}")))?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spec asymmetry. generate_bal_for_block returning Ok(None) is treated as Value::Null (the match bal arm below); returning Err becomes RpcErr::Internal. The boundary between the two is generate_bal_for_block's implementation detail — pre-Amsterdam is Ok(None), but "post-Amsterdam block whose state is missing from disk" might be either depending on how the function fails.

If the intent is "known block, can't generate → also null" (which matches the spirit of notFound), this branch could swallow more error variants. If the intent is "known block, real error → Internal", a one-line doc-comment here explaining the split would save the next reader from having to chase down generate_bal_for_block. Non-blocking; just calling out the boundary.

let Some(header) = context.storage.get_block_header(block_number)? else {
return Ok(Value::Null);
};
let block_hash = header.hash();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit on the hash round-trip. For a BlockIdentifier::Hash(h) input, this code does resolve_block_number(h) → get_block_header(number) → header.hash() — three lookups to reproduce the hash the caller already gave us. For BlockIdentifier::Number/Tag it's the natural path.

Not worth restructuring just for this method, but if BlockIdentifier ever grows a resolve_block_hash(&self, storage) -> Result<Option<H256>> helper that short-circuits the Hash variant, this handler (and any others doing the same dance) gets cheaper for free. Filing under "future-work" rather than "change now."

GetTransactionByBlockHashAndIndexRequest::call(req, context).await
}
"eth_getBlockReceipts" => GetBlockReceiptsRequest::call(req, context).await,
"eth_getBlockAccessList" => BlockAccessListRequest::call(req, context).await,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth a one-line CHANGELOG.md entry for the breaking RPC rename. The PR is correct in not adding a debug_getBlockAccessList alias (the body explains why), but any external tooling that integrated against the debug_ name will fail with MethodNotFound after upgrade. A "Breaking: debug_getBlockAccessList renamed to eth_getBlockAccessList (now spec-conformant per execution-apis EIP-7928)" line would surface this for downstream integrators reading release notes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L1 Ethereum client

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

2 participants