Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions evmrpc/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (

var errNoProofCapableQueryableKVStore = errors.New("cannot find a proof-capable queryable KV store")

const MaxStorageKeysPerProof = 1024
Comment thread
masih marked this conversation as resolved.

type StateAPI struct {
tmClient client.LocalClient
keeper *keeper.Keeper
Expand Down Expand Up @@ -132,9 +134,19 @@ func (a *StateAPI) GetProof(ctx context.Context, address common.Address, storage
if err != nil {
return nil, err
}
if len(storageKeys) > MaxStorageKeysPerProof {
return nil, fmt.Errorf("too many storage keys: got %d, max %d", len(storageKeys), MaxStorageKeysPerProof)
}
paddedKeys := make([]common.Hash, len(storageKeys))
for i, key := range storageKeys {
paddedKey, _, err := decodeHash(key)
if err != nil {
return nil, fmt.Errorf("invalid storage key %q: %w", key, err)
}
Comment thread
cursor[bot] marked this conversation as resolved.
paddedKeys[i] = paddedKey
}
proofResult := ProofResult{Address: address}
for _, key := range storageKeys {
paddedKey := common.BytesToHash([]byte(key))
for _, paddedKey := range paddedKeys {
formattedKey := append(types.StateKey(address), paddedKey[:]...)
qres := queryStore.Query(ctx, abci.RequestQuery{
Path: "/key",
Expand Down
24 changes: 20 additions & 4 deletions evmrpc/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,34 +235,50 @@ func TestGetProof(t *testing.T) {
watermarks := evmrpc.NewWatermarkManager(client, ctxProvider, nil, testApp.EvmKeeper.ReceiptStore())
stateAPI := evmrpc.NewStateAPI(client, &testApp.EvmKeeper, ctxProvider, evmrpc.ConnectionTypeHTTP, watermarks)
require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000616263", testApp.EvmKeeper.GetState(testApp.GetCheckCtx(), evmAddr, common.BytesToHash(key)).Hex())
// hex-encode the storage slot as eth_getProof requires
hexKey := common.BytesToHash(key).Hex()
tests := []struct {
key string
blockNr rpc.BlockNumber
expectedVal []byte
}{
{
key: string(key),
key: hexKey,
blockNr: rpc.BlockNumber(-2),
expectedVal: val,
},
{
key: string(key),
key: hexKey,
blockNr: rpc.BlockNumber(8),
expectedVal: val,
},
{
key: "non existent",
// valid hex slot that has no state set
key: "0x0000000000000000000000000000000000000000000000000000000000000001",
blockNr: rpc.BlockNumber(-2),
expectedVal: []byte{},
},
}
for _, test := range tests {
bptr := &rpc.BlockNumberOrHash{BlockNumber: &test.blockNr}
res, err := stateAPI.GetProof(context.Background(), evmAddr, []string{test.key}, *bptr)
res, err := stateAPI.GetProof(t.Context(), evmAddr, []string{test.key}, *bptr)
require.Nil(t, err)
vals := res.HexValues
require.Equal(t, common.BytesToHash(test.expectedVal), common.HexToHash(vals[0]))
proofs := res.StorageProof
require.Equal(t, "ics23:iavl", proofs[0].Ops[0].Type)
}

// malformed key must be rejected
bptr := &rpc.BlockNumberOrHash{BlockNumber: func() *rpc.BlockNumber { n := rpc.BlockNumber(-2); return &n }()}
_, err := stateAPI.GetProof(t.Context(), evmAddr, []string{"not-hex"}, *bptr)
require.Error(t, err)

// too many keys must be rejected
tooManyKeys := make([]string, evmrpc.MaxStorageKeysPerProof+1)
for i := range tooManyKeys {
tooManyKeys[i] = hexKey
}
_, err = stateAPI.GetProof(t.Context(), evmAddr, tooManyKeys, *bptr)
require.Error(t, err)
}
Loading