9e5f4aaa73
* test: add preliminary unit tests and additional mocks for chain_info, account_info and filters * tests: added additional mocked client calls * tests: bumped coverage of call_tx to 56% and chain_info to 77% * tests: bumped call_tx coverage to 70.2% and added additional mock client calls * tests: tx_info preliminary tests added for debugging. * tests: added test coverage for sign_tx and additional mocks * tests: tx_info test coverage bumped to 60.3% * test: coverage for tracing_tests now at 72% * tests: added fee makert query client mocks and bumped chain_info to 87.6% coverage. * tests: failing Cosmos auth module account query. * tests: added FeeMarket Params mock to call_tx_test * cleanup some unused code * tests: added helper function to test suite for signing a Tx and bumped coverage of tx_info to 71.2% * test: commented GetAccount error case and bumped chain_info to 90.3% coverage * test: cleanup of tests in node_info, sign_tx and account_info * Clean up print Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Apply suggestions from code review * fix import issues Co-authored-by: Vladislav Varadinov <vlad@evmos.org> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Freddy Caceres <facs95@gmail.com>
275 lines
12 KiB
Go
275 lines
12 KiB
Go
package backend
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
|
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/evmos/ethermint/rpc/backend/mocks"
|
|
rpc "github.com/evmos/ethermint/rpc/types"
|
|
"github.com/evmos/ethermint/tests"
|
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
|
mock "github.com/stretchr/testify/mock"
|
|
"github.com/stretchr/testify/require"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/metadata"
|
|
"google.golang.org/grpc/status"
|
|
"strconv"
|
|
"testing"
|
|
)
|
|
|
|
// QueryClient defines a mocked object that implements the ethermint GRPC
|
|
// QueryClient interface. It allows for performing QueryClient queries without having
|
|
// to run a ethermint GRPC server.
|
|
//
|
|
// To use a mock method it has to be registered in a given test.
|
|
var _ evmtypes.QueryClient = &mocks.EVMQueryClient{}
|
|
|
|
// TraceTransaction
|
|
func RegisterTraceTransactionWithPredecessors(queryClient *mocks.EVMQueryClient, msgEthTx *evmtypes.MsgEthereumTx, predecessors []*evmtypes.MsgEthereumTx) {
|
|
data := []byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x7d}
|
|
queryClient.On("TraceTx", rpc.ContextWithHeight(1),
|
|
&evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1, Predecessors: predecessors}).
|
|
Return(&evmtypes.QueryTraceTxResponse{Data: data}, nil)
|
|
}
|
|
|
|
func RegisterTraceTransaction(queryClient *mocks.EVMQueryClient, msgEthTx *evmtypes.MsgEthereumTx) {
|
|
data := []byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x7d}
|
|
queryClient.On("TraceTx", rpc.ContextWithHeight(1), &evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1}).
|
|
Return(&evmtypes.QueryTraceTxResponse{Data: data}, nil)
|
|
}
|
|
|
|
func RegisterTraceTransactionError(queryClient *mocks.EVMQueryClient, msgEthTx *evmtypes.MsgEthereumTx) {
|
|
queryClient.On("TraceTx", rpc.ContextWithHeight(1), &evmtypes.QueryTraceTxRequest{Msg: msgEthTx, BlockNumber: 1}).
|
|
Return(nil, errortypes.ErrInvalidRequest)
|
|
}
|
|
|
|
// TraceBlock
|
|
func RegisterTraceBlock(queryClient *mocks.EVMQueryClient, txs []*evmtypes.MsgEthereumTx) {
|
|
data := []byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x7d}
|
|
queryClient.On("TraceBlock", rpc.ContextWithHeight(1),
|
|
&evmtypes.QueryTraceBlockRequest{Txs: txs, BlockNumber: 1, TraceConfig: &evmtypes.TraceConfig{}}).
|
|
Return(&evmtypes.QueryTraceBlockResponse{Data: data}, nil)
|
|
}
|
|
|
|
func RegisterTraceBlockError(queryClient *mocks.EVMQueryClient) {
|
|
queryClient.On("TraceBlock", rpc.ContextWithHeight(1), &evmtypes.QueryTraceBlockRequest{}).
|
|
Return(nil, errortypes.ErrInvalidRequest)
|
|
}
|
|
|
|
// Params
|
|
func RegisterParams(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) {
|
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
|
Return(&evmtypes.QueryParamsResponse{}, nil).
|
|
Run(func(args mock.Arguments) {
|
|
// If Params call is successful, also update the header height
|
|
arg := args.Get(2).(grpc.HeaderCallOption)
|
|
h := metadata.MD{}
|
|
h.Set(grpctypes.GRPCBlockHeightHeader, fmt.Sprint(height))
|
|
*arg.HeaderAddr = h
|
|
})
|
|
}
|
|
|
|
func RegisterParamsWithoutHeader(queryClient *mocks.EVMQueryClient, height int64) {
|
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}).
|
|
Return(&evmtypes.QueryParamsResponse{Params: evmtypes.DefaultParams()}, nil)
|
|
}
|
|
|
|
func RegisterParamsInvalidHeader(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) {
|
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
|
Return(&evmtypes.QueryParamsResponse{}, nil).
|
|
Run(func(args mock.Arguments) {
|
|
// If Params call is successful, also update the header height
|
|
arg := args.Get(2).(grpc.HeaderCallOption)
|
|
h := metadata.MD{}
|
|
*arg.HeaderAddr = h
|
|
})
|
|
}
|
|
|
|
func RegisterParamsInvalidHeight(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) {
|
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
|
Return(&evmtypes.QueryParamsResponse{}, nil).
|
|
Run(func(args mock.Arguments) {
|
|
// If Params call is successful, also update the header height
|
|
arg := args.Get(2).(grpc.HeaderCallOption)
|
|
h := metadata.MD{}
|
|
h.Set(grpctypes.GRPCBlockHeightHeader, "invalid")
|
|
*arg.HeaderAddr = h
|
|
})
|
|
}
|
|
|
|
func RegisterParamsWithoutHeaderError(queryClient *mocks.EVMQueryClient, height int64) {
|
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}).
|
|
Return(nil, errortypes.ErrInvalidRequest)
|
|
}
|
|
|
|
// Params returns error
|
|
func RegisterParamsError(queryClient *mocks.EVMQueryClient, header *metadata.MD, height int64) {
|
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
|
Return(nil, errortypes.ErrInvalidRequest)
|
|
}
|
|
|
|
func TestRegisterParams(t *testing.T) {
|
|
var header metadata.MD
|
|
queryClient := mocks.NewEVMQueryClient(t)
|
|
|
|
height := int64(1)
|
|
RegisterParams(queryClient, &header, height)
|
|
|
|
_, err := queryClient.Params(rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(&header))
|
|
require.NoError(t, err)
|
|
blockHeightHeader := header.Get(grpctypes.GRPCBlockHeightHeader)
|
|
headerHeight, err := strconv.ParseInt(blockHeightHeader[0], 10, 64)
|
|
require.NoError(t, err)
|
|
require.Equal(t, height, headerHeight)
|
|
}
|
|
|
|
func TestRegisterParamsError(t *testing.T) {
|
|
queryClient := mocks.NewEVMQueryClient(t)
|
|
RegisterBaseFeeError(queryClient)
|
|
_, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// ETH Call
|
|
func RegisterEthCall(queryClient *mocks.EVMQueryClient, request *evmtypes.EthCallRequest) {
|
|
ctx, _ := context.WithCancel(rpc.ContextWithHeight(1))
|
|
queryClient.On("EthCall", ctx, request).
|
|
Return(&evmtypes.MsgEthereumTxResponse{}, nil)
|
|
}
|
|
|
|
func RegisterEthCallError(queryClient *mocks.EVMQueryClient, request *evmtypes.EthCallRequest) {
|
|
ctx, _ := context.WithCancel(rpc.ContextWithHeight(1))
|
|
queryClient.On("EthCall", ctx, request).
|
|
Return(nil, errortypes.ErrInvalidRequest)
|
|
}
|
|
|
|
// Estimate Gas
|
|
func RegisterEstimateGas(queryClient *mocks.EVMQueryClient, args evmtypes.TransactionArgs) {
|
|
bz, _ := json.Marshal(args)
|
|
queryClient.On("EstimateGas", rpc.ContextWithHeight(1), &evmtypes.EthCallRequest{Args: bz}).
|
|
Return(&evmtypes.EstimateGasResponse{}, nil)
|
|
}
|
|
|
|
// BaseFee
|
|
func RegisterBaseFee(queryClient *mocks.EVMQueryClient, baseFee sdk.Int) {
|
|
queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}).
|
|
Return(&evmtypes.QueryBaseFeeResponse{BaseFee: &baseFee}, nil)
|
|
}
|
|
|
|
// Base fee returns error
|
|
func RegisterBaseFeeError(queryClient *mocks.EVMQueryClient) {
|
|
queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}).
|
|
Return(&evmtypes.QueryBaseFeeResponse{}, evmtypes.ErrInvalidBaseFee)
|
|
}
|
|
|
|
// Base fee not enabled
|
|
func RegisterBaseFeeDisabled(queryClient *mocks.EVMQueryClient) {
|
|
queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}).
|
|
Return(&evmtypes.QueryBaseFeeResponse{}, nil)
|
|
}
|
|
|
|
func TestRegisterBaseFee(t *testing.T) {
|
|
baseFee := sdk.NewInt(1)
|
|
queryClient := mocks.NewEVMQueryClient(t)
|
|
RegisterBaseFee(queryClient, baseFee)
|
|
res, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{})
|
|
require.Equal(t, &evmtypes.QueryBaseFeeResponse{BaseFee: &baseFee}, res)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestRegisterBaseFeeError(t *testing.T) {
|
|
queryClient := mocks.NewEVMQueryClient(t)
|
|
RegisterBaseFeeError(queryClient)
|
|
res, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{})
|
|
require.Equal(t, &evmtypes.QueryBaseFeeResponse{}, res)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestRegisterBaseFeeDisabled(t *testing.T) {
|
|
queryClient := mocks.NewEVMQueryClient(t)
|
|
RegisterBaseFeeDisabled(queryClient)
|
|
res, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{})
|
|
require.Equal(t, &evmtypes.QueryBaseFeeResponse{}, res)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// ValidatorAccount
|
|
func RegisterValidatorAccount(queryClient *mocks.EVMQueryClient, validator sdk.AccAddress) {
|
|
queryClient.On("ValidatorAccount", rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}).
|
|
Return(&evmtypes.QueryValidatorAccountResponse{AccountAddress: validator.String()}, nil)
|
|
}
|
|
|
|
func RegisterValidatorAccountError(queryClient *mocks.EVMQueryClient) {
|
|
queryClient.On("ValidatorAccount", rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}).
|
|
Return(nil, status.Error(codes.InvalidArgument, "empty request"))
|
|
}
|
|
|
|
func TestRegisterValidatorAccount(t *testing.T) {
|
|
queryClient := mocks.NewEVMQueryClient(t)
|
|
|
|
validator := sdk.AccAddress(tests.GenerateAddress().Bytes())
|
|
RegisterValidatorAccount(queryClient, validator)
|
|
res, err := queryClient.ValidatorAccount(rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{})
|
|
require.Equal(t, &evmtypes.QueryValidatorAccountResponse{AccountAddress: validator.String()}, res)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Code
|
|
func RegisterCode(queryClient *mocks.EVMQueryClient, addr common.Address, code []byte) {
|
|
queryClient.On("Code", rpc.ContextWithHeight(1), &evmtypes.QueryCodeRequest{Address: addr.String()}).
|
|
Return(&evmtypes.QueryCodeResponse{Code: code}, nil)
|
|
}
|
|
|
|
func RegisterCodeError(queryClient *mocks.EVMQueryClient, addr common.Address) {
|
|
queryClient.On("Code", rpc.ContextWithHeight(1), &evmtypes.QueryCodeRequest{Address: addr.String()}).
|
|
Return(nil, errortypes.ErrInvalidRequest)
|
|
}
|
|
|
|
// Storage
|
|
func RegisterStorageAt(queryClient *mocks.EVMQueryClient, addr common.Address, key string, storage string) {
|
|
queryClient.On("Storage", rpc.ContextWithHeight(1), &evmtypes.QueryStorageRequest{Address: addr.String(), Key: key}).
|
|
Return(&evmtypes.QueryStorageResponse{Value: storage}, nil)
|
|
}
|
|
|
|
func RegisterStorageAtError(queryClient *mocks.EVMQueryClient, addr common.Address, key string) {
|
|
queryClient.On("Storage", rpc.ContextWithHeight(1), &evmtypes.QueryStorageRequest{Address: addr.String(), Key: key}).
|
|
Return(nil, errortypes.ErrInvalidRequest)
|
|
}
|
|
|
|
func RegisterAccount(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) {
|
|
queryClient.On("Account", rpc.ContextWithHeight(height), &evmtypes.QueryAccountRequest{Address: addr.String()}).
|
|
Return(&evmtypes.QueryAccountResponse{
|
|
Balance: "0",
|
|
CodeHash: "",
|
|
Nonce: 0,
|
|
},
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// Balance
|
|
func RegisterBalance(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) {
|
|
queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}).
|
|
Return(&evmtypes.QueryBalanceResponse{Balance: "1"}, nil)
|
|
}
|
|
|
|
func RegisterBalanceInvalid(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) {
|
|
queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}).
|
|
Return(&evmtypes.QueryBalanceResponse{Balance: "invalid"}, nil)
|
|
}
|
|
|
|
func RegisterBalanceNegative(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) {
|
|
queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}).
|
|
Return(&evmtypes.QueryBalanceResponse{Balance: "-1"}, nil)
|
|
}
|
|
|
|
func RegisterBalanceError(queryClient *mocks.EVMQueryClient, addr common.Address, height int64) {
|
|
queryClient.On("Balance", rpc.ContextWithHeight(height), &evmtypes.QueryBalanceRequest{Address: addr.String()}).
|
|
Return(nil, errortypes.ErrInvalidRequest)
|
|
}
|