internal/ethapi: return error when requesting invalid trie key (#25762)
This change makes eth_getProof and eth_getStorageAt return an error when the argument contains invalid hex in storage keys. Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
parent
d213cb0924
commit
8ade5e6c14
@ -18,6 +18,7 @@ package ethapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
@ -674,15 +675,19 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
|
||||
}
|
||||
|
||||
// create the proof for the storageKeys
|
||||
for i, key := range storageKeys {
|
||||
for i, hexKey := range storageKeys {
|
||||
key, err := decodeHash(hexKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if storageTrie != nil {
|
||||
proof, storageError := state.GetStorageProof(address, common.HexToHash(key))
|
||||
proof, storageError := state.GetStorageProof(address, key)
|
||||
if storageError != nil {
|
||||
return nil, storageError
|
||||
}
|
||||
storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(address, common.HexToHash(key)).Big()), toHexSlice(proof)}
|
||||
storageProof[i] = StorageResult{hexKey, (*hexutil.Big)(state.GetState(address, key).Big()), toHexSlice(proof)}
|
||||
} else {
|
||||
storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}}
|
||||
storageProof[i] = StorageResult{hexKey, &hexutil.Big{}, []string{}}
|
||||
}
|
||||
}
|
||||
|
||||
@ -703,6 +708,22 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
|
||||
}, state.Error()
|
||||
}
|
||||
|
||||
// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
|
||||
// be prefixed by 0x and can have an byte length up to 32.
|
||||
func decodeHash(s string) (common.Hash, error) {
|
||||
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
|
||||
s = s[2:]
|
||||
}
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return common.Hash{}, fmt.Errorf("hex string invalid")
|
||||
}
|
||||
if len(b) > 32 {
|
||||
return common.Hash{}, fmt.Errorf("hex string too long, want at most 32 bytes")
|
||||
}
|
||||
return common.BytesToHash(b), nil
|
||||
}
|
||||
|
||||
// GetHeaderByNumber returns the requested canonical block header.
|
||||
// * When blockNr is -1 the chain head is returned.
|
||||
// * When blockNr is -2 the pending chain head is returned.
|
||||
@ -821,12 +842,16 @@ func (s *BlockChainAPI) GetCode(ctx context.Context, address common.Address, blo
|
||||
// GetStorageAt returns the storage from the state at the given address, key and
|
||||
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
|
||||
// numbers are also allowed.
|
||||
func (s *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
||||
func (s *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, hexKey string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
||||
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||
if state == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := state.GetState(address, common.HexToHash(key))
|
||||
key, err := decodeHash(hexKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decode storage key: %s", err)
|
||||
}
|
||||
res := state.GetState(address, key)
|
||||
return res[:], state.Error()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user