Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Bug Fixes

* (cli) [#25485](https://github.com/cosmos/cosmos-sdk/pull/25485) Avoid failed to convert address field in `withdraw-validator-commission` cmd.
* (baseapp) [#25551](https://github.com/cosmos/cosmos-sdk/pull/25551) Prevent updating check state before mempool insert

## [v0.53.4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.53.3) - 2025-07-25

Expand Down
40 changes: 40 additions & 0 deletions baseapp/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,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)) }
Expand Down
31 changes: 24 additions & 7 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,9 @@ func (app *BaseApp) runTx(mode execMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.G
}
}

mempoolCtx := ctx
var commitAnteCache func()

if app.anteHandler != nil {
Comment on lines 909 to 915
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change potentially affects state.

Call sequence:

(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).runTx (baseapp/baseapp.go:844)
(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).deliverTx (baseapp/baseapp.go:772)
(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).internalFinalizeBlock (baseapp/baseapp.go:705)
(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).FinalizeBlock (baseapp/baseapp.go:869)

var (
anteCtx sdk.Context
Expand Down Expand Up @@ -951,17 +954,31 @@ func (app *BaseApp) runTx(mode execMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.G
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,
Expand Down