Sanity check feerate diagram in CTxMemPool::check()
What changed, and why it matters
This commit adds extra internal consistency checks to Bitcoin Core's memory pool validation routine and turns some soft 'Assume' warnings into hard 'assert' failures. It does not change network rules or how transactions are accepted; it only makes the program crash more reliably if its own bookkeeping about transaction fees and weights becomes internally inconsistent. That helps developers catch bugs during testing but is not a fix for an externally exploitable vulnerability.
No urgent action. Treat as normal code-quality/defensive-hardening patch. Ensure debug builds and tests exercise CTxMemPool::check() so any future mempool feerate-diagram bug is caught early.
Security signals we found
Strengthened internal consistency assertions in mempool validation
Conversion of Assume() to assert() in CTxMemPool::check()
New feerate diagram sanity checks against cumulative fee/weight state
No change to consensus, P2P, or mempool acceptance logic
Evidence from the diff
CTxMemPool::check() is a debug/consistency routine that validates the mempool’s internal state. The patch introduces cumulative tracking of modified fees and adjusted weights, compares them against the feerate diagram produced by GetFeerateDiagram(), and converts two Assume() checks into assert() so any mismatch aborts execution. The new assertions verify that the diagram’s cumulative points align with the sorted chunk iteration and that the final diagram point matches total modified fee and adjusted weight. This is a defensive hardening change inside a sanity-check function.
Changed components
src/txmempool.cppCTxMemPool::check()mempool feerate diagramInspect captured patch +23 / −1
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index de4a5572..a68975b2 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -425,6 +425,8 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei
uint64_t checkTotal = 0;
CAmount check_total_fee{0};
+ CAmount check_total_modified_fee{0};
+ int64_t check_total_adjusted_weight{0};
uint64_t innerUsage = 0;
assert(!m_txgraph->IsOversized(TxGraph::Level::MAIN));
@@ -436,13 +438,28 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei
// Number of chunks is bounded by number of transactions.
const auto diagram{GetFeerateDiagram()};
- Assume(diagram.size() <= score_with_topo.size() + 1);
+ assert(diagram.size() <= score_with_topo.size() + 1);
+ assert(diagram.size() >= 1);
std::optional<Wtxid> last_wtxid = std::nullopt;
+ auto diagram_iter = diagram.cbegin();
for (const auto& it : score_with_topo) {
+ // GetSortedScoreWithTopology() contains the same chunks as the feerate
+ // diagram. We do not know where the chunk boundaries are, but we can
+ // check that there are points at which they match the cumulative fee
+ // and weight.
+ // The feerate diagram should never get behind the current transaction
+ // size totals.
+ assert(diagram_iter->size >= check_total_adjusted_weight);
+ if (diagram_iter->fee == check_total_modified_fee &&
+ diagram_iter->size == check_total_adjusted_weight) {
+ ++diagram_iter;
+ }
checkTotal += it->GetTxSize();
+ check_total_adjusted_weight += it->GetAdjustedWeight();
check_total_fee += it->GetFee();
+ check_total_modified_fee += it->GetModifiedFee();
innerUsage += it->DynamicMemoryUsage();
const CTransaction& tx = it->GetTx();
@@ -509,8 +526,13 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei
assert(it2 != mapTx.end());
}
+ ++diagram_iter;
+ assert(diagram_iter == diagram.cend());
+
assert(totalTxSize == checkTotal);
assert(m_total_fee == check_total_fee);
+ assert(diagram.back().fee == check_total_modified_fee);
+ assert(diagram.back().size == check_total_adjusted_weight);
assert(innerUsage == cachedInnerUsage);
}
Why this scored 22/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.