Skip to content

Commit 54c6f3c

Browse files
committed
[mempool] speed up check() by using coins cache and iterating in topo order
No behavior changes. Before, we're always adding transactions to the "check later" queue if they have any parents in the mempool. But there's no reason to do this if all of its inputs are already available from mempoolDuplicate. Instead, check for inputs, and only mark fDependsWait=true if the parents haven't been processed yet. Reduce the amount of "check later" transactions by looking at ancestors before descendants. Do this by iterating through them in ascending order by ancestor count. This works because a child will always have more in-mempool ancestors than its parent. We should never have any entries in the "check later" queue after this commit.
1 parent 30e240f commit 54c6f3c

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

src/txmempool.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,13 +693,14 @@ void CTxMemPool::check(CChainState& active_chainstate) const
693693
uint64_t checkTotal = 0;
694694
CAmount check_total_fee{0};
695695
uint64_t innerUsage = 0;
696+
uint64_t prev_ancestor_count{0};
696697

697698
CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
698699
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
699700
const int64_t spendheight = active_chainstate.m_chain.Height() + 1;
700701

701702
std::list<const CTxMemPoolEntry*> waitingOnDependants;
702-
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
703+
for (const auto& it : GetSortedDepthAndScore()) {
703704
unsigned int i = 0;
704705
checkTotal += it->GetTxSize();
705706
check_total_fee += it->GetFee();
@@ -714,7 +715,7 @@ void CTxMemPool::check(CChainState& active_chainstate) const
714715
if (it2 != mapTx.end()) {
715716
const CTransaction& tx2 = it2->GetTx();
716717
assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
717-
fDependsWait = true;
718+
if (!mempoolDuplicate.HaveCoin(txin.prevout)) fDependsWait = true;
718719
setParentCheck.insert(*it2);
719720
} else {
720721
assert(active_coins_tip.HaveCoin(txin.prevout));
@@ -751,6 +752,9 @@ void CTxMemPool::check(CChainState& active_chainstate) const
751752
assert(it->GetSizeWithAncestors() == nSizeCheck);
752753
assert(it->GetSigOpCostWithAncestors() == nSigOpCheck);
753754
assert(it->GetModFeesWithAncestors() == nFeesCheck);
755+
// Sanity check: we are walking in ascending ancestor count order.
756+
assert(prev_ancestor_count <= it->GetCountWithAncestors());
757+
prev_ancestor_count = it->GetCountWithAncestors();
754758

755759
// Check children against mapNextTx
756760
CTxMemPoolEntry::Children setChildrenCheck;

0 commit comments

Comments
 (0)