Skip to content

fix: prevent updating check state before mempool insert - #25550

Closed
beer-1 wants to merge 26 commits into
cosmos:mainfrom
beer-1:fix/issue-25543
Closed

fix: prevent updating check state before mempool insert#25550
beer-1 wants to merge 26 commits into
cosmos:mainfrom
beer-1:fix/issue-25543

Conversation

@beer-1

@beer-1 beer-1 commented Nov 11, 2025

Copy link
Copy Markdown
Contributor

Description

Closes: #25543

@codecov

codecov Bot commented Nov 12, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.81%. Comparing base (ebb120a) to head (761eb21).
⚠️ Report is 136 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #25550      +/-   ##
==========================================
- Coverage   64.82%   64.81%   -0.02%     
==========================================
  Files         810      794      -16     
  Lines       56157    55179     -978     
==========================================
- Hits        36406    35763     -643     
+ Misses      19751    19416     -335     
Files with missing lines Coverage Δ
baseapp/baseapp.go 86.48% <100.00%> (+0.30%) ⬆️

... and 19 files with indirect coverage changes

Impacted file tree graph

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@aljo242

aljo242 commented Nov 13, 2025

Copy link
Copy Markdown
Contributor

@beer-1 lint failing

@beer-1

beer-1 commented Nov 13, 2025

Copy link
Copy Markdown
Contributor Author

@aljo242 fixed!

@aljo242

aljo242 commented Nov 14, 2025

Copy link
Copy Markdown
Contributor

@beer-1 do you see any potential for performance overhead due to this?

@beer-1

beer-1 commented Nov 14, 2025

Copy link
Copy Markdown
Contributor Author

@beer-1 do you see any potential for performance overhead due to this?

I don't think this introduce any performance degradation because it is just changing order of execution

@beer-1

beer-1 commented Dec 24, 2025

Copy link
Copy Markdown
Contributor Author

comment to prevent stale closing

Comment thread baseapp/baseapp.go Outdated
}

if mode == execModeCheck {
mempoolCtx = ctx.WithMultiStore(msCache)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

confirming my understanding here, we need to set the multistore for mempoolCtx back to to msCache since we are now not writing msCache before calling mempool.Insert when in modeCheck. So if we do not use msCache as our multistore, mmempool.Insert may operate on a stale multistore. Once we do call commitAnteCache though, we are safe to use ctx again since its ms has now been updated.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I modified the mempool.Insert call locally to use ctx instead of mempoolCtx and all of our unit tests still passed. Could you think of a unit test that would demonstrate this ms requirement? imo its not super clear from this logic that that is required (would probably be easiest with a mock mempool and ante handler just checking values in the ms).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@mattac21 Yes, this was a missing regression test.

I added a simple mock mempool test for this case: the ante handler writes a marker into the cached multistore, and the mock mempool's Insert asserts that the marker is visible.

With the current mempoolCtx = ctx.WithMultiStore(msCache) behavior, the test passes. If I change mempool.Insert(mempoolCtx, tx) to mempool.Insert(ctx, tx), it fails because the ante cached write is not visible to the mempool.

So I think this confirms that mempoolCtx or an equivalent context backed by msCache is required here.

@github-actions

github-actions Bot commented May 9, 2026

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days-before-close if no further activity occurs.

@aljo242 aljo242 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the commitAnteCache closure adds unnecessary indirection — you need to track whether it's nil, understand it's deferred, and follow control flow across two separate blocks.

simpler restructure achieves the same thing:

if app.anteHandler != nil {
    // ... ante runs against msCache ...
    if mode != execModeCheck {
        msCache.Write()
        anteEvents = events.ToABCIEvents()
    }
}

switch mode {
case execModeCheck:
    err = app.mempool.Insert(ctx, tx)
    if err != nil {
        return gInfo, nil, anteEvents, err
    }
    if msCache != nil {
        msCache.Write()
    }
    anteEvents = events.ToABCIEvents()

no closure, no nil-guarded function variable. intent is explicit: write after insert for check mode, write immediately otherwise. same behavior, easier to follow.

@aljo242

aljo242 commented May 26, 2026

Copy link
Copy Markdown
Contributor

the commitAnteCache closure adds unnecessary indirection — you need to track whether it's nil, understand it's deferred, and follow control flow across two separate blocks.

simpler restructure achieves the same thing:

if app.anteHandler != nil {
    // ... ante runs against msCache ...
    if mode != execModeCheck {
        msCache.Write()
        anteEvents = events.ToABCIEvents()
    }
}

switch mode {
case execModeCheck:
    err = app.mempool.Insert(ctx, tx)
    if err != nil {
        return gInfo, nil, anteEvents, err
    }
    if msCache != nil {
        msCache.Write()
    }
    anteEvents = events.ToABCIEvents()

no closure, no nil-guarded function variable. intent is explicit: write after insert for check mode, write immediately otherwise. same behavior, easier to follow.

@beer-1

beer-1 commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

@aljo242 I agree that removing the closure makes the flow easier to follow, but I don't think we can use ctx directly for mempool.Insert.

If we do that, mempool.Insert runs with the original multistore, without the ante handler's cached writes. That can break app-chain developers' expectations when their mempool logic relies on state changes made during ante execution.

So I think the safer restructure is to remove the commitAnteCache closure, but still pass a context backed by the ante cache into mempool.Insert in check mode.

@beer-1
beer-1 requested a review from a team as a code owner May 28, 2026 02:21
@beer-1
beer-1 requested a review from aljo242 May 29, 2026 03:42
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days-before-close if no further activity occurs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: prevent invalid sequence rejections caused by early ante state writes

3 participants