internal/ethapi: return error code -32602 for invalid storage key (#33282)
Some checks are pending
/ Docker Image (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run

This was found because other clients are failing RPC tests generated by
Geth. Nethermind and Besu return the correct error code, -32602, in this
situation.
This commit is contained in:
Felix Lange 2025-11-28 11:28:31 +01:00 committed by GitHub
parent fed8e09ab0
commit a122dbe459
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -374,9 +374,9 @@ func (api *BlockChainAPI) GetProof(ctx context.Context, address common.Address,
// Deserialize all keys. This prevents state access on invalid input. // Deserialize all keys. This prevents state access on invalid input.
for i, hexKey := range storageKeys { for i, hexKey := range storageKeys {
var err error var err error
keys[i], keyLengths[i], err = decodeHash(hexKey) keys[i], keyLengths[i], err = decodeStorageKey(hexKey)
if err != nil { if err != nil {
return nil, err return nil, &invalidParamsError{fmt.Sprintf("%v: %q", err, hexKey)}
} }
} }
statedb, header, err := api.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) statedb, header, err := api.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
@ -441,9 +441,10 @@ func (api *BlockChainAPI) GetProof(ctx context.Context, address common.Address,
}, statedb.Error() }, statedb.Error()
} }
// decodeHash parses a hex-encoded 32-byte hash. The input may optionally // decodeStorageKey parses a hex-encoded 32-byte hash.
// be prefixed by 0x and can have a byte length up to 32. // For legacy compatibility reasons, we parse these keys leniently,
func decodeHash(s string) (h common.Hash, inputLength int, err error) { // with the 0x prefix being optional.
func decodeStorageKey(s string) (h common.Hash, inputLength int, err error) {
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") { if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
s = s[2:] s = s[2:]
} }
@ -451,11 +452,11 @@ func decodeHash(s string) (h common.Hash, inputLength int, err error) {
s = "0" + s s = "0" + s
} }
if len(s) > 64 { if len(s) > 64 {
return common.Hash{}, len(s) / 2, errors.New("hex string too long, want at most 32 bytes") return common.Hash{}, len(s) / 2, errors.New("storage key too long (want at most 32 bytes)")
} }
b, err := hex.DecodeString(s) b, err := hex.DecodeString(s)
if err != nil { if err != nil {
return common.Hash{}, 0, errors.New("hex string invalid") return common.Hash{}, 0, errors.New("invalid hex in storage key")
} }
return common.BytesToHash(b), len(b), nil return common.BytesToHash(b), len(b), nil
} }
@ -589,9 +590,9 @@ func (api *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Addre
if state == nil || err != nil { if state == nil || err != nil {
return nil, err return nil, err
} }
key, _, err := decodeHash(hexKey) key, _, err := decodeStorageKey(hexKey)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to decode storage key: %s", err) return nil, &invalidParamsError{fmt.Sprintf("%v: %q", err, hexKey)}
} }
res := state.GetState(address, key) res := state.GetState(address, key)
return res[:], state.Error() return res[:], state.Error()