package types import ( "crypto/ecdsa" "fmt" "math/big" "testing" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" ethcmn "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" "github.com/stretchr/testify/require" ) func TestTransactionRLPEncode(t *testing.T) { txs := NewTestEthTxs(TestChainID, []int64{0}, []ethcmn.Address{TestAddr1}, []*ecdsa.PrivateKey{TestPrivKey1}) gtxs := NewTestGethTxs(TestChainID, []int64{0}, []ethcmn.Address{TestAddr1}, []*ecdsa.PrivateKey{TestPrivKey1}) txRLP, err := rlp.EncodeToBytes(txs[0]) require.NoError(t, err) gtxRLP, err := rlp.EncodeToBytes(gtxs[0]) require.NoError(t, err) require.Equal(t, gtxRLP, txRLP) } func TestTransactionRLPDecode(t *testing.T) { txs := NewTestEthTxs(TestChainID, []int64{0}, []ethcmn.Address{TestAddr1}, []*ecdsa.PrivateKey{TestPrivKey1}) gtxs := NewTestGethTxs(TestChainID, []int64{0}, []ethcmn.Address{TestAddr1}, []*ecdsa.PrivateKey{TestPrivKey1}) txRLP, err := rlp.EncodeToBytes(txs[0]) require.NoError(t, err) gtxRLP, err := rlp.EncodeToBytes(gtxs[0]) require.NoError(t, err) var ( decodedTx Transaction decodedGtx ethtypes.Transaction ) err = rlp.DecodeBytes(txRLP, &decodedTx) require.NoError(t, err) err = rlp.DecodeBytes(gtxRLP, &decodedGtx) require.NoError(t, err) require.Equal(t, decodedGtx.Hash(), decodedTx.Hash()) } func TestValidation(t *testing.T) { ethTxs := NewTestEthTxs( TestChainID, []int64{0}, []ethcmn.Address{TestAddr1}, []*ecdsa.PrivateKey{TestPrivKey1}, ) testCases := []struct { msg sdk.Msg mutate func(sdk.Msg) sdk.Msg expectedErr bool }{ {ethTxs[0], func(msg sdk.Msg) sdk.Msg { return msg }, false}, {ethTxs[0], func(msg sdk.Msg) sdk.Msg { tx := msg.(*Transaction) tx.data.Price = big.NewInt(-1) return tx }, true}, {ethTxs[0], func(msg sdk.Msg) sdk.Msg { tx := msg.(*Transaction) tx.data.Amount = big.NewInt(-1) return tx }, true}, } for i, tc := range testCases { msg := tc.mutate(tc.msg) err := msg.ValidateBasic() if tc.expectedErr { require.NotEqual(t, sdk.CodeOK, err.Code(), fmt.Sprintf("expected error: test case #%d", i)) } else { require.NoError(t, err, fmt.Sprintf("unexpected error: test case #%d", i)) } } } func TestTransactionVerifySig(t *testing.T) { txs := NewTestEthTxs( TestChainID, []int64{0}, []ethcmn.Address{TestAddr1}, []*ecdsa.PrivateKey{TestPrivKey1}, ) addr, err := txs[0].VerifySig(TestChainID) require.NoError(t, err) require.Equal(t, TestAddr1, addr) addr, err = txs[0].VerifySig(big.NewInt(100)) require.Error(t, err) require.NotEqual(t, TestAddr1, addr) } func TestTxDecoder(t *testing.T) { testCodec := NewTestCodec() txDecoder := TxDecoder(testCodec, TestSDKAddr) msgs := []sdk.Msg{sdk.NewTestMsg()} // create a non-SDK Ethereum transaction txs := NewTestEthTxs( TestChainID, []int64{0}, []ethcmn.Address{TestAddr1}, []*ecdsa.PrivateKey{TestPrivKey1}, ) txBytes, err := rlp.EncodeToBytes(txs[0]) require.NoError(t, err) // require the transaction to properly decode into a Transaction decodedTx, err := txDecoder(txBytes) require.NoError(t, err) require.IsType(t, Transaction{}, decodedTx) require.Equal(t, txs[0].data, (decodedTx.(Transaction)).data) // create a SDK (auth.StdTx) transaction and encode stdTx := NewTestStdTx(TestChainID, msgs, []int64{0}, []int64{0}, []*ecdsa.PrivateKey{TestPrivKey1}, NewTestStdFee()) payload := testCodec.MustMarshalBinary(stdTx) tx := NewTransaction(0, TestSDKAddr, big.NewInt(10), 1000, big.NewInt(100), payload) txBytes, err = rlp.EncodeToBytes(tx) require.NoError(t, err) // require the transaction to properly decode into a Transaction decodedTx, err = txDecoder(txBytes) require.NoError(t, err) require.IsType(t, auth.StdTx{}, decodedTx) require.Equal(t, stdTx, decodedTx) // require the decoding to fail when no transaction bytes are given decodedTx, err = txDecoder([]byte{}) require.Error(t, err) require.Nil(t, decodedTx) }