Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: synthetic eth txs unit tests #2342

Merged
merged 24 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
* [2240](https://github.com/zeta-chain/node/pull/2240) - removed hard-coded Bitcoin regnet chainID in E2E withdraw tests
* [2266](https://github.com/zeta-chain/node/pull/2266) - try fixing E2E test `crosschain_swap` failure `btc transaction not signed`
* [2294](https://github.com/zeta-chain/node/pull/2294) - add and fix existing ethermint rpc unit test
* [2329](https://github.com/zeta-chain/node/pull/2329) - fix TODOs in rpc unit tests
* [2342](https://github.com/zeta-chain/node/pull/2342) - synthetic eth txs unit tests
* [2299](https://github.com/zeta-chain/node/pull/2299) - add `zetae2e` command to deploy test contracts

### Fixes
Expand Down
55 changes: 32 additions & 23 deletions rpc/backend/account_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"math/big"

tmrpcclient "github.com/cometbft/cometbft/rpc/client"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -82,6 +83,7 @@ func (suite *BackendTestSuite) TestGetProof() {
blockNrInvalid := rpctypes.NewBlockNumber(big.NewInt(1))
blockNr := rpctypes.NewBlockNumber(big.NewInt(4))
address1 := tests.GenerateAddress()
expProofValue := big.NewInt(2)

testCases := []struct {
name string
Expand All @@ -93,7 +95,7 @@ func (suite *BackendTestSuite) TestGetProof() {
expAccRes *rpctypes.AccountResult
}{
{
"fail - BlockNumeber = 1 (invalidBlockNumber)",
"fail - BlockNumber = 1 (invalidBlockNumber)",
address1,
[]string{},
rpctypes.BlockNumberOrHash{BlockNumber: &blockNrInvalid},
Expand Down Expand Up @@ -139,13 +141,15 @@ func (suite *BackendTestSuite) TestGetProof() {
"store/evm/key",
evmtypes.StateKey(address1, common.HexToHash("0x0").Bytes()),
tmrpcclient.ABCIQueryOptions{Height: iavlHeight, Prove: true},
expProofValue.Bytes(),
)
RegisterABCIQueryWithOptions(
client,
bn.Int64(),
"store/acc/key",
authtypes.AddressStoreKey(sdk.AccAddress(address1.Bytes())),
tmrpcclient.ABCIQueryOptions{Height: iavlHeight, Prove: true},
expProofValue.Bytes(),
)
},
true,
Expand All @@ -159,7 +163,7 @@ func (suite *BackendTestSuite) TestGetProof() {
StorageProof: []rpctypes.StorageResult{
{
Key: "0x0",
Value: (*hexutil.Big)(big.NewInt(2)),
Value: (*hexutil.Big)(expProofValue),
Proof: []string{""},
},
},
Expand Down Expand Up @@ -415,27 +419,32 @@ func (suite *BackendTestSuite) TestGetTransactionCount() {
false,
hexutil.Uint64(0),
},
// TODO (https://github.com/zeta-chain/node/issues/2302): Error mocking the GetAccount call - problem with Any type
//{
// "pass - returns the number of transactions at the given address up to the given block number",
// true,
// rpctypes.NewBlockNumber(big.NewInt(1)),
// func(addr common.Address, bn rpctypes.BlockNumber) {
// client := suite.backend.clientCtx.Client.(*mocks.Client)
// account, err := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, suite.acc)
// suite.Require().NoError(err)
// request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(suite.acc.Bytes()).String()}
// requestMarshal, _ := request.Marshal()
// RegisterABCIQueryAccount(
// client,
// requestMarshal,
// tmrpcclient.ABCIQueryOptions{Height: int64(1), Prove: false},
// account,
// )
// },
// true,
// hexutil.Uint64(0),
//},
{
"pass - returns the number of transactions at the given address up to the given block number",
true,
rpctypes.NewBlockNumber(big.NewInt(1)),
func(addr common.Address, bn rpctypes.BlockNumber) {
var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
suite.backend.clientCtx = suite.backend.clientCtx.WithInterfaceRegistry(
codectypes.NewInterfaceRegistry(),
)
client := suite.backend.clientCtx.Client.(*mocks.Client)
account, err := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, suite.acc)
suite.Require().NoError(err)
request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(suite.acc.Bytes()).String()}
requestMarshal, _ := request.Marshal()
RegisterABCIQueryAccount(
client,
requestMarshal,
tmrpcclient.ABCIQueryOptions{Height: int64(1), Prove: false},
account,
)
},
true,
hexutil.Uint64(1),
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
Expand Down
54 changes: 54 additions & 0 deletions rpc/backend/backend_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"

dbm "github.com/cometbft/cometbft-db"
abci "github.com/cometbft/cometbft/abci/types"
tmrpctypes "github.com/cometbft/cometbft/rpc/core/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
Expand Down Expand Up @@ -35,6 +36,30 @@ type BackendTestSuite struct {
signer keyring.Signer
}

// testTx is a dummy implementation of cosmos Tx used for testing.
type testTx struct {
}

func (tx testTx) GetMsgs() []sdk.Msg { return nil }
func (tx testTx) GetSigners() []sdk.AccAddress { return nil }

func (tx testTx) ValidateBasic() error { return nil }
func (t testTx) ProtoMessage() { panic("not implemented") }
func (t testTx) Reset() { panic("not implemented") }

func (t testTx) String() string { panic("not implemented") }

func (t testTx) Bytes() []byte { panic("not implemented") }

func (t testTx) VerifySignature(msg []byte, sig []byte) bool { panic("not implemented") }

func (t testTx) Type() string { panic("not implemented") }

var (
_ sdk.Tx = (*testTx)(nil)
_ sdk.Msg = (*testTx)(nil)
)

func TestBackendTestSuite(t *testing.T) {
suite.Run(t, new(BackendTestSuite))
}
Expand All @@ -55,6 +80,7 @@ func (suite *BackendTestSuite) SetupTest() {
}

// Create Account with set sequence

suite.acc = sdk.AccAddress(tests.GenerateAddress().Bytes())
accounts := map[string]client.TestAccount{}
accounts[suite.acc.String()] = client.TestAccount{
Expand Down Expand Up @@ -117,6 +143,34 @@ func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byt
return msgEthereumTx, bz
}

func (suite *BackendTestSuite) buildSyntheticTxResult(txHash string) ([]byte, abci.ResponseDeliverTx) {
testTx := &testTx{}
txBuilder := suite.backend.clientCtx.TxConfig.NewTxBuilder()
txBuilder.SetSignatures()
txBuilder.SetMsgs(testTx)
bz, _ := suite.backend.clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
return bz, abci.ResponseDeliverTx{
Code: 0,
Events: []abci.Event{
{Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
{Key: "ethereumTxHash", Value: txHash},
{Key: "txIndex", Value: "8888"},
{Key: "amount", Value: "1000"},
{Key: "txGasUsed", Value: "21000"},
{Key: "txHash", Value: ""},
{Key: "recipient", Value: "0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7"},
}},
{
Type: "message", Attributes: []abci.EventAttribute{
{Key: "sender", Value: "0x735b14BB79463307AAcBED86DAf3322B1e6226aB"},
{Key: "txType", Value: "88"},
{Key: "txNonce", Value: "1"},
},
},
},
}
}

// buildFormattedBlock returns a formatted block for testing
func (suite *BackendTestSuite) buildFormattedBlock(
blockRes *tmrpctypes.ResultBlockResults,
Expand Down
116 changes: 110 additions & 6 deletions rpc/backend/blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

sdkmath "cosmossdk.io/math"
"github.com/cometbft/cometbft/abci/types"
abci "github.com/cometbft/cometbft/abci/types"
tmrpctypes "github.com/cometbft/cometbft/rpc/core/types"
tmtypes "github.com/cometbft/cometbft/types"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -19,6 +20,7 @@ import (

"github.com/zeta-chain/zetacore/rpc/backend/mocks"
ethrpc "github.com/zeta-chain/zetacore/rpc/types"
"github.com/zeta-chain/zetacore/testutil/sample"
)

func (suite *BackendTestSuite) TestBlockNumber() {
Expand Down Expand Up @@ -140,7 +142,7 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() {
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int, validator sdk.AccAddress, txBz []byte) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
resBlock, _ = RegisterBlock(client, height, txBz)
resBlock, _ = RegisterBlock(client, height, []tmtypes.Tx{txBz})
RegisterBlockResultsError(client, blockNum.Int64())
},
true,
Expand All @@ -157,7 +159,7 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() {
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int, validator sdk.AccAddress, txBz []byte) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
resBlock, _ = RegisterBlock(client, height, txBz)
resBlock, _ = RegisterBlock(client, height, []tmtypes.Tx{txBz})
blockRes, _ = RegisterBlockResults(client, blockNum.Int64())
RegisterConsensusParams(client, height)

Expand All @@ -179,7 +181,7 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() {
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int, validator sdk.AccAddress, txBz []byte) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
resBlock, _ = RegisterBlock(client, height, txBz)
resBlock, _ = RegisterBlock(client, height, []tmtypes.Tx{txBz})
blockRes, _ = RegisterBlockResults(client, blockNum.Int64())
RegisterConsensusParams(client, height)

Expand Down Expand Up @@ -497,7 +499,7 @@ func (suite *BackendTestSuite) TestGetBlockTransactionCountByNumber() {
func(blockNum ethrpc.BlockNumber) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, height, bz)
RegisterBlock(client, height, []tmtypes.Tx{bz})
RegisterBlockResults(client, height)
},
hexutil.Uint(1),
Expand Down Expand Up @@ -1268,7 +1270,7 @@ func (suite *BackendTestSuite) TestHeaderByNumber() {
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
expResultBlock, _ = RegisterBlock(client, height, bz)
expResultBlock, _ = RegisterBlock(client, height, []tmtypes.Tx{bz})
RegisterBlockResults(client, height)

queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
Expand Down Expand Up @@ -1471,7 +1473,7 @@ func (suite *BackendTestSuite) TestEthBlockByNumber() {
func(blockNum ethrpc.BlockNumber) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, height, bz)
RegisterBlock(client, height, []tmtypes.Tx{bz})

RegisterBlockResults(client, blockNum.Int64())
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
Expand Down Expand Up @@ -1613,3 +1615,105 @@ func (suite *BackendTestSuite) TestEthBlockFromTendermintBlock() {
})
}
}

func (suite *BackendTestSuite) TestEthAndSyntheticMsgsFromTendermintBlock() {
// synthetic tx
hash := sample.Hash().Hex()
tx, txRes := suite.buildSyntheticTxResult(hash)

// real tx
msgEthereumTx, _ := suite.buildEthereumTx()
realTx := suite.signAndEncodeEthTx(msgEthereumTx)

suite.backend.indexer = nil
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
// block contains block real and synthetic tx
resBlock, _ := RegisterBlock(client, 1, []tmtypes.Tx{realTx, tx})
blockRes, _ := RegisterBlockResultsWithTxResults(client, 1, []*abci.ResponseDeliverTx{{}, &txRes})
RegisterBaseFee(queryClient, sdk.NewInt(1))

// both real and synthetic should be returned
msgs, additionals := suite.backend.EthMsgsFromTendermintBlock(resBlock, blockRes)
suite.Require().Equal(2, len(msgs))
suite.Require().Equal(2, len(additionals))

suite.Require().Nil(additionals[0])
suite.Require().NotNil(additionals[1])

suite.Require().Equal(msgEthereumTx.Hash, msgs[0].Hash)
suite.Require().Equal(hash, msgs[1].Hash)
}

func (suite *BackendTestSuite) TestEthAndSyntheticEthBlockByNumber() {
// synthetic tx
hash := sample.Hash().Hex()
tx, txRes := suite.buildSyntheticTxResult(hash)

// real tx
msgEthereumTx, _ := suite.buildEthereumTx()
realTx := suite.signAndEncodeEthTx(msgEthereumTx)

suite.backend.indexer = nil
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
// block contains block real and synthetic tx
RegisterBlock(client, 1, []tmtypes.Tx{realTx, tx})
RegisterBlockResultsWithTxResults(client, 1, []*abci.ResponseDeliverTx{{}, &txRes})
RegisterBaseFee(queryClient, sdk.NewInt(1))

// only real should be returned
block, err := suite.backend.EthBlockByNumber(1)
suite.Require().NoError(err)
suite.Require().Equal(1, len(block.Transactions()))
suite.Require().Equal(msgEthereumTx.Hash, block.Transactions()[0].Hash().String())
}

func (suite *BackendTestSuite) TestEthAndSyntheticGetBlockByNumber() {
// synthetic tx
hash := sample.Hash().Hex()
tx, txRes := suite.buildSyntheticTxResult(hash)

// real tx
msgEthereumTx, _ := suite.buildEthereumTx()
realTx := suite.signAndEncodeEthTx(msgEthereumTx)

suite.backend.indexer = nil
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
// block contains block real and synthetic tx
RegisterBlock(client, 1, []tmtypes.Tx{realTx, tx})
RegisterBlockResultsWithTxResults(client, 1, []*abci.ResponseDeliverTx{{}, &txRes})
RegisterBaseFee(queryClient, sdk.NewInt(1))
RegisterValidatorAccount(queryClient, sdk.AccAddress(common.Address{}.Bytes()))
RegisterConsensusParams(client, 1)

// both real and synthetic should be returned
block, err := suite.backend.GetBlockByNumber(1, false)
suite.Require().NoError(err)

transactions := block["transactions"].([]interface{})
suite.Require().Equal(2, len(transactions))
suite.Require().Equal(common.HexToHash(msgEthereumTx.Hash), transactions[0])
suite.Require().Equal(common.HexToHash(hash), transactions[1])

// both real and synthetic should be returned
block, err = suite.backend.GetBlockByNumber(1, true)
suite.Require().NoError(err)

transactions = block["transactions"].([]interface{})
suite.Require().Equal(2, len(transactions))
resRealTx := transactions[0].(*ethrpc.RPCTransaction)
suite.Require().Equal(common.HexToHash(msgEthereumTx.Hash), resRealTx.Hash)
resSyntheticTx := transactions[1].(*ethrpc.RPCTransaction)
suite.Require().Equal(common.HexToHash(hash), resSyntheticTx.Hash)

suite.Require().Equal(hash, resSyntheticTx.Hash.Hex())
suite.Require().Equal("0x735b14BB79463307AAcBED86DAf3322B1e6226aB", resSyntheticTx.From.Hex())
suite.Require().Equal("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7", resSyntheticTx.To.Hex())
suite.Require().Equal("0x58", resSyntheticTx.Type.String())
suite.Require().Equal("0x1", resSyntheticTx.Nonce.String())
suite.Require().Nil(resSyntheticTx.V)
suite.Require().Nil(resSyntheticTx.R)
suite.Require().Nil(resSyntheticTx.S)
}
2 changes: 1 addition & 1 deletion rpc/backend/call_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac
}
if args.Nonce == nil {
// get the nonce from the account retriever
// ignore error in case tge account doesn't exist yet
// ignore error in case the account doesn't exist yet
nonce, err := b.getAccountNonce(*args.From, true, 0, b.logger)
if err != nil {
nonce = 0
Expand Down
Loading
Loading