Skip to content

internal/ethapi: return InvalidParams for malformed sendRawTransaction RLP - #35129

Open
manusw7 wants to merge 3 commits into
ethereum:masterfrom
manusw7:fix/sendRawTransaction-invalid-params
Open

internal/ethapi: return InvalidParams for malformed sendRawTransaction RLP#35129
manusw7 wants to merge 3 commits into
ethereum:masterfrom
manusw7:fix/sendRawTransaction-invalid-params

Conversation

@manusw7

@manusw7 manusw7 commented Jun 9, 2026

Copy link
Copy Markdown

Summary

SendRawTransaction and SendRawTransactionSync return the bare UnmarshalBinary error. Since RLP/decode errors don't implement rpc.Error.ErrorCode(), the dispatcher falls back to errcodeDefault = -32000. Per JSON-RPC 2.0, malformed params should be -32602.

This wires the existing invalidParamsError wrapper (internal/ethapi/errors.go) into both decode paths. Decoder messages pass through unchanged — only the wire code changes.

Changes

 // internal/ethapi/api.go — SendRawTransaction
     if err := tx.UnmarshalBinary(input); err != nil {
-        return common.Hash{}, err
+        return common.Hash{}, &invalidParamsError{message: err.Error()}
     }
 // SendRawTransactionSync — same one-line change

Why -32602

The -32000 today is a fallback accident, not a deliberate choice. This matches where the spec is heading: execution-apis#817 (fjl: input-validation conditions on submit methods are just "invalid parameters") and #818 (drops the -32000 "Invalid input" group from eth_sendRawTransaction). Reth and Besu already return -32602 for RLP-decode failures; geth and Erigon default to -32000.

Test plan

Added TestSendRawTransaction_InvalidParams_OnMalformedRLP (internal/ethapi/api_test.go): 5 decode-failure shapes (0xc0, 0xd4, 0x09c0, 0x03c0, 0x04c0) × both methods, asserting ErrorCode() == -32602 via errors.As. All 10 subtests pass.

Out of scope

  • Decoder message wording — unchanged.
  • Non-decode paths (SubmitTransaction, blob conversion): node-state/operational, not param validation — -32000 stays.
  • Engine API: UnmarshalBinary from user-facing JSON-RPC only exists in these two functions.

Related

…n RLP

SendRawTransaction and SendRawTransactionSync currently return the bare
UnmarshalBinary error to the JSON-RPC layer. Because the underlying decode
errors don't implement rpc.Error.ErrorCode(), rpc/json.go:errorMessage falls
back to errcodeDefault = -32000. Per JSON-RPC 2.0, malformed method parameters
should use -32602 (InvalidParams), which is what Reth and Besu emit for the
same input.

internal/ethapi/errors.go already defines invalidParamsError with
ErrorCode() = errCodeInvalidParams. Wire it into the two decode paths and
add a parameterised test covering 5 distinct RLP-decode failure shapes
against both entry points.
@s1na

s1na commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

IMO we should wait for the dust on error codes on execution-apis repo to settle before making changes. Nothing is decided there afaik.

@fjl

fjl commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Please remove the tests.

@fjl fjl closed this Jun 10, 2026
@fjl fjl reopened this Jun 10, 2026
@manusw7

manusw7 commented Jun 16, 2026

Copy link
Copy Markdown
Author

@s1na do you have some updates on how this PR should progress?

I think this change is independent of the catalog work in #817.
#823 is reshuffling tx-validation codes (nonce/fee/gas/pool).
Decode-failure isn't covered there — it's a JSON-RPC 2.0 standard -32602.

Also right now for RLP/decode errors, there are some incongruences between clients.

Maybe I'm missing some changes discussed in execution-apis repo that will covered the scenario in this PR.
Let me know what do you think.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants