Skip to content

fix(eth_sendRawTransaction): return InvalidParams for malformed RLP - #12003

Draft
manusw7 wants to merge 4 commits into
masterfrom
fix/eth_sendrawtransaction-invalid-params
Draft

fix(eth_sendRawTransaction): return InvalidParams for malformed RLP#12003
manusw7 wants to merge 4 commits into
masterfrom
fix/eth_sendrawtransaction-invalid-params

Conversation

@manusw7

@manusw7 manusw7 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Closes #11921

Changes

  • Map RlpException thrown by eth_sendRawTransaction / eth_sendRawTransactionSync to -32602 (InvalidParams) instead of -32000 (InvalidInput).
  • Propagate the underlying decoder reason via "Invalid RLP: " + e.Message, replacing the opaque "Invalid RLP." literal so callers can tell why the payload was rejected (empty list, truncated, unknown type, EIP-4844/7702 short list, etc.).
  • Extend test coverage: parameterize Send_raw_transaction_returns_invalid_params_for_malformed_rlp over the 5 decode-failure shapes from the issue (0xc0, 0xd4, 0x09c0, 0x03c0, 0x04c0); update SendRawTransactionSyncFailureCases and the SetCode-authorization regression test to assert the new code.

Types of changes

What types of changes does your code introduce?

  • Bugfix (a non-breaking change that fixes an issue)
  • New feature (a non-breaking change that adds functionality)
  • Breaking change (a change that causes existing functionality not to work as expected)
  • Optimization
  • Refactoring
  • Documentation update
  • Build-related changes
  • Other: Description

Testing

Requires testing

  • Yes
  • No

If yes, did you write tests?

  • Yes
  • No

Notes on testing

13 fixtures in rpc-tests#11 (test_01-06, 12-16, 20, 21) currently FAIL against Nethermind and flip to PASS with this change.

Documentation

Requires documentation update

  • Yes
  • No

Requires explanation in Release Notes

  • Yes
  • No

Remarks

The -32000 returned today is a fallback accident, not a deliberate choice — RLP decode errors don't carry a JSON-RPC code, so the dispatcher defaults to -32000. Per JSON-RPC 2.0, parameter-validation failures should be -32602. Reth and Besu already do this; this change aligns Nethermind.

Companion PRs taking the same axis to the other major clients:

@claude

claude Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Claude finished @manusw7's task in 2m 45s —— View job


PR Review: fix(eth_sendRawTransaction): return InvalidParams for malformed RLP

  • Gathering context
  • Reading relevant rules
  • Reviewing changed files
  • Analyzing correctness, security, and edge cases
  • Posting findings

Summary

This is a correct, well-scoped fix. The change aligns Nethermind with JSON-RPC 2.0 semantics: parameter-decoding failures belong at -32602 (InvalidParams), not -32000 (TransactionRejected), which is the catch-all for runtime or application-level failures. The PR is consistent with Reth and Besu behavior.

Two low-severity nits are noted below; neither blocks merge.


Findings

Low — String concatenation instead of interpolation

EthRpcModule.cs:371 uses "Invalid RLP: " + e.Message. The rest of the file and the codebase consistently use $"…" interpolated strings for message construction. This is a pure style nit with no runtime impact (error paths are cold), but it's worth keeping consistent.

Fix this →

            return ResultWrapper<Hash256>.Fail($"Invalid RLP: {e.Message}", ErrorCodes.InvalidParams);

Low — SetCode null-address test asserts code only, not message

eth_sendRawTransaction_returns_correct_error_if_AuthorityTuple_has_null_value (line ~2416) only asserts actual.Error!.Code == InvalidParams but doesn't assert the message fragment. The parameterized test above it does check for "Invalid RLP:", so the pattern is established. Since this test was pre-existing (only the expected code changed), it's acceptable as-is, but adding a Does.Contain("Invalid RLP:") assertion would make it consistent with the new parameterized test.


Positive observations

  • eth_sendRawTransactionSync is correctly covered — it delegates to the virtual eth_sendRawTransaction (line 466), so the fix propagates automatically; the SendRawTransactionSyncFailureCases update confirms this is also tested.
  • e.Message content is safe to expose — all RlpException throw sites in the serializer use structural descriptions (positions, byte values, type names). None include raw user-supplied bytes or stack traces. No injection or information-disclosure risk.
  • Good parameterization — the five test cases (c0, d4, 09c0, 03c0, 04c0) cover all the failure shapes from issue eth_sendRawTransaction: RLP decode failure returns wrong JSON-RPC error code #11921. Using Does.Contain for message assertions is appropriate here since the suffix differs per case.
  • DebugRpcModule / TraceRpcModule are intentionally out of scope — those catch RlpException with InvalidInput for block-level RPC calls. That's a separate concern and correct not to change here.

Comment thread src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs Outdated
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
@Marchhill

Copy link
Copy Markdown
Contributor

@manusw7 ready for review?

@manusw7

manusw7 commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

@manusw7 ready for review?

we should wait for an update from geth before proceeding (see here ethereum/go-ethereum#35129)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

eth_sendRawTransaction: RLP decode failure returns wrong JSON-RPC error code

2 participants