From 18d46ba326dfd8643bc488730f72c92ff6310863 Mon Sep 17 00:00:00 2001 From: beer-1 Date: Thu, 6 Nov 2025 13:04:43 +0900 Subject: [PATCH 1/4] prevent updating check state before mempool insert --- baseapp/abci_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ baseapp/baseapp.go | 31 ++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/baseapp/abci_test.go b/baseapp/abci_test.go index 368833b25329..1107565946bc 100644 --- a/baseapp/abci_test.go +++ b/baseapp/abci_test.go @@ -620,6 +620,46 @@ func TestABCI_CheckTx(t *testing.T) { require.Nil(t, storedBytes) } +func TestABCI_CheckTx_DoesNotCorruptStateOnMempoolFailure(t *testing.T) { + counterKey := []byte("counter-key") + anteOpt := func(bapp *baseapp.BaseApp) { + bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, counterKey)) + } + + cfg := mempool.DefaultPriorityNonceMempoolConfig() + cfg.MaxTx = 1 + pool := mempool.NewPriorityMempool(cfg) + + suite := NewBaseAppSuite(t, anteOpt, baseapp.SetMempool(pool)) + baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImpl{t, capKey1, counterKey}) + + _, err := suite.baseApp.InitChain(&abci.RequestInitChain{ + ConsensusParams: &cmtproto.ConsensusParams{}, + }) + require.NoError(t, err) + + tx := newTxCounter(t, suite.txConfig, 0, 0) + txBytes, err := suite.txConfig.TxEncoder()(tx) + require.NoError(t, err) + + res, err := suite.baseApp.CheckTx(&abci.RequestCheckTx{Tx: txBytes}) + require.NoError(t, err) + require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) + + failTx := newTxCounter(t, suite.txConfig, 1, 0) + failTxBytes, err := suite.txConfig.TxEncoder()(failTx) + require.NoError(t, err) + + failRes, err := suite.baseApp.CheckTx(&abci.RequestCheckTx{Tx: failTxBytes}) + require.NoError(t, err) + require.False(t, failRes.IsOK()) + require.Contains(t, failRes.Log, mempool.ErrMempoolTxMaxCapacity.Error()) + + checkStateStore := getCheckStateCtx(suite.baseApp).KVStore(capKey1) + require.Equal(t, int64(1), getIntFromStore(t, checkStateStore, counterKey)) + require.Equal(t, 1, pool.CountTx()) +} + func TestABCI_FinalizeBlock_DeliverTx(t *testing.T) { anteKey := []byte("ante-key") anteOpt := func(bapp *baseapp.BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) } diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 31fd20b1f7e7..f055b245e469 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -846,6 +846,9 @@ func (app *BaseApp) RunTx(mode sdk.ExecMode, txBytes []byte, tx sdk.Tx, txIndex } } + mempoolCtx := ctx + var commitAnteCache func() + if app.anteHandler != nil { var ( anteCtx sdk.Context @@ -888,17 +891,31 @@ func (app *BaseApp) RunTx(mode sdk.ExecMode, txBytes []byte, tx sdk.Tx, txIndex return gInfo, nil, nil, err } - msCache.Write() - anteEvents = events.ToABCIEvents() + commitAnteCache = func() { + if msCache != nil { + msCache.Write() + } + anteEvents = events.ToABCIEvents() + } + + if mode == execModeCheck { + mempoolCtx = ctx.WithMultiStore(msCache) + } else { + commitAnteCache() + commitAnteCache = nil + } } - switch mode { - case execModeCheck: - err = app.mempool.Insert(ctx, tx) - if err != nil { + if mode == execModeCheck { + if err := app.mempool.Insert(mempoolCtx, tx); err != nil { return gInfo, nil, anteEvents, err } - case execModeFinalize: + + if commitAnteCache != nil { + commitAnteCache() + commitAnteCache = nil + } + } else if mode == execModeFinalize { err = app.mempool.Remove(tx) if err != nil && !errors.Is(err, mempool.ErrTxNotFound) { return gInfo, nil, anteEvents, From b9f65aef11fed3305e1c58293bd4a22a24c1c4c4 Mon Sep 17 00:00:00 2001 From: beer-1 Date: Tue, 11 Nov 2025 15:12:26 +0900 Subject: [PATCH 2/4] update readme --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 787216cbd698..e185388fe11f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,12 @@ Ref: https://keepachangelog.com/en/1.0.0/ # Changelog +## Unreleased + +### Bug Fixes + +* (baseapp) [#25550](https://github.com/cosmos/cosmos-sdk/pull/25550) Prevent updating check state before mempool insert + ## [v0.53.4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.53.3) - 2025-07-25 This patch update also includes minor dependency bumps. From 95c6b58eb0667d7505dc5a12996de9c10041b0d6 Mon Sep 17 00:00:00 2001 From: beer-1 Date: Tue, 11 Nov 2025 15:22:45 +0900 Subject: [PATCH 3/4] use switch --- baseapp/baseapp.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index f055b245e469..c200a626b698 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -906,7 +906,8 @@ func (app *BaseApp) RunTx(mode sdk.ExecMode, txBytes []byte, tx sdk.Tx, txIndex } } - if mode == execModeCheck { + switch mode { + case execModeCheck: if err := app.mempool.Insert(mempoolCtx, tx); err != nil { return gInfo, nil, anteEvents, err } @@ -915,7 +916,7 @@ func (app *BaseApp) RunTx(mode sdk.ExecMode, txBytes []byte, tx sdk.Tx, txIndex commitAnteCache() commitAnteCache = nil } - } else if mode == execModeFinalize { + case execModeFinalize: err = app.mempool.Remove(tx) if err != nil && !errors.Is(err, mempool.ErrTxNotFound) { return gInfo, nil, anteEvents, From 7a19e3989e470569dc8787fafb87f159e10f0eed Mon Sep 17 00:00:00 2001 From: beer-1 Date: Thu, 13 Nov 2025 22:50:39 +0900 Subject: [PATCH 4/4] fix lint --- baseapp/baseapp.go | 1 - 1 file changed, 1 deletion(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index c200a626b698..aa96d64e857b 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -914,7 +914,6 @@ func (app *BaseApp) RunTx(mode sdk.ExecMode, txBytes []byte, tx sdk.Tx, txIndex if commitAnteCache != nil { commitAnteCache() - commitAnteCache = nil } case execModeFinalize: err = app.mempool.Remove(tx)