laconicd-deprecated/rpc/backend/call_tx_test.go
Vladislav Varadinov 9e5f4aaa73
tests: Add unit tests for rpc client endpoints (#1409)
* 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>
2022-11-17 01:35:15 +00:00

485 lines
12 KiB
Go

package backend
import (
"encoding/json"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rlp"
"github.com/evmos/ethermint/rpc/backend/mocks"
rpctypes "github.com/evmos/ethermint/rpc/types"
"github.com/evmos/ethermint/tests"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"google.golang.org/grpc/metadata"
"math/big"
)
func (suite *BackendTestSuite) TestResend() {
txNonce := (hexutil.Uint64)(1)
baseFee := sdk.NewInt(1)
gasPrice := new(hexutil.Big)
toAddr := tests.GenerateAddress()
callArgs := evmtypes.TransactionArgs{
From: nil,
To: &toAddr,
Gas: nil,
GasPrice: nil,
MaxFeePerGas: gasPrice,
MaxPriorityFeePerGas: gasPrice,
Value: gasPrice,
Nonce: nil,
Input: nil,
Data: nil,
AccessList: nil,
}
testCases := []struct {
name string
registerMock func()
args evmtypes.TransactionArgs
gasPrice *hexutil.Big
gasLimit *hexutil.Uint64
expHash common.Hash
expPass bool
}{
{
"fail - Missing transaction nonce ",
func() {},
evmtypes.TransactionArgs{
Nonce: nil,
},
nil,
nil,
common.Hash{},
false,
},
{
"pass - Can't set Tx defaults BaseFee disabled",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFeeDisabled(queryClient)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
},
nil,
nil,
common.Hash{},
true,
},
{
"pass - Can't set Tx defaults ",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterFeeMarketParams(feeMarketClient, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
},
nil,
nil,
common.Hash{},
true,
},
{
"pass - MaxFeePerGas is nil",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFeeDisabled(queryClient)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
MaxPriorityFeePerGas: nil,
GasPrice: nil,
MaxFeePerGas: nil,
},
nil,
nil,
common.Hash{},
true,
},
{
"fail - GasPrice and (MaxFeePerGas or MaxPriorityPerGas specified",
func() {},
evmtypes.TransactionArgs{
Nonce: &txNonce,
MaxPriorityFeePerGas: nil,
GasPrice: gasPrice,
MaxFeePerGas: gasPrice,
},
nil,
nil,
common.Hash{},
false,
},
{
"fail - Block error",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlockError(client, 1)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
},
nil,
nil,
common.Hash{},
false,
},
{
"pass - MaxFeePerGas is nil",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
GasPrice: nil,
MaxPriorityFeePerGas: gasPrice,
MaxFeePerGas: gasPrice,
},
nil,
nil,
common.Hash{},
true,
},
{
"pass - Chain Id is nil",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
MaxPriorityFeePerGas: gasPrice,
ChainID: nil,
},
nil,
nil,
common.Hash{},
true,
},
{
"fail - Pending transactions error",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
RegisterEstimateGas(queryClient, callArgs)
RegisterParams(queryClient, &header, 1)
RegisterParamsWithoutHeader(queryClient, 1)
RegisterUnconfirmedTxsError(client, nil)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
To: &toAddr,
MaxFeePerGas: gasPrice,
MaxPriorityFeePerGas: gasPrice,
Gas: nil,
},
gasPrice,
nil,
common.Hash{},
false,
},
{
"fail - Not Ethereum txs",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
RegisterEstimateGas(queryClient, callArgs)
RegisterParams(queryClient, &header, 1)
RegisterParamsWithoutHeader(queryClient, 1)
RegisterUnconfirmedTxsEmpty(client, nil)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
To: &toAddr,
MaxFeePerGas: gasPrice,
MaxPriorityFeePerGas: gasPrice,
Gas: nil,
},
gasPrice,
nil,
common.Hash{},
false,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
hash, err := suite.backend.Resend(tc.args, tc.gasPrice, tc.gasLimit)
if tc.expPass {
suite.Require().Equal(tc.expHash, hash)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestSendRawTransaction() {
ethTx, bz := suite.buildEthereumTx()
rlpEncodedBz, _ := rlp.EncodeToBytes(ethTx.AsTransaction())
cosmosTx, _ := ethTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
txBytes, _ := suite.backend.clientCtx.TxConfig.TxEncoder()(cosmosTx)
testCases := []struct {
name string
registerMock func()
rawTx []byte
expHash common.Hash
expPass bool
}{
{
"fail - empty bytes",
func() {},
[]byte{},
common.Hash{},
false,
},
{
"fail - no RLP encoded bytes",
func() {},
bz,
common.Hash{},
false,
},
{
"fail - unprotected transactions",
func() {
suite.backend.allowUnprotectedTxs = false
},
rlpEncodedBz,
common.Hash{},
false,
},
{
"fail - failed to get evm params",
func() {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
suite.backend.allowUnprotectedTxs = true
RegisterParamsWithoutHeaderError(queryClient, 1)
},
rlpEncodedBz,
common.Hash{},
false,
},
{
"fail - failed to broadcast transaction",
func() {
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
suite.backend.allowUnprotectedTxs = true
RegisterParamsWithoutHeader(queryClient, 1)
RegisterBroadcastTxError(client, txBytes)
},
rlpEncodedBz,
common.HexToHash(ethTx.Hash),
false,
},
{
"pass - Gets the correct transaction hash of the eth transaction",
func() {
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
suite.backend.allowUnprotectedTxs = true
RegisterParamsWithoutHeader(queryClient, 1)
RegisterBroadcastTx(client, txBytes)
},
rlpEncodedBz,
common.HexToHash(ethTx.Hash),
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
hash, err := suite.backend.SendRawTransaction(tc.rawTx)
if tc.expPass {
suite.Require().Equal(tc.expHash, hash)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestDoCall() {
_, bz := suite.buildEthereumTx()
gasPrice := (*hexutil.Big)(big.NewInt(1))
toAddr := tests.GenerateAddress()
callArgs := evmtypes.TransactionArgs{
From: nil,
To: &toAddr,
Gas: nil,
GasPrice: nil,
MaxFeePerGas: gasPrice,
MaxPriorityFeePerGas: gasPrice,
Value: gasPrice,
Input: nil,
Data: nil,
AccessList: nil,
}
argsBz, err := json.Marshal(callArgs)
suite.Require().NoError(err)
testCases := []struct {
name string
registerMock func()
blockNum rpctypes.BlockNumber
callArgs evmtypes.TransactionArgs
expEthTx *evmtypes.MsgEthereumTxResponse
expPass bool
}{
{
"fail - Invalid request",
func() {
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBlock(client, 1, bz)
RegisterEthCallError(queryClient, &evmtypes.EthCallRequest{Args: argsBz})
},
rpctypes.BlockNumber(1),
callArgs,
&evmtypes.MsgEthereumTxResponse{},
false,
},
{
"pass - Returned transaction response",
func() {
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBlock(client, 1, bz)
RegisterEthCall(queryClient, &evmtypes.EthCallRequest{Args: argsBz})
},
rpctypes.BlockNumber(1),
callArgs,
&evmtypes.MsgEthereumTxResponse{},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
msgEthTx, err := suite.backend.DoCall(tc.callArgs, tc.blockNum)
if tc.expPass {
suite.Require().Equal(tc.expEthTx, msgEthTx)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGasPrice() {
defaultGasPrice := (*hexutil.Big)(big.NewInt(1))
testCases := []struct {
name string
registerMock func()
expGas *hexutil.Big
expPass bool
}{
{
"pass - get the default gas price",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
RegisterFeeMarketParams(feeMarketClient, 1)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, sdk.NewInt(1))
},
defaultGasPrice,
true,
},
{
"fail - can't get gasFee, FeeMarketParams error",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
RegisterFeeMarketParamsError(feeMarketClient, 1)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, sdk.NewInt(1))
},
defaultGasPrice,
false,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
gasPrice, err := suite.backend.GasPrice()
if tc.expPass {
suite.Require().Equal(tc.expGas, gasPrice)
} else {
suite.Require().Error(err)
}
})
}
}