From 7e6948f50cd4838a0161838a099f74e0b5b0213c Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:24:04 +0100 Subject: [PATCH] fix(baseapp): nil check in posthandler events (backport #19058) (#19067) Co-authored-by: Julien Robert --- CHANGELOG.md | 1 + baseapp/baseapp.go | 10 +++++++--- baseapp/baseapp_test.go | 28 ++++++++++++++++++++-------- baseapp/utils_test.go | 14 ++++++++++++++ 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 915484dcd433..1dc9d67dc4fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (baseapp) [#19058](https://github.com/cosmos/cosmos-sdk/pull/19058) Fix baseapp posthandler branch would fail if the `runMsgs` had returned an error. * (baseapp) [#18609](https://github.com/cosmos/cosmos-sdk/issues/18609) Fixed accounting in the block gas meter after module's beginBlock and before DeliverTx, ensuring transaction processing always starts with the expected zeroed out block gas meter. * (baseapp) [#18895](https://github.com/cosmos/cosmos-sdk/pull/18895) Fix de-duplicating vote extensions during validation in ValidateVoteExtensions. diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 98f3b7346383..d651fc8c074b 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -936,11 +936,15 @@ func (app *BaseApp) runTx(mode execMode, txBytes []byte) (gInfo sdk.GasInfo, res // Note that the state is still preserved. postCtx := runMsgCtx.WithEventManager(sdk.NewEventManager()) - newCtx, err := app.postHandler(postCtx, tx, mode == execModeSimulate, err == nil) - if err != nil { - return gInfo, nil, anteEvents, err + newCtx, errPostHandler := app.postHandler(postCtx, tx, mode == execModeSimulate, err == nil) + if errPostHandler != nil { + return gInfo, nil, anteEvents, errors.Join(err, errPostHandler) } + // we don't want runTx to panic if runMsgs has failed earlier + if result == nil { + result = &sdk.Result{} + } result.Events = append(result.Events, newCtx.EventManager().ABCIEvents()...) } diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 082aeacf402b..1ba3fb82d4d8 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -1,6 +1,7 @@ package baseapp_test import ( + "bytes" "context" "crypto/sha256" "fmt" @@ -45,9 +46,10 @@ var ( type ( BaseAppSuite struct { - baseApp *baseapp.BaseApp - cdc *codec.ProtoCodec - txConfig client.TxConfig + baseApp *baseapp.BaseApp + cdc *codec.ProtoCodec + txConfig client.TxConfig + logBuffer *bytes.Buffer } SnapshotsConfig struct { @@ -65,8 +67,10 @@ func NewBaseAppSuite(t *testing.T, opts ...func(*baseapp.BaseApp)) *BaseAppSuite txConfig := authtx.NewTxConfig(cdc, authtx.DefaultSignModes) db := dbm.NewMemDB() + logBuffer := new(bytes.Buffer) + logger := log.NewLogger(logBuffer, log.ColorOption(false)) - app := baseapp.NewBaseApp(t.Name(), log.NewTestLogger(t), db, txConfig.TxDecoder(), opts...) + app := baseapp.NewBaseApp(t.Name(), logger, db, txConfig.TxDecoder(), opts...) require.Equal(t, t.Name(), app.Name()) app.SetInterfaceRegistry(cdc.InterfaceRegistry()) @@ -80,9 +84,10 @@ func NewBaseAppSuite(t *testing.T, opts ...func(*baseapp.BaseApp)) *BaseAppSuite require.Nil(t, app.LoadLatestVersion()) return &BaseAppSuite{ - baseApp: app, - cdc: cdc, - txConfig: txConfig, + baseApp: app, + cdc: cdc, + txConfig: txConfig, + logBuffer: logBuffer, } } @@ -631,7 +636,6 @@ func TestBaseAppPostHandler(t *testing.T) { } suite := NewBaseAppSuite(t, anteOpt) - baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImpl{t, capKey1, []byte("foo")}) _, err := suite.baseApp.InitChain(&abci.RequestInitChain{ @@ -666,6 +670,14 @@ func TestBaseAppPostHandler(t *testing.T) { require.False(t, res.TxResults[0].IsOK(), fmt.Sprintf("%v", res)) require.True(t, postHandlerRun) + + // regression test, should not panic when runMsgs fails + tx = wonkyMsg(t, suite.txConfig, tx) + txBytes, err = suite.txConfig.TxEncoder()(tx) + require.NoError(t, err) + _, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1, Txs: [][]byte{txBytes}}) + require.NoError(t, err) + require.NotContains(t, suite.logBuffer.String(), "panic recovered in runTx") } // Test and ensure that invalid block heights always cause errors. diff --git a/baseapp/utils_test.go b/baseapp/utils_test.go index 81a1dfe5fb8e..1de526953fae 100644 --- a/baseapp/utils_test.go +++ b/baseapp/utils_test.go @@ -390,3 +390,17 @@ func setFailOnHandler(cfg client.TxConfig, tx signing.Tx, fail bool) signing.Tx builder.SetMsgs(msgs...) return builder.GetTx() } + +// wonkyMsg is to be used to run a MsgCounter2 message when the MsgCounter2 handler is not registered. +func wonkyMsg(t *testing.T, cfg client.TxConfig, tx signing.Tx) signing.Tx { + t.Helper() + builder := cfg.NewTxBuilder() + builder.SetMemo(tx.GetMemo()) + + msgs := tx.GetMsgs() + msgs = append(msgs, &baseapptestutil.MsgCounter2{}) + + err := builder.SetMsgs(msgs...) + require.NoError(t, err) + return builder.GetTx() +}