Skip to content

Commit

Permalink
ante: ignore no signature error for evm transactions (evmos#143)
Browse files Browse the repository at this point in the history
fixes evmos#118

don't sign unit test tx

since that's the same case as real tx

comment EthValidateBasicDecorator
  • Loading branch information
yihuang authored Jun 21, 2021
1 parent d892663 commit 91ad638
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 48 deletions.
2 changes: 1 addition & 1 deletion app/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ func NewAnteHandler(
anteHandler = sdk.ChainAnteDecorators(
authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
authante.NewMempoolFeeDecorator(),
authante.NewValidateBasicDecorator(),
authante.TxTimeoutHeightDecorator{},
authante.NewValidateMemoDecorator(ak),
NewEthValidateBasicDecorator(),
NewEthSigVerificationDecorator(evmKeeper),
NewEthAccountVerificationDecorator(ak, bankKeeper, evmKeeper),
NewEthNonceVerificationDecorator(ak),
Expand Down
38 changes: 30 additions & 8 deletions app/ante/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
signedContractTx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedContractTx.From = addr.Hex()

tx := suite.CreateTestTx(signedContractTx, privKey, 1)
tx := suite.CreateTestTx(signedContractTx, privKey, 1, true)
return tx
},
false, false, true,
Expand All @@ -44,7 +44,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
signedContractTx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedContractTx.From = addr.Hex()

tx := suite.CreateTestTx(signedContractTx, privKey, 1)
tx := suite.CreateTestTx(signedContractTx, privKey, 1, true)
return tx
},
true, false, true,
Expand All @@ -55,7 +55,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
signedContractTx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedContractTx.From = addr.Hex()

tx := suite.CreateTestTx(signedContractTx, privKey, 1)
tx := suite.CreateTestTx(signedContractTx, privKey, 1, true)
return tx
},
false, true, true,
Expand All @@ -66,7 +66,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()

tx := suite.CreateTestTx(signedTx, privKey, 1)
tx := suite.CreateTestTx(signedTx, privKey, 1, true)
return tx
},
false, false, true,
Expand All @@ -77,7 +77,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 2, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()

tx := suite.CreateTestTx(signedTx, privKey, 1)
tx := suite.CreateTestTx(signedTx, privKey, 1, true)
return tx
},
true, false, true,
Expand All @@ -88,17 +88,39 @@ func (suite AnteTestSuite) TestAnteHandler() {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 3, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()

tx := suite.CreateTestTx(signedTx, privKey, 1)
tx := suite.CreateTestTx(signedTx, privKey, 1, true)
return tx
}, false, true, true,
},
{
"success - CheckTx (cosmos tx not signed)",
func() sdk.Tx {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 4, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()

tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx
}, false, true, true,
},
{
"fail - CheckTx (cosmos tx is not valid)",
func() sdk.Tx {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 4, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()

txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
// bigger than MaxGasWanted
txBuilder.SetGasLimit(uint64(1 << 63))
return txBuilder.GetTx()
}, false, true, false,
},
{
"fail - CheckTx (memo too long)",
func() sdk.Tx {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 3, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 5, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()

txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1)
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, true)
txBuilder.SetMemo(strings.Repeat("*", 257))
return txBuilder.GetTx()
}, true, false, false,
Expand Down
24 changes: 24 additions & 0 deletions app/ante/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -549,3 +549,27 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
// set the original gas meter
return next(ctx, tx, simulate)
}

// EthValidateBasicDecorator is adapted from ValidateBasicDecorator from cosmos-sdk, it ignores ErrNoSignatures
type EthValidateBasicDecorator struct{}

// NewEthValidateBasicDecorator creates a new EthValidateBasicDecorator
func NewEthValidateBasicDecorator() EthValidateBasicDecorator {
return EthValidateBasicDecorator{}
}

// AnteHandle handles basic validation of tx
func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
// no need to validate basic on recheck tx, call next antehandler
if ctx.IsReCheckTx() {
return next(ctx, tx, simulate)
}

err := tx.ValidateBasic()
// ErrNoSignatures is fine with eth tx
if err != nil && err != sdkerrors.ErrNoSignatures {
return ctx, err
}

