rpc: fix eth_getProof (#286)
This commit is contained in:
parent
8fa866482e
commit
c7d89e3d56
2
Makefile
2
Makefile
@ -160,7 +160,7 @@ test-import:
|
|||||||
# TODO: remove tmp directory after test run to avoid subsequent errors
|
# TODO: remove tmp directory after test run to avoid subsequent errors
|
||||||
|
|
||||||
test-rpc:
|
test-rpc:
|
||||||
@${GO_MOD} go test -v --vet=off ./rpc/tester
|
@${GO_MOD} go test -v --vet=off ./tests/rpc_test
|
||||||
|
|
||||||
it-tests:
|
it-tests:
|
||||||
./scripts/integration-test-all.sh -q 1 -z 1 -s 10
|
./scripts/integration-test-all.sh -q 1 -z 1 -s 10
|
||||||
|
@ -21,6 +21,8 @@ import (
|
|||||||
"github.com/cosmos/ethermint/x/evm"
|
"github.com/cosmos/ethermint/x/evm"
|
||||||
"github.com/cosmos/ethermint/x/evm/types"
|
"github.com/cosmos/ethermint/x/evm/types"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
"github.com/tendermint/tendermint/crypto/merkle"
|
||||||
"github.com/tendermint/tendermint/rpc/client"
|
"github.com/tendermint/tendermint/rpc/client"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
@ -36,6 +38,7 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
)
|
)
|
||||||
@ -748,6 +751,9 @@ func (e *PublicEthAPI) GetUncleByBlockNumberAndIndex(number hexutil.Uint, idx he
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copied the Account and StorageResult types since they are registered under an
|
||||||
|
// internal pkg on geth.
|
||||||
|
|
||||||
// AccountResult struct for account proof
|
// AccountResult struct for account proof
|
||||||
type AccountResult struct {
|
type AccountResult struct {
|
||||||
Address common.Address `json:"address"`
|
Address common.Address `json:"address"`
|
||||||
@ -768,20 +774,20 @@ type StorageResult struct {
|
|||||||
|
|
||||||
// GetProof returns an account object with proof and any storage proofs
|
// GetProof returns an account object with proof and any storage proofs
|
||||||
func (e *PublicEthAPI) GetProof(address common.Address, storageKeys []string, block BlockNumber) (*AccountResult, error) {
|
func (e *PublicEthAPI) GetProof(address common.Address, storageKeys []string, block BlockNumber) (*AccountResult, error) {
|
||||||
opts := client.ABCIQueryOptions{Height: int64(block), Prove: true}
|
e.cliCtx = e.cliCtx.WithHeight(int64(block))
|
||||||
path := fmt.Sprintf("custom/%s/%s/%s", types.ModuleName, evm.QueryAccount, address.Hex())
|
path := fmt.Sprintf("custom/%s/%s/%s", types.ModuleName, evm.QueryAccount, address.Hex())
|
||||||
pRes, err := e.cliCtx.Client.ABCIQueryWithOptions(path, nil, opts)
|
|
||||||
|
// query eth account at block height
|
||||||
|
resBz, _, err := e.cliCtx.Query(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: convert TM merkle proof to []string if needed in future
|
|
||||||
// proof := pRes.Response.GetProof()
|
|
||||||
|
|
||||||
var account types.QueryResAccount
|
var account types.QueryResAccount
|
||||||
e.cliCtx.Codec.MustUnmarshalJSON(pRes.Response.GetValue(), &account)
|
e.cliCtx.Codec.MustUnmarshalJSON(resBz, &account)
|
||||||
|
|
||||||
storageProofs := make([]StorageResult, len(storageKeys))
|
storageProofs := make([]StorageResult, len(storageKeys))
|
||||||
|
opts := client.ABCIQueryOptions{Height: int64(block), Prove: true}
|
||||||
for i, k := range storageKeys {
|
for i, k := range storageKeys {
|
||||||
// Get value for key
|
// Get value for key
|
||||||
vPath := fmt.Sprintf("custom/%s/%s/%s/%s", types.ModuleName, evm.QueryStorage, address, k)
|
vPath := fmt.Sprintf("custom/%s/%s/%s/%s", types.ModuleName, evm.QueryStorage, address, k)
|
||||||
@ -789,19 +795,46 @@ func (e *PublicEthAPI) GetProof(address common.Address, storageKeys []string, bl
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var value types.QueryResStorage
|
var value types.QueryResStorage
|
||||||
e.cliCtx.Codec.MustUnmarshalJSON(vRes.Response.GetValue(), &value)
|
e.cliCtx.Codec.MustUnmarshalJSON(vRes.Response.GetValue(), &value)
|
||||||
|
|
||||||
|
// check for proof
|
||||||
|
proof := vRes.Response.GetProof()
|
||||||
|
proofStr := new(merkle.Proof).String()
|
||||||
|
if proof != nil {
|
||||||
|
proofStr = proof.String()
|
||||||
|
}
|
||||||
|
|
||||||
storageProofs[i] = StorageResult{
|
storageProofs[i] = StorageResult{
|
||||||
Key: k,
|
Key: k,
|
||||||
Value: (*hexutil.Big)(common.BytesToHash(value.Value).Big()),
|
Value: (*hexutil.Big)(common.BytesToHash(value.Value).Big()),
|
||||||
Proof: []string{""},
|
Proof: []string{proofStr},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req := abci.RequestQuery{
|
||||||
|
Path: fmt.Sprintf("store/%s/key", auth.StoreKey),
|
||||||
|
Data: auth.AddressStoreKey(sdk.AccAddress(address.Bytes())),
|
||||||
|
Height: int64(block),
|
||||||
|
Prove: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := e.cliCtx.QueryABCI(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for proof
|
||||||
|
accountProof := res.GetProof()
|
||||||
|
accProofStr := new(merkle.Proof).String()
|
||||||
|
if accountProof != nil {
|
||||||
|
accProofStr = accountProof.String()
|
||||||
|
}
|
||||||
|
|
||||||
return &AccountResult{
|
return &AccountResult{
|
||||||
Address: address,
|
Address: address,
|
||||||
AccountProof: []string{""}, // This shouldn't be necessary (different proof formats)
|
AccountProof: []string{accProofStr},
|
||||||
Balance: (*hexutil.Big)(utils.MustUnmarshalBigInt(account.Balance)),
|
Balance: (*hexutil.Big)(utils.MustUnmarshalBigInt(account.Balance)),
|
||||||
CodeHash: common.BytesToHash(account.CodeHash),
|
CodeHash: common.BytesToHash(account.CodeHash),
|
||||||
Nonce: hexutil.Uint64(account.Nonce),
|
Nonce: hexutil.Uint64(account.Nonce),
|
||||||
|
@ -19,11 +19,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cosmos/ethermint/version"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
"github.com/cosmos/ethermint/rpc"
|
||||||
|
"github.com/cosmos/ethermint/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -155,6 +158,23 @@ func TestEth_GetStorageAt(t *testing.T) {
|
|||||||
require.True(t, bytes.Equal(storage, expectedRes), "expected: %d (%d bytes) got: %d (%d bytes)", expectedRes, len(expectedRes), storage, len(storage))
|
require.True(t, bytes.Equal(storage, expectedRes), "expected: %d (%d bytes) got: %d (%d bytes)", expectedRes, len(expectedRes), storage, len(storage))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEth_GetProof(t *testing.T) {
|
||||||
|
params := make([]interface{}, 3)
|
||||||
|
params[0] = addrA
|
||||||
|
params[1] = []string{string(addrAStoreKey)}
|
||||||
|
params[2] = "latest"
|
||||||
|
rpcRes := call(t, "eth_getProof", params)
|
||||||
|
require.NotNil(t, rpcRes)
|
||||||
|
|
||||||
|
var accRes rpc.AccountResult
|
||||||
|
err := json.Unmarshal(rpcRes.Result, &accRes)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, accRes.AccountProof)
|
||||||
|
require.NotEmpty(t, accRes.StorageProof)
|
||||||
|
|
||||||
|
t.Logf("Got AccountResult %s", rpcRes.Result)
|
||||||
|
}
|
||||||
|
|
||||||
func TestEth_GetCode(t *testing.T) {
|
func TestEth_GetCode(t *testing.T) {
|
||||||
expectedRes := hexutil.Bytes{}
|
expectedRes := hexutil.Bytes{}
|
||||||
rpcRes := call(t, "eth_getCode", []string{addrA, zeroString})
|
rpcRes := call(t, "eth_getCode", []string{addrA, zeroString})
|
||||||
|
Loading…
Reference in New Issue
Block a user