laconicd-deprecated/rpc/backend/sign_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

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)
}
})
}
}