* 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>
		
			
				
	
	
		
			261 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			261 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package backend
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"github.com/cosmos/cosmos-sdk/crypto"
 | |
| 	sdk "github.com/cosmos/cosmos-sdk/types"
 | |
| 	"github.com/ethereum/go-ethereum/common"
 | |
| 	"github.com/ethereum/go-ethereum/common/hexutil"
 | |
| 	ethtypes "github.com/ethereum/go-ethereum/core/types"
 | |
| 	goethcrypto "github.com/ethereum/go-ethereum/crypto"
 | |
| 	"github.com/ethereum/go-ethereum/signer/core/apitypes"
 | |
| 	"github.com/evmos/ethermint/crypto/ethsecp256k1"
 | |
| 	"github.com/evmos/ethermint/rpc/backend/mocks"
 | |
| 	"github.com/evmos/ethermint/tests"
 | |
| 	evmtypes "github.com/evmos/ethermint/x/evm/types"
 | |
| 	"google.golang.org/grpc/metadata"
 | |
| )
 | |
| 
 | |
| func (suite *BackendTestSuite) TestSendTransaction() {
 | |
| 	gasPrice := new(hexutil.Big)
 | |
| 	gas := hexutil.Uint64(1)
 | |
| 	zeroGas := hexutil.Uint64(0)
 | |
| 	toAddr := tests.GenerateAddress()
 | |
| 	priv, _ := ethsecp256k1.GenerateKey()
 | |
| 	from := common.BytesToAddress(priv.PubKey().Address().Bytes())
 | |
| 	nonce := hexutil.Uint64(1)
 | |
| 	baseFee := sdk.NewInt(1)
 | |
| 	callArgsDefault := evmtypes.TransactionArgs{
 | |
| 		From:     &from,
 | |
| 		To:       &toAddr,
 | |
| 		GasPrice: gasPrice,
 | |
| 		Gas:      &gas,
 | |
| 		Nonce:    &nonce,
 | |
| 	}
 | |
| 
 | |
| 	hash := common.Hash{}
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		name         string
 | |
| 		registerMock func()
 | |
| 		args         evmtypes.TransactionArgs
 | |
| 		expHash      common.Hash
 | |
| 		expPass      bool
 | |
| 	}{
 | |
| 		{
 | |
| 			"fail - Can't find account in Keyring",
 | |
| 			func() {},
 | |
| 			evmtypes.TransactionArgs{},
 | |
| 			hash,
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"fail - Block error can't set Tx defaults",
 | |
| 			func() {
 | |
| 				var header metadata.MD
 | |
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
 | |
| 				client := suite.backend.clientCtx.Client.(*mocks.Client)
 | |
| 				armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1")
 | |
| 				suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "")
 | |
| 				RegisterParams(queryClient, &header, 1)
 | |
| 				RegisterBlockError(client, 1)
 | |
| 			},
 | |
| 			callArgsDefault,
 | |
| 			hash,
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"fail - Cannot validate transaction gas set to 0",
 | |
| 			func() {
 | |
| 				var header metadata.MD
 | |
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
 | |
| 				client := suite.backend.clientCtx.Client.(*mocks.Client)
 | |
| 				armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1")
 | |
| 				suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "")
 | |
| 				RegisterParams(queryClient, &header, 1)
 | |
| 				RegisterBlock(client, 1, nil)
 | |
| 				RegisterBlockResults(client, 1)
 | |
| 				RegisterBaseFee(queryClient, baseFee)
 | |
| 			},
 | |
| 			evmtypes.TransactionArgs{
 | |
| 				From:     &from,
 | |
| 				To:       &toAddr,
 | |
| 				GasPrice: gasPrice,
 | |
| 				Gas:      &zeroGas,
 | |
| 				Nonce:    &nonce,
 | |
| 			},
 | |
| 			hash,
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"fail - Cannot broadcast transaction",
 | |
| 			func() {
 | |
| 				var header metadata.MD
 | |
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
 | |
| 				client := suite.backend.clientCtx.Client.(*mocks.Client)
 | |
| 				armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1")
 | |
| 				suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "")
 | |
| 				RegisterParams(queryClient, &header, 1)
 | |
| 				RegisterBlock(client, 1, nil)
 | |
| 				RegisterBlockResults(client, 1)
 | |
| 				RegisterBaseFee(queryClient, baseFee)
 | |
| 				RegisterParamsWithoutHeader(queryClient, 1)
 | |
| 				ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
 | |
| 				msg := callArgsDefault.ToTransaction()
 | |
| 				msg.Sign(ethSigner, suite.backend.clientCtx.Keyring)
 | |
| 				tx, _ := msg.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
 | |
| 				txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder()
 | |
| 				txBytes, _ := txEncoder(tx)
 | |
| 				RegisterBroadcastTxError(client, txBytes)
 | |
| 			},
 | |
| 			callArgsDefault,
 | |
| 			common.Hash{},
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"pass - Return the transaction hash",
 | |
| 			func() {
 | |
| 				var header metadata.MD
 | |
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
 | |
| 				client := suite.backend.clientCtx.Client.(*mocks.Client)
 | |
| 				armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1")
 | |
| 				suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "")
 | |
| 				RegisterParams(queryClient, &header, 1)
 | |
