diff --git a/CHANGELOG.md b/CHANGELOG.md index 05eb64e453..e11369de4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,8 +41,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### State Machine Breaking * (evm) [\#1174](https://github.com/evmos/ethermint/pull/1174) Don't allow eth txs with 0 in mempool. -* (ante) [#1176](https://github.com/evmos/ethermint/pull/1176) Fix invalid tx hashes; Remove `Size_` field and validate `Hash`/`From` fields in ante handler, - recompute eth tx hashes in JSON-RPC APIs to fix old blocks. ## [v0.17.2] - 2022-07-26 diff --git a/app/ante/ante_test.go b/app/ante/ante_test.go index 41b040e0ad..1b09095870 100644 --- a/app/ante/ante_test.go +++ b/app/ante/ante_test.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/cosmos/cosmos-sdk/types/tx/signing" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -17,22 +16,19 @@ import ( ) func (suite AnteTestSuite) TestAnteHandler() { - var acc authtypes.AccountI + suite.enableFeemarket = false + suite.SetupTest() // reset + addr, privKey := tests.NewAddrKey() to := tests.GenerateAddress() - setup := func() { - suite.enableFeemarket = false - suite.SetupTest() // reset + acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes()) + suite.Require().NoError(acc.SetSequence(1)) + suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - acc = suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes()) - suite.Require().NoError(acc.SetSequence(1)) - suite.app.AccountKeeper.SetAccount(suite.ctx, acc) + suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt(10000000000)) - suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt(10000000000)) - - suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, big.NewInt(100)) - } + suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, big.NewInt(100)) testCases := []struct { name string @@ -67,7 +63,7 @@ func (suite AnteTestSuite) TestAnteHandler() { func() sdk.Tx { signedContractTx := evmtypes.NewTxContract( suite.app.EvmKeeper.ChainID(), - 1, + 2, big.NewInt(10), 100000, big.NewInt(150), @@ -88,7 +84,7 @@ func (suite AnteTestSuite) TestAnteHandler() { func() sdk.Tx { signedContractTx := evmtypes.NewTxContract( suite.app.EvmKeeper.ChainID(), - 1, + 3, big.NewInt(10), 100000, big.NewInt(150), @@ -109,7 +105,7 @@ func (suite AnteTestSuite) TestAnteHandler() { func() sdk.Tx { signedTx := evmtypes.NewTx( suite.app.EvmKeeper.ChainID(), - 1, + 4, &to, big.NewInt(10), 100000, @@ -131,7 +127,7 @@ func (suite AnteTestSuite) TestAnteHandler() { func() sdk.Tx { signedTx := evmtypes.NewTx( suite.app.EvmKeeper.ChainID(), - 1, + 5, &to, big.NewInt(10), 100000, @@ -153,7 +149,7 @@ func (suite AnteTestSuite) TestAnteHandler() { func() sdk.Tx { signedTx := evmtypes.NewTx( suite.app.EvmKeeper.ChainID(), - 1, + 6, &to, big.NewInt(10), 100000, @@ -174,7 +170,7 @@ func (suite AnteTestSuite) TestAnteHandler() { func() sdk.Tx { signedTx := evmtypes.NewTx( suite.app.EvmKeeper.ChainID(), - 1, + 7, &to, big.NewInt(10), 100000, @@ -193,7 +189,7 @@ func (suite AnteTestSuite) TestAnteHandler() { { "fail - CheckTx (cosmos tx is not valid)", func() sdk.Tx { - signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil) + signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 8, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil) signedTx.From = addr.Hex() txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false) @@ -205,7 +201,7 @@ func (suite AnteTestSuite) TestAnteHandler() { { "fail - CheckTx (memo too long)", func() sdk.Tx { - signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil) + signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 5, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil) signedTx.From = addr.Hex() txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false) @@ -216,7 +212,7 @@ func (suite AnteTestSuite) TestAnteHandler() { { "fail - CheckTx (ExtensionOptionsEthereumTx not set)", func() sdk.Tx { - signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil) + signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 5, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil) signedTx.From = addr.Hex() txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false, true) @@ -394,33 +390,10 @@ func (suite AnteTestSuite) TestAnteHandler() { return txBuilder.GetTx() }, false, false, false, }, - { - "fails - invalid from", - func() sdk.Tx { - msg := evmtypes.NewTxContract( - suite.app.EvmKeeper.ChainID(), - 1, - big.NewInt(10), - 100000, - big.NewInt(150), - big.NewInt(200), - nil, - nil, - nil, - ) - msg.From = addr.Hex() - tx := suite.CreateTestTx(msg, privKey, 1, false) - msg = tx.GetMsgs()[0].(*evmtypes.MsgEthereumTx) - msg.From = addr.Hex() - return tx - }, true, false, false, - }, } for _, tc := range testCases { suite.Run(tc.name, func() { - setup() - suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx) // expConsumed := params.TxGasContractCreation + params.TxGas diff --git a/app/ante/eth.go b/app/ante/eth.go index d401774ea0..8fcabb587c 100644 --- a/app/ante/eth.go +++ b/app/ante/eth.go @@ -61,7 +61,8 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s if err != nil { return ctx, sdkerrors.Wrapf( sdkerrors.ErrorInvalidSigner, - "couldn't retrieve sender address from the ethereum transaction: %s", + "couldn't retrieve sender address ('%s') from the ethereum transaction: %s", + msgEthTx.From, err.Error(), ) } @@ -402,82 +403,74 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu // For eth type cosmos tx, some fields should be veified as zero values, // since we will only verify the signature against the hash of the MsgEthereumTx.Data - wrapperTx, ok := tx.(protoTxProvider) - if !ok { - return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid tx type %T, didn't implement interface protoTxProvider", tx) - } + if wrapperTx, ok := tx.(protoTxProvider); ok { + protoTx := wrapperTx.GetProtoTx() + body := protoTx.Body + if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 { + return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, + "for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty") + } - protoTx := wrapperTx.GetProtoTx() - body := protoTx.Body - if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 { - return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, - "for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty") - } + if len(body.ExtensionOptions) != 1 { + return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1") + } - if len(body.ExtensionOptions) != 1 { - return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1") - } + txFee := sdk.Coins{} + txGasLimit := uint64(0) - txFee := sdk.Coins{} - txGasLimit := uint64(0) + params := vbd.evmKeeper.GetParams(ctx) + chainID := vbd.evmKeeper.ChainID() + ethCfg := params.ChainConfig.EthereumConfig(chainID) + baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg) - params := vbd.evmKeeper.GetParams(ctx) - chainID := vbd.evmKeeper.ChainID() - ethCfg := params.ChainConfig.EthereumConfig(chainID) - baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg) + for _, msg := range protoTx.GetMsgs() { + msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) + if !ok { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) + } - for _, msg := range protoTx.GetMsgs() { - msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) - } + txGasLimit += msgEthTx.GetGas() - // Validate `From` field - if msgEthTx.From != "" { - return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid From %s, expect empty string", msgEthTx.From) - } + txData, err := evmtypes.UnpackTxData(msgEthTx.Data) + if err != nil { + return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data") + } + + // return error if contract creation or call are disabled through governance + if !params.EnableCreate && txData.GetTo() == nil { + return ctx, sdkerrors.Wrap(evmtypes.ErrCreateDisabled, "failed to create new contract") + } else if !params.EnableCall && txData.GetTo() != nil { + return ctx, sdkerrors.Wrap(evmtypes.ErrCallDisabled, "failed to call contract") + } - txGasLimit += msgEthTx.GetGas() + if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType { + return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported") + } - txData, err := evmtypes.UnpackTxData(msgEthTx.Data) - if err != nil { - return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data") + txFee = txFee.Add(sdk.NewCoin(params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee()))) } - // return error if contract creation or call are disabled through governance - if !params.EnableCreate && txData.GetTo() == nil { - return ctx, sdkerrors.Wrap(evmtypes.ErrCreateDisabled, "failed to create new contract") - } else if !params.EnableCall && txData.GetTo() != nil { - return ctx, sdkerrors.Wrap(evmtypes.ErrCallDisabled, "failed to call contract") + authInfo := protoTx.AuthInfo + if len(authInfo.SignerInfos) > 0 { + return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty") } - if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType { - return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported") + if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" { + return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty") } - txFee = txFee.Add(sdk.NewCoin(params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee()))) - } - - authInfo := protoTx.AuthInfo - if len(authInfo.SignerInfos) > 0 { - return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty") - } - - if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" { - return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty") - } - - if !authInfo.Fee.Amount.IsEqual(txFee) { - return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee) - } + if !authInfo.Fee.Amount.IsEqual(txFee) { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee) + } - if authInfo.Fee.GasLimit != txGasLimit { - return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit) - } + if authInfo.Fee.GasLimit != txGasLimit { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit) + } - sigs := protoTx.Signatures - if len(sigs) > 0 { - return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx Signatures should be empty") + sigs := protoTx.Signatures + if len(sigs) > 0 { + return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx Signatures should be empty") + } } return next(ctx, tx, simulate) diff --git a/app/ante/utils_test.go b/app/ante/utils_test.go index 99e0af56e0..321cc4ced3 100644 --- a/app/ante/utils_test.go +++ b/app/ante/utils_test.go @@ -190,7 +190,6 @@ func (suite *AnteTestSuite) CreateTestTxBuilder( err = msg.Sign(suite.ethSigner, tests.NewSigner(priv)) suite.Require().NoError(err) - msg.From = "" err = builder.SetMsgs(msg) suite.Require().NoError(err) diff --git a/docs/api/proto-docs.md b/docs/api/proto-docs.md index d2afcfbd62..16ae2231b5 100644 --- a/docs/api/proto-docs.md +++ b/docs/api/proto-docs.md @@ -476,7 +476,7 @@ MsgEthereumTx encapsulates an Ethereum transaction as an SDK message. | `data` | [google.protobuf.Any](#google.protobuf.Any) | | inner transaction data caches | -| `size` | [double](#double) | | DEPRECATED: encoded storage size of the transaction | +| `size` | [double](#double) | | encoded storage size of the transaction | | `hash` | [string](#string) | | transaction hash in hex format | | `from` | [string](#string) | | ethereum signer address in hex format. This address value is checked against the address derived from the signature (V, R, S) using the secp256k1 elliptic curve | diff --git a/proto/ethermint/evm/v1/tx.proto b/proto/ethermint/evm/v1/tx.proto index 0898f8e0ac..9dc53f2fa0 100644 --- a/proto/ethermint/evm/v1/tx.proto +++ b/proto/ethermint/evm/v1/tx.proto @@ -25,7 +25,7 @@ message MsgEthereumTx { google.protobuf.Any data = 1; // caches - // DEPRECATED: encoded storage size of the transaction + // encoded storage size of the transaction double size = 2 [ (gogoproto.jsontag) = "-" ]; // transaction hash in hex format string hash = 3 [ (gogoproto.moretags) = "rlp:\"-\"" ]; diff --git a/rpc/backend/evm_backend.go b/rpc/backend/evm_backend.go index e8b87801a0..21494cb33a 100644 --- a/rpc/backend/evm_backend.go +++ b/rpc/backend/evm_backend.go @@ -1009,7 +1009,6 @@ func (b *Backend) GetEthereumMsgsFromTendermintBlock(resBlock *tmrpctypes.Result continue } - ethMsg.Hash = ethMsg.AsTransaction().Hash().Hex() result = append(result, ethMsg) } } diff --git a/rpc/namespaces/ethereum/eth/filters/api.go b/rpc/namespaces/ethereum/eth/filters/api.go index 9bc5a4700e..10409fd837 100644 --- a/rpc/namespaces/ethereum/eth/filters/api.go +++ b/rpc/namespaces/ethereum/eth/filters/api.go @@ -157,7 +157,7 @@ func (api *PublicFilterAPI) NewPendingTransactionFilter() rpc.ID { for _, msg := range tx.GetMsgs() { ethTx, ok := msg.(*evmtypes.MsgEthereumTx) if ok { - f.hashes = append(f.hashes, ethTx.AsTransaction().Hash()) + f.hashes = append(f.hashes, common.HexToHash(ethTx.Hash)) } } } @@ -221,7 +221,7 @@ func (api *PublicFilterAPI) NewPendingTransactions(ctx context.Context) (*rpc.Su for _, msg := range tx.GetMsgs() { ethTx, ok := msg.(*evmtypes.MsgEthereumTx) if ok { - _ = notifier.Notify(rpcSub.ID, ethTx.AsTransaction().Hash()) + _ = notifier.Notify(rpcSub.ID, common.HexToHash(ethTx.Hash)) } } case <-rpcSub.Err(): diff --git a/rpc/types/events.go b/rpc/types/events.go index 6b74d3784a..db50301eac 100644 --- a/rpc/types/events.go +++ b/rpc/types/events.go @@ -155,21 +155,8 @@ func (p *ParsedTxs) newTx(attrs []abci.EventAttribute) error { } // updateTx updates an exiting tx from events, called during parsing. -// In event format 2, we update the tx with the attributes of the second `ethereum_tx` event, -// Due to bug https://github.com/evmos/ethermint/issues/1175, the first `ethereum_tx` event may emit incorrect tx hash, -// so we prefer the second event and override the first one. func (p *ParsedTxs) updateTx(eventIndex int, attrs []abci.EventAttribute) error { - tx := NewParsedTx(eventIndex) - if err := fillTxAttributes(&tx, attrs); err != nil { - return err - } - if tx.Hash != p.Txs[eventIndex].Hash { - // if hash is different, index the new one too - p.TxHashes[tx.Hash] = eventIndex - } - // override the tx because the second event is more trustworthy - p.Txs[eventIndex] = tx - return nil + return fillTxAttributes(&p.Txs[eventIndex], attrs) } // GetTxByHash find ParsedTx by tx hash, returns nil if not exists. diff --git a/rpc/types/events_test.go b/rpc/types/events_test.go index 68e097d38c..c946a97f30 100644 --- a/rpc/types/events_test.go +++ b/rpc/types/events_test.go @@ -107,8 +107,6 @@ func TestParseTxResult(t *testing.T) { }}, {Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{ {Key: []byte("amount"), Value: []byte("1000")}, - {Key: []byte("ethereumTxHash"), Value: []byte(txHash.Hex())}, - {Key: []byte("txIndex"), Value: []byte("0")}, {Key: []byte("txGasUsed"), Value: []byte("21000")}, {Key: []byte("txHash"), Value: []byte("14A84ED06282645EFBF080E0B7ED80D8D8D6A36337668A12B5F229F81CDD3F57")}, {Key: []byte("recipient"), Value: []byte("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7")}, diff --git a/rpc/types/utils.go b/rpc/types/utils.go index f8a0c7e11c..15da24489a 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -34,7 +34,6 @@ func RawTxToEthTx(clientCtx client.Context, txBz tmtypes.Tx) ([]*evmtypes.MsgEth if !ok { return nil, fmt.Errorf("invalid message type %T, expected %T", msg, &evmtypes.MsgEthereumTx{}) } - ethTx.Hash = ethTx.AsTransaction().Hash().Hex() ethTxs[i] = ethTx } return ethTxs, nil diff --git a/tests/e2e/integration_test.go b/tests/e2e/integration_test.go index 3b36acc95a..6ae14a5f0e 100644 --- a/tests/e2e/integration_test.go +++ b/tests/e2e/integration_test.go @@ -794,8 +794,6 @@ func (s *IntegrationTestSuite) TestBatchETHTransactions() { err = msgTx.Sign(s.ethSigner, s.network.Validators[0].ClientCtx.Keyring) s.Require().NoError(err) - // A valid msg should have empty `From` - msgTx.From = "" msgs = append(msgs, msgTx.GetMsgs()...) txData, err := evmtypes.UnpackTxData(msgTx.Data) s.Require().NoError(err) diff --git a/x/evm/spec/04_transactions.md b/x/evm/spec/04_transactions.md index 4a132cf36b..d3609dda23 100644 --- a/x/evm/spec/04_transactions.md +++ b/x/evm/spec/04_transactions.md @@ -14,7 +14,7 @@ An EVM state transition can be achieved by using the `MsgEthereumTx`. This messa type MsgEthereumTx struct { // inner transaction data Data *types.Any `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` - // DEPRECATED: encoded storage size of the transaction + // encoded storage size of the transaction Size_ float64 `protobuf:"fixed64,2,opt,name=size,proto3" json:"-"` // transaction hash in hex format Hash string `protobuf:"bytes,3,opt,name=hash,proto3" json:"hash,omitempty" rlp:"-"` diff --git a/x/evm/types/msg.go b/x/evm/types/msg.go index 111346600a..8bd40f5f4c 100644 --- a/x/evm/types/msg.go +++ b/x/evm/types/msg.go @@ -130,12 +130,10 @@ func newMsgEthereumTx( panic(err) } - msg := MsgEthereumTx{Data: dataAny} - msg.Hash = msg.AsTransaction().Hash().Hex() - return &msg + return &MsgEthereumTx{Data: dataAny} } -// FromEthereumTx populates the message fields from the given ethereum transaction +// fromEthereumTx populates the message fields from the given ethereum transaction func (msg *MsgEthereumTx) FromEthereumTx(tx *ethtypes.Transaction) error { txData, err := NewTxDataFromTx(tx) if err != nil { @@ -148,6 +146,7 @@ func (msg *MsgEthereumTx) FromEthereumTx(tx *ethtypes.Transaction) error { } msg.Data = anyTxData + msg.Size_ = float64(tx.Size()) msg.Hash = tx.Hash().Hex() return nil } @@ -167,32 +166,12 @@ func (msg MsgEthereumTx) ValidateBasic() error { } } - // Validate Size_ field, should be kept empty - if msg.Size_ != 0 { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "tx size is deprecated") - } - txData, err := UnpackTxData(msg.Data) if err != nil { return sdkerrors.Wrap(err, "failed to unpack tx data") } - // prevent txs with 0 gas to fill up the mempool - if txData.GetGas() == 0 { - return sdkerrors.Wrap(ErrInvalidGasLimit, "gas limit must not be zero") - } - - if err := txData.Validate(); err != nil { - return err - } - - // Validate Hash field after validated txData to avoid panic - txHash := msg.AsTransaction().Hash().Hex() - if msg.Hash != txHash { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid tx hash %s, expected: %s", msg.Hash, txHash) - } - - return nil + return txData.Validate() } // GetMsgs returns a single MsgEthereumTx as an sdk.Msg. @@ -358,10 +337,6 @@ func (msg *MsgEthereumTx) BuildTx(b client.TxBuilder, evmDenom string) (signing. } builder.SetExtensionOptions(option) - - // A valid msg should have empty `From` - msg.From = "" - err = builder.SetMsgs(msg) if err != nil { return nil, err diff --git a/x/evm/types/msg_test.go b/x/evm/types/msg_test.go index 0a31bb1b90..7fe6f3c91f 100644 --- a/x/evm/types/msg_test.go +++ b/x/evm/types/msg_test.go @@ -372,85 +372,24 @@ func (suite *MsgsTestSuite) TestMsgEthereumTx_ValidateBasic() { }, } - for _, tc := range testCases { - suite.Run(tc.msg, func() { - to := common.HexToAddress(tc.from) - - tx := types.NewTx(tc.chainID, 1, &to, tc.amount, tc.gasLimit, tc.gasPrice, tc.gasFeeCap, tc.gasTipCap, nil, tc.accessList) - tx.From = tc.from - - // apply nil assignment here to test ValidateBasic function instead of NewTx - if strings.Contains(tc.msg, "nil tx.Data") { - tx.Data = nil - } + for i, tc := range testCases { + to := common.HexToAddress(tc.from) - err := tx.ValidateBasic() + tx := types.NewTx(tc.chainID, 1, &to, tc.amount, 1000, tc.gasPrice, tc.gasFeeCap, tc.gasTipCap, nil, tc.accessList) + tx.From = tc.from - if tc.expectPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} + // apply nil assignment here to test ValidateBasic function instead of NewTx + if strings.Contains(tc.msg, "nil tx.Data") { + tx.Data = nil + } -func (suite *MsgsTestSuite) TestMsgEthereumTx_ValidateBasicAdvanced() { - hundredInt := big.NewInt(100) - testCases := []struct { - msg string - msgBuilder func() *types.MsgEthereumTx - expectPass bool - }{ - { - "fails - invalid tx hash", - func() *types.MsgEthereumTx { - msg := types.NewTxContract( - hundredInt, - 1, - big.NewInt(10), - 100000, - big.NewInt(150), - big.NewInt(200), - nil, - nil, - nil, - ) - msg.Hash = "0x00" - return msg - }, - false, - }, - { - "fails - invalid size", - func() *types.MsgEthereumTx { - msg := types.NewTxContract( - hundredInt, - 1, - big.NewInt(10), - 100000, - big.NewInt(150), - big.NewInt(200), - nil, - nil, - nil, - ) - msg.Size_ = 1 - return msg - }, - false, - }, - } + err := tx.ValidateBasic() - for _, tc := range testCases { - suite.Run(tc.msg, func() { - err := tc.msgBuilder().ValidateBasic() - if tc.expectPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) + if tc.expectPass { + suite.Require().NoError(err, "valid test %d failed: %s, %v", i, tc.msg) + } else { + suite.Require().Error(err, "invalid test %d passed: %s, %v", i, tc.msg) + } } } diff --git a/x/evm/types/tx.pb.go b/x/evm/types/tx.pb.go index 883fa0013b..a2e5fffad2 100644 --- a/x/evm/types/tx.pb.go +++ b/x/evm/types/tx.pb.go @@ -37,7 +37,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type MsgEthereumTx struct { // inner transaction data Data *types.Any `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` - // DEPRECATED: encoded storage size of the transaction + // encoded storage size of the transaction Size_ float64 `protobuf:"fixed64,2,opt,name=size,proto3" json:"-"` // transaction hash in hex format Hash string `protobuf:"bytes,3,opt,name=hash,proto3" json:"hash,omitempty" rlp:"-"` diff --git a/x/evm/types/tx_args.go b/x/evm/types/tx_args.go index 5fcc89e8a0..525a008f0b 100644 --- a/x/evm/types/tx_args.go +++ b/x/evm/types/tx_args.go @@ -143,12 +143,10 @@ func (args *TransactionArgs) ToTransaction() *MsgEthereumTx { from = args.From.Hex() } - msg := MsgEthereumTx{ + return &MsgEthereumTx{ Data: any, From: from, } - msg.Hash = msg.AsTransaction().Hash().Hex() - return &msg } // ToMessage converts the arguments to the Message type used by the core evm. diff --git a/x/evm/types/utils.go b/x/evm/types/utils.go index 5f5e02b0ed..c30d2e6550 100644 --- a/x/evm/types/utils.go +++ b/x/evm/types/utils.go @@ -62,9 +62,7 @@ func UnwrapEthereumMsg(tx *sdk.Tx, ethHash common.Hash) (*MsgEthereumTx, error) if !ok { return nil, fmt.Errorf("invalid tx type: %T", tx) } - txHash := ethMsg.AsTransaction().Hash() - ethMsg.Hash = txHash.Hex() - if txHash == ethHash { + if ethMsg.AsTransaction().Hash() == ethHash { return ethMsg, nil } } diff --git a/x/feemarket/keeper/integration_test.go b/x/feemarket/keeper/integration_test.go index e5fe03c930..7eb7a5f29f 100644 --- a/x/feemarket/keeper/integration_test.go +++ b/x/feemarket/keeper/integration_test.go @@ -567,7 +567,6 @@ func prepareEthTx(priv *ethsecp256k1.PrivKey, msgEthereumTx *evmtypes.MsgEthereu err = msgEthereumTx.Sign(s.ethSigner, tests.NewSigner(priv)) s.Require().NoError(err) - msgEthereumTx.From = "" err = txBuilder.SetMsgs(msgEthereumTx) s.Require().NoError(err)