From 57a70888d006556b77cac4157663075aaf408249 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 30 Jun 2020 15:12:20 -0400 Subject: [PATCH 1/5] Remove GetSignatures from SigVerifiableTx --- client/tx/tx_test.go | 4 +++- x/auth/ante/basic.go | 30 ++++++++++++++++++++++++++++-- x/auth/ante/sigverify.go | 1 - 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/client/tx/tx_test.go b/client/tx/tx_test.go index daa0dea739a6..d7d1eef6ff2c 100644 --- a/client/tx/tx_test.go +++ b/client/tx/tx_test.go @@ -111,7 +111,9 @@ func TestBuildUnsignedTx(t *testing.T) { tx, err := tx.BuildUnsignedTx(txf, msg) require.NoError(t, err) require.NotNil(t, tx) - require.Empty(t, tx.GetTx().(ante.SigVerifiableTx).GetSignatures()) + sigs, err := tx.GetTx().(ante.SigVerifiableTx).GetSignaturesV2() + require.NoError(t, err) + require.Empty(t, sigs) } func TestSign(t *testing.T) { diff --git a/x/auth/ante/basic.go b/x/auth/ante/basic.go index f7120e627f24..4765646f6f48 100644 --- a/x/auth/ante/basic.go +++ b/x/auth/ante/basic.go @@ -1,6 +1,7 @@ package ante import ( + "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/tendermint/tendermint/crypto" "github.com/cosmos/cosmos-sdk/codec/legacy" @@ -100,10 +101,15 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim // simulate gas cost for signatures in simulate mode if simulate { // in simulate mode, each element should be a nil signature - sigs := sigTx.GetSignatures() + sigs, err := sigTx.GetSignaturesV2() + if err != nil { + return ctx, err + } + n := len(sigs) + for i, signer := range sigTx.GetSigners() { // if signature is already filled in, no need to simulate gas cost - if sigs[i] != nil { + if i < n && !isIncompleteSignature(sigs[i].Data) { continue } @@ -139,3 +145,23 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim return next(ctx, tx, simulate) } + +// isIncompleteSignature tests whether SignatureData is fully filled in for simulation purposes +func isIncompleteSignature(data signing.SignatureData) bool { + if data == nil { + return true + } + + switch data := data.(type) { + case *signing.SingleSignatureData: + return len(data.Signature) == 0 + case *signing.MultiSignatureData: + for _, s := range data.Signatures { + if isIncompleteSignature(s) { + return true + } + } + } + + return false +} diff --git a/x/auth/ante/sigverify.go b/x/auth/ante/sigverify.go index b7d7d46dea31..0f588dcd7c42 100644 --- a/x/auth/ante/sigverify.go +++ b/x/auth/ante/sigverify.go @@ -43,7 +43,6 @@ type SigVerifiableTx interface { sdk.Tx GetSigners() []sdk.AccAddress GetPubKeys() []crypto.PubKey // If signer already has pubkey in context, this list will have nil in its place - GetSignatures() [][]byte GetSignaturesV2() ([]signing.SignatureV2, error) } From 37b18041bce3350299d579006416801bbc61ca54 Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Thu, 30 Jul 2020 23:21:57 +0530 Subject: [PATCH 2/5] Fix conflicts --- x/auth/ante/basic.go | 7 +++---- x/auth/ante/sigverify.go | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/x/auth/ante/basic.go b/x/auth/ante/basic.go index 3debdc212a48..588b44355c38 100644 --- a/x/auth/ante/basic.go +++ b/x/auth/ante/basic.go @@ -1,15 +1,14 @@ package ante import ( - "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/tendermint/tendermint/crypto" - "github.com/cosmos/cosmos-sdk/x/auth/signing" - "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/auth/types" ) @@ -92,7 +91,7 @@ func NewConsumeGasForTxSizeDecorator(ak AccountKeeper) ConsumeTxSizeGasDecorator } func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { - sigTx, ok := tx.(signing.SigVerifiableTx) + sigTx, ok := tx.(authsigning.SigVerifiableTx) if !ok { return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type") } diff --git a/x/auth/ante/sigverify.go b/x/auth/ante/sigverify.go index bc3da6cee052..bf909c429fcf 100644 --- a/x/auth/ante/sigverify.go +++ b/x/auth/ante/sigverify.go @@ -5,6 +5,8 @@ import ( "encoding/hex" "fmt" + "github.com/tendermint/tendermint/crypto" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/types/tx/signing" From af6bca26b1d96f94d13315b5664f42f27ba76a81 Mon Sep 17 00:00:00 2001 From: Cory Levinson Date: Mon, 31 Aug 2020 17:31:36 -0400 Subject: [PATCH 3/5] update client tests --- client/testutil/suite.go | 10 ++++++---- client/tx/tx_test.go | 5 ++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/client/testutil/suite.go b/client/testutil/suite.go index 4bc02572385e..36eb377907ad 100644 --- a/client/testutil/suite.go +++ b/client/testutil/suite.go @@ -119,7 +119,6 @@ func (s *TxConfigTestSuite) TestTxBuilderSetSignatures() { err = txBuilder.SetSignatures(sig1, msig) s.Require().NoError(err) sigTx = txBuilder.GetTx() - s.Require().Len(sigTx.GetSignatures(), 2) sigsV2, err := sigTx.GetSignaturesV2() s.Require().NoError(err) s.Require().Len(sigsV2, 2) @@ -163,7 +162,6 @@ func (s *TxConfigTestSuite) TestTxBuilderSetSignatures() { err = txBuilder.SetSignatures(sig1, msig) s.Require().NoError(err) sigTx = txBuilder.GetTx() - s.Require().Len(sigTx.GetSignatures(), 2) sigsV2, err = sigTx.GetSignaturesV2() s.Require().NoError(err) s.Require().Len(sigsV2, 2) @@ -267,7 +265,9 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() { s.Require().Equal(feeAmount, tx3.GetFee()) s.Require().Equal(gasLimit, tx3.GetGas()) s.Require().Equal(memo, tx3.GetMemo()) - s.Require().Equal([][]byte{dummySig}, tx3.GetSignatures()) + tx3Sigs, err := tx3.GetSignaturesV2() + s.Require().NoError(err) + s.Require().Equal([][]byte{dummySig}, tx3Sigs) s.Require().Equal([]crypto.PubKey{pubkey}, tx3.GetPubKeys()) s.T().Log("JSON encode transaction") @@ -284,7 +284,9 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() { s.Require().Equal(feeAmount, tx3.GetFee()) s.Require().Equal(gasLimit, tx3.GetGas()) s.Require().Equal(memo, tx3.GetMemo()) - s.Require().Equal([][]byte{dummySig}, tx3.GetSignatures()) + tx3Sigs, err = tx3.GetSignaturesV2() + s.Require().NoError(err) + s.Require().Equal([][]byte{dummySig}, tx3Sigs) s.Require().Equal([]crypto.PubKey{pubkey}, tx3.GetPubKeys()) } diff --git a/client/tx/tx_test.go b/client/tx/tx_test.go index fb3f36c578a4..5b027ca93142 100644 --- a/client/tx/tx_test.go +++ b/client/tx/tx_test.go @@ -111,7 +111,10 @@ func TestBuildUnsignedTx(t *testing.T) { tx, err := tx.BuildUnsignedTx(txf, msg) require.NoError(t, err) require.NotNil(t, tx) - require.Empty(t, tx.GetTx().(signing.SigVerifiableTx).GetSignatures()) + + sigs, err := tx.GetTx().(signing.SigVerifiableTx).GetSignaturesV2() + require.NoError(t, err) + require.Empty(t, sigs) } func TestSign(t *testing.T) { From 8a3d18e5d186f13d5e7de7a395e25d13ff834ab3 Mon Sep 17 00:00:00 2001 From: Cory Levinson Date: Tue, 1 Sep 2020 15:48:19 -0400 Subject: [PATCH 4/5] fix x/auth tests --- client/testutil/suite.go | 4 ++-- x/auth/ante/basic.go | 1 + x/auth/ante/basic_test.go | 2 +- x/auth/client/cli/cli_test.go | 12 +++++++++--- x/auth/tx/builder.go | 26 +++++++++++++++++--------- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/client/testutil/suite.go b/client/testutil/suite.go index 36eb377907ad..3f6e138e5af8 100644 --- a/client/testutil/suite.go +++ b/client/testutil/suite.go @@ -267,7 +267,7 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() { s.Require().Equal(memo, tx3.GetMemo()) tx3Sigs, err := tx3.GetSignaturesV2() s.Require().NoError(err) - s.Require().Equal([][]byte{dummySig}, tx3Sigs) + s.Require().Equal([]signingtypes.SignatureV2{sig}, tx3Sigs) s.Require().Equal([]crypto.PubKey{pubkey}, tx3.GetPubKeys()) s.T().Log("JSON encode transaction") @@ -286,7 +286,7 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() { s.Require().Equal(memo, tx3.GetMemo()) tx3Sigs, err = tx3.GetSignaturesV2() s.Require().NoError(err) - s.Require().Equal([][]byte{dummySig}, tx3Sigs) + s.Require().Equal([]signingtypes.SignatureV2{sig}, tx3Sigs) s.Require().Equal([]crypto.PubKey{pubkey}, tx3.GetPubKeys()) } diff --git a/x/auth/ante/basic.go b/x/auth/ante/basic.go index 4382ceda3bef..6ead49e1ead9 100644 --- a/x/auth/ante/basic.go +++ b/x/auth/ante/basic.go @@ -102,6 +102,7 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim // simulate gas cost for signatures in simulate mode if simulate { // in simulate mode, each element should be a nil signature + // TODO: Needs to be able to handle SignaturesV2 which may return nil, Currently this cannot return nil signatures sigs, err := sigTx.GetSignaturesV2() if err != nil { return ctx, err diff --git a/x/auth/ante/basic_test.go b/x/auth/ante/basic_test.go index 0247e3c2bc34..8a9d1848e5a8 100644 --- a/x/auth/ante/basic_test.go +++ b/x/auth/ante/basic_test.go @@ -149,7 +149,7 @@ func (suite *AnteTestSuite) TestConsumeGasForTxSize() { suite.Require().True(len(simTxBytes) < len(txBytes), "simulated tx still has signatures") // Set suite.ctx with smaller simulated TxBytes manually - suite.ctx = suite.ctx.WithTxBytes(txBytes) + suite.ctx = suite.ctx.WithTxBytes(simTxBytes) beforeSimGas := suite.ctx.GasMeter().GasConsumed() diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index 9e102abda040..8440aea5b002 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -193,7 +193,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() { s.Require().NoError(err) s.Require().Equal(txBuilder.GetTx().GetGas(), uint64(flags.DefaultGasLimit)) s.Require().Equal(len(txBuilder.GetTx().GetMsgs()), 1) - s.Require().Equal(0, len(txBuilder.GetTx().GetSignatures())) + sigs, err := txBuilder.GetTx().GetSignaturesV2() + s.Require().NoError(err) + s.Require().Equal(0, len(sigs)) // Test generate sendTx with --gas=$amount limitedGasGeneratedTx, err := bankcli.MsgSendExec( @@ -215,7 +217,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() { s.Require().NoError(err) s.Require().Equal(txBuilder.GetTx().GetGas(), uint64(100)) s.Require().Equal(len(txBuilder.GetTx().GetMsgs()), 1) - s.Require().Equal(0, len(txBuilder.GetTx().GetSignatures())) + sigs, err = txBuilder.GetTx().GetSignaturesV2() + s.Require().NoError(err) + s.Require().Equal(0, len(sigs)) resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address) s.Require().NoError(err) @@ -274,7 +278,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() { txBuilder, err = val1.ClientCtx.TxConfig.WrapTxBuilder(signedFinalTx) s.Require().NoError(err) s.Require().Equal(len(txBuilder.GetTx().GetMsgs()), 1) - s.Require().Equal(1, len(txBuilder.GetTx().GetSignatures())) + sigs, err = txBuilder.GetTx().GetSignaturesV2() + s.Require().NoError(err) + s.Require().Equal(1, len(sigs)) s.Require().Equal(val1.Address.String(), txBuilder.GetTx().GetSigners()[0].String()) // Write the output to disk diff --git a/x/auth/tx/builder.go b/x/auth/tx/builder.go index 4bf3c74f1384..cfb4bc925179 100644 --- a/x/auth/tx/builder.go +++ b/x/auth/tx/builder.go @@ -237,15 +237,23 @@ func (w *wrapper) GetSignaturesV2() ([]signing.SignatureV2, error) { res := make([]signing.SignatureV2, n) for i, si := range signerInfos { - var err error - sigData, err := ModeInfoAndSigToSignatureData(si.ModeInfo, sigs[i]) - if err != nil { - return nil, err - } - res[i] = signing.SignatureV2{ - PubKey: pubKeys[i], - Data: sigData, - Sequence: si.GetSequence(), + // handle nil signatures (in case of simulation) + if si.ModeInfo == nil { + res[i] = signing.SignatureV2{ + PubKey: pubKeys[i], + } + } else { + var err error + sigData, err := ModeInfoAndSigToSignatureData(si.ModeInfo, sigs[i]) + if err != nil { + return nil, err + } + res[i] = signing.SignatureV2{ + PubKey: pubKeys[i], + Data: sigData, + Sequence: si.GetSequence(), + } + } } From bb5bdbb5dcb02415d49a521a11bf03ad1ed9cb49 Mon Sep 17 00:00:00 2001 From: Cory Levinson Date: Tue, 1 Sep 2020 17:16:14 -0400 Subject: [PATCH 5/5] add MultiSignatureData test case for ConsumeTxSizeGasDecorator test --- x/auth/ante/basic.go | 4 +- x/auth/ante/basic_test.go | 108 +++++++++++++++++++++----------------- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/x/auth/ante/basic.go b/x/auth/ante/basic.go index 6ead49e1ead9..df874a63b1f4 100644 --- a/x/auth/ante/basic.go +++ b/x/auth/ante/basic.go @@ -102,7 +102,6 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim // simulate gas cost for signatures in simulate mode if simulate { // in simulate mode, each element should be a nil signature - // TODO: Needs to be able to handle SignaturesV2 which may return nil, Currently this cannot return nil signatures sigs, err := sigTx.GetSignaturesV2() if err != nil { return ctx, err @@ -158,6 +157,9 @@ func isIncompleteSignature(data signing.SignatureData) bool { case *signing.SingleSignatureData: return len(data.Signature) == 0 case *signing.MultiSignatureData: + if len(data.Signatures) == 0 { + return true + } for _, s := range data.Signatures { if isIncompleteSignature(s) { return true diff --git a/x/auth/ante/basic_test.go b/x/auth/ante/basic_test.go index 8a9d1848e5a8..8b304d180e51 100644 --- a/x/auth/ante/basic_test.go +++ b/x/auth/ante/basic_test.go @@ -8,6 +8,7 @@ import ( "github.com/tendermint/tendermint/crypto" + "github.com/cosmos/cosmos-sdk/crypto/types/multisig" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/ante" ) @@ -91,7 +92,6 @@ func (suite *AnteTestSuite) TestValidateMemo() { func (suite *AnteTestSuite) TestConsumeGasForTxSize() { suite.SetupTest(true) // setup - suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // keys and addresses priv1, _, addr1 := testdata.KeyTestPubAddr() @@ -100,66 +100,80 @@ func (suite *AnteTestSuite) TestConsumeGasForTxSize() { msg := testdata.NewTestMsg(addr1) feeAmount := testdata.NewTestFeeAmount() gasLimit := testdata.NewTestGasLimit() - suite.Require().NoError(suite.txBuilder.SetMsgs(msg)) - suite.txBuilder.SetFeeAmount(feeAmount) - suite.txBuilder.SetGasLimit(gasLimit) - suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10)) - - privs, accNums, accSeqs := []crypto.PrivKey{priv1}, []uint64{0}, []uint64{0} - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) - suite.Require().NoError(err) - - txBytes, err := suite.clientCtx.TxConfig.TxJSONEncoder()(tx) - suite.Require().Nil(err, "Cannot marshal tx: %v", err) cgtsd := ante.NewConsumeGasForTxSizeDecorator(suite.app.AccountKeeper) antehandler := sdk.ChainAnteDecorators(cgtsd) - params := suite.app.AccountKeeper.GetParams(suite.ctx) - expectedGas := sdk.Gas(len(txBytes)) * params.TxSizeCostPerByte + testCases := []struct { + name string + sigV2 signing.SignatureV2 + }{ + {"SingleSignatureData", signing.SignatureV2{PubKey: priv1.PubKey()}}, + {"MultiSignatureData", signing.SignatureV2{PubKey: priv1.PubKey(), Data: multisig.NewMultisig(2)}}, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() + suite.Require().NoError(suite.txBuilder.SetMsgs(msg)) + suite.txBuilder.SetFeeAmount(feeAmount) + suite.txBuilder.SetGasLimit(gasLimit) + suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10)) + + privs, accNums, accSeqs := []crypto.PrivKey{priv1}, []uint64{0}, []uint64{0} + tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + suite.Require().NoError(err) + + txBytes, err := suite.clientCtx.TxConfig.TxJSONEncoder()(tx) + suite.Require().Nil(err, "Cannot marshal tx: %v", err) - // Set suite.ctx with TxBytes manually - suite.ctx = suite.ctx.WithTxBytes(txBytes) + params := suite.app.AccountKeeper.GetParams(suite.ctx) + expectedGas := sdk.Gas(len(txBytes)) * params.TxSizeCostPerByte - // track how much gas is necessary to retrieve parameters - beforeGas := suite.ctx.GasMeter().GasConsumed() - suite.app.AccountKeeper.GetParams(suite.ctx) - afterGas := suite.ctx.GasMeter().GasConsumed() - expectedGas += afterGas - beforeGas + // Set suite.ctx with TxBytes manually + suite.ctx = suite.ctx.WithTxBytes(txBytes) - beforeGas = suite.ctx.GasMeter().GasConsumed() - suite.ctx, err = antehandler(suite.ctx, tx, false) - suite.Require().Nil(err, "ConsumeTxSizeGasDecorator returned error: %v", err) + // track how much gas is necessary to retrieve parameters + beforeGas := suite.ctx.GasMeter().GasConsumed() + suite.app.AccountKeeper.GetParams(suite.ctx) + afterGas := suite.ctx.GasMeter().GasConsumed() + expectedGas += afterGas - beforeGas - // require that decorator consumes expected amount of gas - consumedGas := suite.ctx.GasMeter().GasConsumed() - beforeGas - suite.Require().Equal(expectedGas, consumedGas, "Decorator did not consume the correct amount of gas") + beforeGas = suite.ctx.GasMeter().GasConsumed() + suite.ctx, err = antehandler(suite.ctx, tx, false) + suite.Require().Nil(err, "ConsumeTxSizeGasDecorator returned error: %v", err) - // simulation must not underestimate gas of this decorator even with nil signatures - txBuilder, err := suite.clientCtx.TxConfig.WrapTxBuilder(tx) - suite.Require().NoError(err) - suite.Require().NoError(txBuilder.SetSignatures(signing.SignatureV2{ - PubKey: priv1.PubKey(), - })) - tx = txBuilder.GetTx() + // require that decorator consumes expected amount of gas + consumedGas := suite.ctx.GasMeter().GasConsumed() - beforeGas + suite.Require().Equal(expectedGas, consumedGas, "Decorator did not consume the correct amount of gas") + + // simulation must not underestimate gas of this decorator even with nil signatures + txBuilder, err := suite.clientCtx.TxConfig.WrapTxBuilder(tx) + suite.Require().NoError(err) + suite.Require().NoError(txBuilder.SetSignatures(tc.sigV2)) + tx = txBuilder.GetTx() - simTxBytes, err := suite.clientCtx.TxConfig.TxJSONEncoder()(tx) - suite.Require().Nil(err, "Cannot marshal tx: %v", err) - // require that simulated tx is smaller than tx with signatures - suite.Require().True(len(simTxBytes) < len(txBytes), "simulated tx still has signatures") + simTxBytes, err := suite.clientCtx.TxConfig.TxJSONEncoder()(tx) + suite.Require().Nil(err, "Cannot marshal tx: %v", err) + // require that simulated tx is smaller than tx with signatures + suite.Require().True(len(simTxBytes) < len(txBytes), "simulated tx still has signatures") - // Set suite.ctx with smaller simulated TxBytes manually - suite.ctx = suite.ctx.WithTxBytes(simTxBytes) + // Set suite.ctx with smaller simulated TxBytes manually + suite.ctx = suite.ctx.WithTxBytes(simTxBytes) - beforeSimGas := suite.ctx.GasMeter().GasConsumed() + beforeSimGas := suite.ctx.GasMeter().GasConsumed() - // run antehandler with simulate=true - suite.ctx, err = antehandler(suite.ctx, tx, true) - consumedSimGas := suite.ctx.GasMeter().GasConsumed() - beforeSimGas + // run antehandler with simulate=true + suite.ctx, err = antehandler(suite.ctx, tx, true) + consumedSimGas := suite.ctx.GasMeter().GasConsumed() - beforeSimGas + + // require that antehandler passes and does not underestimate decorator cost + suite.Require().Nil(err, "ConsumeTxSizeGasDecorator returned error: %v", err) + suite.Require().True(consumedSimGas >= expectedGas, "Simulate mode underestimates gas on AnteDecorator. Simulated cost: %d, expected cost: %d", consumedSimGas, expectedGas) + + }) + } - // require that antehandler passes and does not underestimate decorator cost - suite.Require().Nil(err, "ConsumeTxSizeGasDecorator returned error: %v", err) - suite.Require().True(consumedSimGas >= expectedGas, "Simulate mode underestimates gas on AnteDecorator. Simulated cost: %d, expected cost: %d", consumedSimGas, expectedGas) } func (suite *AnteTestSuite) TestTxHeightTimeoutDecorator() {