fix(l1): distinguish a disabled RPC namespace from an unimplemented method - #7255
fix(l1): distinguish a disabled RPC namespace from an unimplemented method#7255ilitteri wants to merge 1 commit into
Conversation
…ented method. Two independent defects produced that impression, both reproduced against a running node. `debug_executionWitness` bounded its params only from above (`params.len() > 2`) and then indexed `params[0]`, so `"params": []` panicked with an index-out-of- bounds inside the connection task. The caller got a dropped connection and no JSON-RPC response at all. Every sibling handler already had the `is_empty()` guard; this one was the only method in the whole non-engine surface that could be made to drop a connection, confirmed by sweeping all 68 dispatched methods against `[]`, `[null]`, `[null,null]` and `[null,null,null]`. Separately, `--http.api` defaults to `eth,net,web3`, so on a stock node every `debug_*` request is refused by the namespace allowlist before the handler ever sees its params — with a bare "Method not found", which reads as "ethrex has not implemented this method" rather than "this endpoint is not serving it". The code stays `-32601`, which is correct and matches geth, but the message now names the namespace and the flag that would enable it. Applied to the sibling refusals too: the authenticated port's non-engine/eth rejection, the WebSocket `eth_subscribe` allowlist guard, and the L2 dispatcher's `eth` and `ethrex` guards. `engine_*` over HTTP is checked before the allowlist so it points at `--authrpc.port` instead of advising a flag that rejects `engine` outright. `RpcNamespace::as_prefix` renders the CLI spelling (`txpool`, not `Mempool`) and is covered by a round-trip test against `from_prefix`, so the advice cannot drift into naming something the parser would refuse.
|
🤖 Kimi Code ReviewI'll review this PR diff focusing on correctness, security, performance, and Rust best practices. Overall AssessmentThis is a well-structured PR that improves RPC error messages by distinguishing "method not implemented" from "method exists but namespace is disabled on this endpoint." The changes are defensive and include good test coverage. I found a few issues to address. Issues Found1. Potential panic in
|
| Priority | File | Line | Change |
|---|---|---|---|
| Low | crates/networking/rpc/utils.rs |
308 | Make as_prefix a const fn |
| Low | crates/networking/rpc/rpc.rs |
1358 | Consider unreachable!() instead of dead error arm |
| Low | crates/networking/rpc/rpc.rs |
1752 | Consider stricter test assertion (don't accept MethodNotServedHere for allowed methods) |
| Verify | crates/networking/rpc/rpc.rs |
1815 | Confirm InMemory store doesn't use the path for temp files |
No critical bugs or security vulnerabilities found. The PR is well-constructed and ready to merge with at most minor polish.
Automated review by Kimi (Moonshot AI) · kimi-k2.6 · custom prompt
🤖 Claude Code ReviewI've completed a thorough static review of the diff. Compiling wasn't approved, but the changes are small, well-typed, and covered by new unit tests described in the PR. Here's my review. Review: PR #7255 — distinguish disabled RPC namespace from unimplemented methodSummaryTwo independent, well-scoped fixes: (1) a real panic/DoS bug in Correctness
Minor observations (non-blocking)
Test coverageGood breadth: round-trip test for VerdictNo correctness, security, or consensus-relevant issues found. The panic fix is a genuine (low-severity but real) DoS fix and is correctly scoped; the namespace-message change is careful to preserve the JSON-RPC error code for backward compatibility. Good to merge as-is. Automated review by Claude (Anthropic) · sonnet · custom prompt |
🤖 Codex Code Review
Beyond that, the I could not run the targeted Rust tests here because Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
Lines of code reportTotal lines added: Detailed view |
Motivation
A
debug_*call against a stock node returns a bareMethod not found, which reads as "ethrex does not implement this method". Tooling that probes the standard RPC surface keeps drawing that conclusion — the same failure shape already documented at the top oftest/tests/rpc/missing_rpc_methods_tests.rs, where differential testing reported ethrex as lacking functionality it largely already had.The cause is not the request:
--http.apidefaults toeth,net,web3, so on a stock node everydebug_*request is refused by the namespace allowlist before the handler ever sees its params. Reproduced against a running node — the response is identical with valid params, with empty params, and with noparamsfield at all:debug_traceBlockByNumber["latest"]-32601 Method not founddebug_traceBlockByNumber[]-32601 Method not founddebug_chainConfig(noparamsfield)-32601 Method not foundInvestigating it surfaced a second, unrelated defect: one handler panics on empty params and drops the connection.
Description
Distinguish "not served here" from "not implemented". Adds
RpcErr::MethodNotServedHere { method, reason }for a method this build implements but this endpoint does not serve. The code stays-32601, which is correct per JSON-RPC 2.0 and matches geth's behaviour for a disabled module, so any client keying on the code is unaffected; only the message gains the reason. A genuinely unknown method still returns the bareMethodNotFound, so the two cases are now distinguishable.Applied to every sibling refusal, not just the HTTP allowlist: the authenticated port's non-
engine/ethrejection, the WebSocketeth_subscribeallowlist guard, and the L2 dispatcher'sethandethrexguards — the last naming--http.api.ethrex, which is the flag that actually controls it.engine_*over HTTP is now checked before the allowlist. It previously fell through to the allowlist branch and was told to addengineto--http.api, a flag whose parser rejectsengineoutright; it now points at--authrpc.port.RpcNamespace::as_prefixrenders the CLI spelling (txpool, notMempool) and has a round-trip test againstfrom_prefix, so the advice cannot drift into naming something the CLI would refuse.Fix the panic.
debug_executionWitnessbounded its params only from above (params.len() > 2) and then indexedparams[0], so"params": []panicked with an index-out-of-bounds inside the connection task — the caller got a dropped connection and no JSON-RPC response at all, and the node logged:Every sibling handler (
eth_call,eth_estimateGas,eth_createAccessList,debug_traceCall,engine_forkchoiceUpdated*) already had theis_empty()guard; this one was missing it. Sweeping all 68 dispatched non-enginemethods against[],[null],[null,null]and[null,null,null]confirms it was the only method in the whole surface that could be made to drop a connection, and that none can after the fix.How to Test
Unit coverage:
cargo test -p ethrex-rpc -p ethrex-l2-rpc --libandcargo test -p ethrex-test --test ethrex_tests.Out of scope
Param errors return
-32000(RpcErr::BadParams) across the entire RPC surface where JSON-RPC 2.0 specifies-32602. The crate already has anInvalidParamsvariant at-32602and the migration is happening spot by spot (#7236 dideth_getLogs); a blanket change touches every namespace and its test expectations, so it is left for its own PR. Related, also untouched:"params": {}returns-32000 "Invalid request body"with"id": "", where the spec wants-32600with the request's id.Checklist
STORE_SCHEMA_VERSION(crates/storage/lib.rs) if the PR includes breaking changes to theStorerequiring a re-sync.