What changed, and why it matters
This commit simplifies how Bitcoin Core's memory pool (mempool) calculates the descendants of a transaction. It replaces a manual tree-walking routine with a call to a dedicated transaction graph component (m_txgraph). There is no direct evidence in the commit that this fixes a security bug; it appears to be a code cleanup or refactoring change.
Treat as a routine refactoring commit. If assessing risk, verify that TxGraph::GetDescendants behaves equivalently to the removed manual traversal (same ordering, completeness, and handling of already-present entries). No immediate security action is indicated by the diff alone.
Security signals we found
Refactor of mempool descendant traversal logic
Dependency on m_txgraph for correctness of descendant set
No explicit bounds, validation, or authorization changes visible
Evidence from the diff
CTxMemPool::CalculateDescendants() is rewritten to delegate descendant enumeration to m_txgraph->GetDescendants(…, TxGraph::Level::MAIN) instead of manually traversing CTxMemPoolEntry::m_children. The new code inserts each returned descendant into the output set via mapTx.iterator_to. The change removes ~25 lines of iterative traversal logic and adds 3 lines. No security-relevant behavior change is visible in the diff, though correctness now depends on the txgraph implementation.
Changed components
src/txmempool.cppCTxMemPool::CalculateDescendantsmempool transaction graph (m_txgraph / TxGraph)Inspect captured patch +3 / −25
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 2b8bec25..8ba41e94 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -323,33 +323,11 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
nTransactionsUpdated++;
}
-// Calculates descendants of entry that are not already in setDescendants, and adds to
-// setDescendants. Assumes entryit is already a tx in the mempool and CTxMemPoolEntry::m_children
-// is correct for tx and all descendants.
-// Also assumes that if an entry is in setDescendants already, then all
-// in-mempool descendants of it are already in setDescendants as well, so that we
-// can save time by not iterating over those entries.
+// Calculates descendants of given entry and adds to setDescendants.
void CTxMemPool::CalculateDescendants(txiter entryit, setEntries& setDescendants) const
{
- setEntries stage;
- if (setDescendants.count(entryit) == 0) {
- stage.insert(entryit);
- }
- // Traverse down the children of entry, only adding children that are not
- // accounted for in setDescendants already (because those children have either
- // already been walked, or will be walked in this iteration).
- while (!stage.empty()) {
- txiter it = *stage.begin();
- setDescendants.insert(it);
- stage.erase(it);
-
- const CTxMemPoolEntry::Children& children = it->GetMemPoolChildrenConst();
- for (const CTxMemPoolEntry& child : children) {
- txiter childiter = mapTx.iterator_to(child);
- if (!setDescendants.count(childiter)) {
- stage.insert(childiter);
- }
- }
+ for (auto tx : m_txgraph->GetDescendants(*entryit, TxGraph::Level::MAIN)) {
+ setDescendants.insert(mapTx.iterator_to(static_cast<const CTxMemPoolEntry&>(*tx)));
}
}
Why this scored 16/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.