Sanity check `GetFeerateDiagram()` in CTxMemPool::check()
What changed, and why it matters
This commit adds an internal sanity check inside Bitcoin Core's transaction memory pool (mempool) self-check routine. It verifies that a newly introduced feerate diagram data structure stays within expected size bounds. The change is defensive and only affects debug/self-check code, not normal network operation. There is no indication it fixes an active security vulnerability or that it is exploitable by an attacker.
No urgent action required. Treat as routine code-quality/defensive commit. Reviewers may want to confirm the +1 bound is correct and that the new feerate diagram implementation elsewhere cannot violate this invariant in a way that would hide a real bug in release builds where Assume() is disabled.
Security signals we found
Defensive invariant assertion added to mempool self-check
No network-facing or consensus code changed
No input validation, authorization, or cryptographic logic modified
No memory-unsafe operations introduced
Evidence from the diff
The patch modifies CTxMemPool::check(), a consistency-checking function typically run under debug conditions or via explicit sanity checks. It now calls GetSortedScoreWithTopology() once and stores the result, then calls GetFeerateDiagram() and asserts via Assume() that the returned diagram’s size does not exceed score_with_topo.size() + 1. This is a structural invariant check for the feerate diagram introduced elsewhere, not a consensus or network rule change. The Assume macro generally compiles to a no-op in release builds, so the check has no runtime effect in production nodes.
Changed components
src/txmempool.cppCTxMemPool::check()GetFeerateDiagram()GetSortedScoreWithTopology()Inspect captured patch +7 / −1
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 592f6194..5a46a029 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -425,9 +425,15 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
+ const auto score_with_topo{GetSortedScoreWithTopology()};
+
+ // Number of chunks is bounded by number of transactions.
+ const auto diagram{GetFeerateDiagram()};
+ Assume(diagram.size() <= score_with_topo.size() + 1);
+
std::optional<Wtxid> last_wtxid = std::nullopt;
- for (const auto& it : GetSortedScoreWithTopology()) {
+ for (const auto& it : score_with_topo) {
checkTotal += it->GetTxSize();
check_total_fee += it->GetFee();
innerUsage += it->DynamicMemoryUsage();
Why this scored 24/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.