laconicd/x/evm/types/msg_test.go
Federico Kunze 8e7ebe80e9
evm: fix signature verification (#61)
* evm: fix sig verification

* fixes

* test fixes
2021-06-01 13:14:33 -04:00

177 lines
5.2 KiB
Go

package types
import (
"bytes"
"math/big"
"testing"
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/tests"
ethcmn "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)
type MsgsTestSuite struct {
suite.Suite
signer keyring.Signer
from ethcmn.Address
to ethcmn.Address
chainID *big.Int
}
func TestMsgsTestSuite(t *testing.T) {
suite.Run(t, new(MsgsTestSuite))
}
func (suite *MsgsTestSuite) SetupTest() {
privFrom, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
privTo, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
suite.signer = tests.NewSigner(privFrom)
suite.from = crypto.PubkeyToAddress(privFrom.ToECDSA().PublicKey)
suite.to = crypto.PubkeyToAddress(privTo.ToECDSA().PublicKey)
suite.chainID = big.NewInt(1)
}
func (suite *MsgsTestSuite) TestMsgEthereumTx_Constructor() {
msg := NewMsgEthereumTx(nil, 0, &suite.to, nil, 100000, nil, []byte("test"), nil)
suite.Require().Equal(msg.Data.To, suite.to.Hex())
suite.Require().Equal(msg.Route(), RouterKey)
suite.Require().Equal(msg.Type(), TypeMsgEthereumTx)
suite.Require().NotNil(msg.To())
suite.Require().Equal(msg.GetMsgs(), []sdk.Msg{msg})
suite.Require().Panics(func() { msg.GetSigners() })
suite.Require().Panics(func() { msg.GetSignBytes() })
msg = NewMsgEthereumTxContract(nil, 0, nil, 100000, nil, []byte("test"), nil)
suite.Require().NotNil(msg)
suite.Require().Empty(msg.Data.To)
suite.Require().Nil(msg.To())
}
func (suite *MsgsTestSuite) TestMsgEthereumTx_ValidateBasic() {
testCases := []struct {
msg string
to *ethcmn.Address
amount *big.Int
gasPrice *big.Int
expectPass bool
}{
{msg: "pass with recipient", to: &suite.to, amount: big.NewInt(100), gasPrice: big.NewInt(100000), expectPass: true},
{msg: "pass contract", to: nil, amount: big.NewInt(100), gasPrice: big.NewInt(100000), expectPass: true},
{msg: "invalid recipient", to: &ethcmn.Address{}, amount: big.NewInt(-1), gasPrice: big.NewInt(1000), expectPass: false},
// NOTE: these can't be effectively tested because the SetBytes function from big.Int only sets
// the absolute value
{msg: "negative amount", to: &suite.to, amount: big.NewInt(-1), gasPrice: big.NewInt(1000), expectPass: true},
{msg: "negative gas price", to: &suite.to, amount: big.NewInt(100), gasPrice: big.NewInt(-1), expectPass: true},
{msg: "zero gas price", to: &suite.to, amount: big.NewInt(100), gasPrice: big.NewInt(0), expectPass: true},
}
for i, tc := range testCases {
msg := NewMsgEthereumTx(suite.chainID, 0, tc.to, tc.amount, 0, tc.gasPrice, nil, nil)
err := msg.ValidateBasic()
if tc.expectPass {
suite.Require().NoError(err, "valid test %d failed: %s", i, tc.msg)
} else {
suite.Require().Error(err, "invalid test %d passed: %s", i, tc.msg)
}
}
}
func (suite *MsgsTestSuite) TestMsgEthereumTx_EncodeRLP() {
expMsg := NewMsgEthereumTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), nil)
raw, err := rlp.EncodeToBytes(&expMsg)
suite.Require().NoError(err)
msg := &MsgEthereumTx{}
err = rlp.Decode(bytes.NewReader(raw), &msg)
suite.Require().NoError(err)
suite.Require().Equal(expMsg.Data, msg.Data)
}
func (suite *MsgsTestSuite) TestMsgEthereumTx_RLPSignBytes() {
msg := NewMsgEthereumTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), nil)
suite.NotPanics(func() { _ = msg.RLPSignBytes(suite.chainID) })
}
func (suite *MsgsTestSuite) TestMsgEthereumTx_Sign() {
msg := NewMsgEthereumTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), nil)
testCases := []struct {
msg string
ethSigner ethtypes.Signer
malleate func()
expectPass bool
}{
{
"pass - EIP2930 signer",
ethtypes.NewEIP2930Signer(suite.chainID),
func() { msg.From = suite.from.Hex() },
true,
},
// TODO: support legacy txs
{
"not supported - EIP155 signer",
ethtypes.NewEIP155Signer(suite.chainID),
func() { msg.From = suite.from.Hex() },
false,
},
{
"not supported - Homestead signer",
ethtypes.HomesteadSigner{},
func() { msg.From = suite.from.Hex() },
false,
},
{
"not supported - Frontier signer",
ethtypes.FrontierSigner{},
func() { msg.From = suite.from.Hex() },
false,
},
{
"no from address ",
ethtypes.NewEIP2930Signer(suite.chainID),
func() { msg.From = "" },
false,
},
{
"from address ≠ signer address",
ethtypes.NewEIP2930Signer(suite.chainID),
func() { msg.From = suite.to.Hex() },
false,
},
}
for i, tc := range testCases {
tc.malleate()
err := msg.Sign(tc.ethSigner, suite.signer)
if tc.expectPass {
suite.Require().NoError(err, "valid test %d failed: %s", i, tc.msg)
tx := msg.AsTransaction()
signer := ethtypes.NewEIP2930Signer(suite.chainID)
sender, err := ethtypes.Sender(signer, tx)
suite.Require().NoError(err, tc.msg)
suite.Require().Equal(msg.From, sender.Hex(), tc.msg)
} else {
suite.Require().Error(err, "invalid test %d passed: %s", i, tc.msg)
}
}
}