return next(ctx, tx, simulate)
}
79 changes: 40 additions & 39 deletions app/ante/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ type AnteTestSuite struct {
ctx sdk.Context
app *app.EthermintApp
clientCtx client.Context
txBuilder client.TxBuilder
anteHandler sdk.AnteHandler
ethSigner ethtypes.Signer
}
Expand All @@ -59,7 +58,6 @@ func (suite *AnteTestSuite) SetupTest() {
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)

suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()

suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper, encodingConfig.TxConfig.SignModeHandler())
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
Expand All @@ -71,20 +69,21 @@ func TestAnteTestSuite(t *testing.T) {

// CreateTestTx is a helper function to create a tx given multiple inputs.
func (suite *AnteTestSuite) CreateTestTx(
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64,
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
) authsigning.Tx {
return suite.CreateTestTxBuilder(msg, priv, accNum).GetTx()
return suite.CreateTestTxBuilder(msg, priv, accNum, signCosmosTx).GetTx()
}

// CreateTestTxBuilder is a helper function to create a tx builder given multiple inputs.
func (suite *AnteTestSuite) CreateTestTxBuilder(
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64,
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
) client.TxBuilder {

option, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{})
suite.Require().NoError(err)

builder, ok := suite.txBuilder.(authtx.ExtensionOptionsTxBuilder)
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
builder, ok := txBuilder.(authtx.ExtensionOptionsTxBuilder)
suite.Require().True(ok)

builder.SetExtensionOptions(option)
Expand All @@ -98,41 +97,43 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
builder.SetFeeAmount(fees)
builder.SetGasLimit(msg.GetGas())

// First round: we gather all the signer infos. We use the "set empty
// signature" hack to do that.
sigV2 := signing.SignatureV2{
PubKey: priv.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(),
Signature: nil,
},
Sequence: msg.Data.Nonce,
if signCosmosTx {
// First round: we gather all the signer infos. We use the "set empty
// signature" hack to do that.
sigV2 := signing.SignatureV2{
PubKey: priv.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(),
Signature: nil,
},
Sequence: msg.Data.Nonce,
}

sigsV2 := []signing.SignatureV2{sigV2}

err = txBuilder.SetSignatures(sigsV2...)
suite.Require().NoError(err)

// Second round: all signer infos are set, so each signer can sign.

signerData := authsigning.SignerData{
ChainID: suite.ctx.ChainID(),
AccountNumber: accNum,
Sequence: msg.Data.Nonce,
}
sigV2, err = tx.SignWithPrivKey(
suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData,
txBuilder, priv, suite.clientCtx.TxConfig, msg.Data.Nonce,
)
suite.Require().NoError(err)

sigsV2 = []signing.SignatureV2{sigV2}

err = txBuilder.SetSignatures(sigsV2...)
suite.Require().NoError(err)
}

sigsV2 := []signing.SignatureV2{sigV2}

err = suite.txBuilder.SetSignatures(sigsV2...)
suite.Require().NoError(err)

// Second round: all signer infos are set, so each signer can sign.

signerData := authsigning.SignerData{
ChainID: suite.ctx.ChainID(),
AccountNumber: accNum,
Sequence: msg.Data.Nonce,
}
sigV2, err = tx.SignWithPrivKey(
suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData,
suite.txBuilder, priv, suite.clientCtx.TxConfig, msg.Data.Nonce,
)
suite.Require().NoError(err)

sigsV2 = []signing.SignatureV2{sigV2}

err = suite.txBuilder.SetSignatures(sigsV2...)
suite.Require().NoError(err)

return suite.txBuilder
return txBuilder
}

func newTestAddrKey() (common.Address, cryptotypes.PrivKey) {
Expand Down
4 changes: 4 additions & 0 deletions ethereum/rpc/eth_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,10 @@ func (e *PublicEthAPI) doCall(
// Create new call message
msg := evmtypes.NewMsgEthereumTx(e.chainIDEpoch, seq, args.To, value, gas, gasPrice, data, accessList)
msg.From = args.From.String()
signer := ethtypes.LatestSignerForChainID(e.chainIDEpoch)
if err := msg.Sign(signer, e.clientCtx.Keyring); err != nil {
return nil, err
}

if err := msg.ValidateBasic(); err != nil {
return nil, err
Expand Down

0 comments on commit 91ad638

Please sign in to comment.