| 				RegisterBlock(client, 1, nil)
 | |
| 				RegisterBlockResults(client, 1)
 | |
| 				RegisterBaseFee(queryClient, baseFee)
 | |
| 				RegisterParamsWithoutHeader(queryClient, 1)
 | |
| 				ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
 | |
| 				msg := callArgsDefault.ToTransaction()
 | |
| 				msg.Sign(ethSigner, suite.backend.clientCtx.Keyring)
 | |
| 				tx, _ := msg.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
 | |
| 				txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder()
 | |
| 				txBytes, _ := txEncoder(tx)
 | |
| 				RegisterBroadcastTx(client, txBytes)
 | |
| 			},
 | |
| 			callArgsDefault,
 | |
| 			hash,
 | |
| 			true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tc := range testCases {
 | |
| 		suite.Run(fmt.Sprintf("case %s", tc.name), func() {
 | |
| 			suite.SetupTest() // reset test and queries
 | |
| 			tc.registerMock()
 | |
| 
 | |
| 			if tc.expPass {
 | |
| 				// Sign the transaction and get the hash
 | |
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
 | |
| 				RegisterParamsWithoutHeader(queryClient, 1)
 | |
| 				ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
 | |
| 				msg := callArgsDefault.ToTransaction()
 | |
| 				msg.Sign(ethSigner, suite.backend.clientCtx.Keyring)
 | |
| 				tc.expHash = msg.AsTransaction().Hash()
 | |
| 			}
 | |
| 			responseHash, err := suite.backend.SendTransaction(tc.args)
 | |
| 			if tc.expPass {
 | |
| 				suite.Require().NoError(err)
 | |
| 				suite.Require().Equal(tc.expHash, responseHash)
 | |
| 			} else {
 | |
| 				suite.Require().Error(err)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (suite *BackendTestSuite) TestSign() {
 | |
| 	from, priv := tests.NewAddrKey()
 | |
| 	testCases := []struct {
 | |
| 		name         string
 | |
| 		registerMock func()
 | |
| 		fromAddr     common.Address
 | |
| 		inputBz      hexutil.Bytes
 | |
| 		expPass      bool
 | |
| 	}{
 | |
| 		{
 | |
| 			"fail - can't find key in Keyring",
 | |
| 			func() {},
 | |
| 			from,
 | |
| 			nil,
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"pass - sign nil data",
 | |
| 			func() {
 | |
| 				armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1")
 | |
| 				suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "")
 | |
| 			},
 | |
| 			from,
 | |
| 			nil,
 | |
| 			true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tc := range testCases {
 | |
| 		suite.Run(fmt.Sprintf("case %s", tc.name), func() {
 | |
| 			suite.SetupTest() // reset test and queries
 | |
| 			tc.registerMock()
 | |
| 
 | |
| 			responseBz, err := suite.backend.Sign(tc.fromAddr, tc.inputBz)
 | |
| 			if tc.expPass {
 | |
| 				signature, _, err := suite.backend.clientCtx.Keyring.SignByAddress((sdk.AccAddress)(from.Bytes()), tc.inputBz)
 | |
| 				signature[goethcrypto.RecoveryIDOffset] += 27
 | |
| 				suite.Require().NoError(err)
 | |
| 				suite.Require().Equal((hexutil.Bytes)(signature), responseBz)
 | |
| 			} else {
 | |
| 				suite.Require().Error(err)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (suite *BackendTestSuite) TestSignTypedData() {
 | |
| 	from, priv := tests.NewAddrKey()
 | |
| 	testCases := []struct {
 | |
| 		name           string
 | |
| 		registerMock   func()
 | |
| 		fromAddr       common.Address
 | |
| 		inputTypedData apitypes.TypedData
 | |
| 		expPass        bool
 | |
| 	}{
 | |
| 		{
 | |
| 			"fail - can't find key in Keyring",
 | |
| 			func() {},
 | |
| 			from,
 | |
| 			apitypes.TypedData{},
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"fail - empty TypeData",
 | |
| 			func() {
 | |
| 				armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1")
 | |
| 				suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "")
 | |
| 			},
 | |
| 			from,
 | |
| 			apitypes.TypedData{},
 | |
| 			false,
 | |
| 		},
 | |
| 		// TODO: Generate a TypedData msg
 | |
| 	}
 | |
| 
 | |
| 	for _, tc := range testCases {
 | |
| 		suite.Run(fmt.Sprintf("case %s", tc.name), func() {
 | |
| 			suite.SetupTest() // reset test and queries
 | |
| 			tc.registerMock()
 | |
| 
 | |
| 			responseBz, err := suite.backend.SignTypedData(tc.fromAddr, tc.inputTypedData)
 | |
| 
 | |
| 			if tc.expPass {
 | |
| 				sigHash, _, err := apitypes.TypedDataAndHash(tc.inputTypedData)
 | |
| 				signature, _, err := suite.backend.clientCtx.Keyring.SignByAddress((sdk.AccAddress)(from.Bytes()), sigHash)
 | |
| 				signature[goethcrypto.RecoveryIDOffset] += 27
 | |
| 				suite.Require().NoError(err)
 | |
| 				suite.Require().Equal((hexutil.Bytes)(signature), responseBz)
 | |
| 			} else {
 | |
| 				suite.Require().Error(err)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 |