l0rinc
commented at 3:45 AM on September 23, 2026:
contributor
Problem: The mempool estimator added in #34075 checks health by comparing the weight of mempool transactions removed for a block with the block’s non-coinbase transaction weight.
It gets the removed entries from removeForBlock and sums their local weight.
That function matches mempool entries to block transactions by txid, which does not commit to witness data.
A matched entry can therefore have a different weight from the mined transaction, skewing the coverage check.
The block policy estimator also treats the local variant as confirmed even though its wtxid was not in the block.
Same-txid, different-witness transactions also appear in #35501 and #35893.
Fix: First, calculate total and covered block weight in one pass, computing each block transaction’s weight once and reusing it when a mempool entry matches.
This follows the one-pass accounting in GetMempoolHealth and makes the mined-weight basis explicit.
Then require an exact wtxid match in removeForBlock before reporting a mempool entry as mined.
A mismatched local variant is removed as a conflict, so neither estimator treats it as mined.
DrahtBot added the label TX fees and policy on Sep 23, 2026
DrahtBot
commented at 3:45 AM on September 23, 2026:
contributor
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
If your review is incorrectly listed, please copy-paste <code><!--meta-tag:bot-skip--></code> into the comment that the bot should ignore.
<!--174a7506f384e20aa4161008e828411d-->
Conflicts
Reviewers, this pull request conflicts with the following ones:
#35713 (Remove boost as a unit test runner by rustaceanrob)
#35480 (doc: document ZMQ notification behavior during reorgs and evictions by fernandguil)
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
<!--5faf32d7da4f0f540f40219e4f7537a3-->
l0rinc force-pushed on Sep 23, 2026
ismaelsadeeq
commented at 10:26 AM on September 23, 2026:
member
Concept ACK.
This is an inherent false positive in master that also affects the block_policy, too so #34075 inherits it :(. Should be rare to occur to make a meaningful difference, but it should be fixed.
removeForBlock matches by txid, so when a block mines txid A with a different wtxid than the A we have in our mempool, MempoolTransactionsRemovedForBlock still reports our variant as the one that was mined.
The mempool_policy then miscounts its weight (this PR's concern), but the block_policy also records a false confirmation, see processBlockTx it records our mempool variant's feerate bucket with a confirmation, but it's actually a different transaction that we did not see propagate.
Rather than recomputing weight from the connected block, I think there's a cleaner fix that covers both, we should just filter at removeForBlock: only record a tx removal as BLOCK on an exact wtxid match, and evict a witness mismatch as a CONFLICT instead via TransactionRemovedFromMempool.
l0rinc
commented at 8:07 PM on September 23, 2026:
contributor
we should just filter at removeForBlock: only record a tx removal as BLOCK on an exact wtxid match, and evict a witness mismatch as a CONFLICT instead via TransactionRemovedFromMempool.
I considered changing removeForBlock instead of only the fee estimator, but treating a witness mismatch as CONFLICT also changes removal notifications and may count as a failure in block policy estimation so I would prefer doing that in a followup to avoid surprising side-effects.
This fix is more focused on the more urgent problem and also reuses each mined transaction’s weight in one block walk (instead of two iterations) and tests the coverage calculation, so I’d keep it focused and tackle removal separately.
ismaelsadeeq
commented at 8:55 AM on September 24, 2026:
member
but treating a witness mismatch as CONFLICT also changes removal notifications and may count as a failure in block policy estimation so I would prefer doing that in a followup to avoid surprising side-effects.
That is the correct behaviour. It is a minimal fix that works for both.
l0rinc renamed this: fees: count mined weight in mempool coverage mempool, fees: stop treating different witness variants as mined on Sep 24, 2026
l0rinc force-pushed on Sep 24, 2026
l0rinc
commented at 10:18 PM on September 24, 2026:
contributor
Updated the stack to calculate coverage from mined transaction weights in one block walk, then require an exact wtxid match before reporting a mempool transaction as mined. I was hesitant to change removeForBlock at first, but it has only one production call site. The resulting notification changes also required documentation and release notes.
The previous implementation made the witness mismatch easy to miss in review, so I made the coverage calculation explicit before changing removal behavior. The later removeForBlock change also resolves the production mismatch, but the estimator change leaves a simpler one-pass calculation that computes each block transaction’s weight only once.
Mismatched variants now leave as conflicts, preventing false confirmations in block policy estimation and triggering the wallet and ZMQ notifications described in the release notes.
ismaelsadeeq
commented at 7:06 AM on September 25, 2026:
member
Approach ACK
This should be simplified, we do not need the refactor and the changes in the mempool estimator at all. The interface assumes all the txs reported by the notification have the same tx id and witness, and fixing the false positive in 4cc6c2c1e9da2dd4fae5175ca355765cb6013136 will naturally work for both fee rate estimators.
We should also have a test that indicates the effects of the fix for block_policy as well.
test: characterize witness-weight coverage
A txid does not commit to witness data.
Record that the estimator counts a heavier local variant and marks the window healthy even though mined coverage falls below the threshold.
b8c2f082e7
refactor: sum block weight with a loop
Use a loop that skips the coinbase to sum block weight.
Keep summing removed mempool entries separately so coverage values stay the same.
e06c01a363
refactor: sum block coverage in one pass
Walk the connected block and the removed entries together in block order.
Keep using the local variant's weight for covered transactions so this change preserves the existing coverage result.
ae4804ea0c
fees: count mined weight in coverage
Transactions with the same txid can have different witnesses in the mempool and the connected block.
Count matches using the block transaction's weight so the local witness size cannot skew the health check.
e730c0cd8a
test: characterize same-txid witness removal
Record that `removeForBlock` reports a different witness variant as mined and sends no conflict notification.
The block policy estimator then records a confirmation for the local variant's feerate bucket.
a9473055c9
mempool: classify witness mismatch as conflict
Report a mempool transaction as mined only when its wtxid matches the block transaction.
Remove a same-txid witness variant as CONFLICT so block policy does not record a false confirmation.
The removal callback also drops the local variant from fee tracking and can count a failure for targets it already missed.
Wallet and ZMQ subscribers now receive a removal event for this variant.
A wallet may issue an unconfirmed `-walletnotify` before the block callback confirms the txid, and ZMQ sequence subscribers see a removal for a txid in the block.
777393c100
doc: describe witness-mismatch block removals
Document the exact-wtxid removal contract and validation notifications.
Clarify the weight reported for mempool coverage and describe observable wallet, ZMQ, and fee-estimate changes.
100f7ff80c
l0rinc force-pushed on Sep 26, 2026
l0rinc
commented at 4:34 AM on September 26, 2026:
contributor
We should also have a test that indicates the effects of the fix for block_policy as well.
I added that check to remove_for_block_witness_mismatch: the block policy estimator no longer records the local variant as confirmed.
This should be simplified, we do not need the refactor and the changes in the mempool estimator at all
While there is a fix with a smaller diff, the separate sums before made it easy for us to miss that a txid match could have a different witness, so I’d like to learn from this and adjust the accounting first.
GetMempoolHealth already accumulates both coverage totals in one loop, so I’d like to follow the same pattern here.
Computing each block transaction’s weight once and reusing it for coverage when there’s a match keeps the code consistent and easier to review.
DrahtBot added the label CI failed on Sep 26, 2026
DrahtBot removed the label CI failed on Sep 28, 2026
ismaelsadeeq
commented at 8:36 AM on September 28, 2026:
member
I added that check to remove_for_block_witness_mismatch: the block policy estimator no longer records the local variant as confirmed.
Indeed, that's good, but in addition to that, you have mempool_health_uses_mined_witness_weight too, so my suggestion was also block_policy_record_witness_mismatch_as_failure so the effect is visible and explicit.
While there is a fix with a smaller diff, the separate sums before made it easy for us to miss that a txid match could have a different witness, so I’d like to learn from this and adjust the accounting first. GetMempoolHealth already accumulates both coverage totals in one loop, so I’d like to follow the same pattern here. Computing each block transaction’s weight once and reusing it for coverage when there’s a match keeps the code consistent and easier to review.
Not sure I agree, so I think that's a refactor that is beyond the scope of this fix, hence should be separate from this fix and be in it's own PR.
This is a metadata mirror of the GitHub repository
bitcoin/bitcoin.
This site is not affiliated with GitHub.
Content is generated from a GitHub metadata backup.
generated: 2026-09-28 10:51 UTC
This site is hosted by @0xB10C More mirrored repositories can be found on mirror.b10c.me