diff options
author | glozow <gloriajzhao@gmail.com> | 2021-09-30 09:08:40 +0100 |
---|---|---|
committer | glozow <gloriajzhao@gmail.com> | 2021-10-04 15:00:28 +0100 |
commit | 54c6f3c1da01090aee9691a2c2bee0984a054ce8 (patch) | |
tree | 2f0759ff420949138f3ddf882ef4fa4168ad4293 /src/txmempool.cpp | |
parent | 30e240f65e69c6dffcd033afc63895345bd51f53 (diff) |
[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.
Diffstat (limited to 'src/txmempool.cpp')
-rw-r--r-- | src/txmempool.cpp | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 5a93f30c8a..10f7f66263 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -693,13 +693,14 @@ void CTxMemPool::check(CChainState& active_chainstate) const uint64_t checkTotal = 0; CAmount check_total_fee{0}; uint64_t innerUsage = 0; + uint64_t prev_ancestor_count{0}; CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip(); CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip)); const int64_t spendheight = active_chainstate.m_chain.Height() + 1; std::list<const CTxMemPoolEntry*> waitingOnDependants; - for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { + for (const auto& it : GetSortedDepthAndScore()) { unsigned int i = 0; checkTotal += it->GetTxSize(); check_total_fee += it->GetFee(); @@ -714,7 +715,7 @@ void CTxMemPool::check(CChainState& active_chainstate) const if (it2 != mapTx.end()) { const CTransaction& tx2 = it2->GetTx(); assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull()); - fDependsWait = true; + if (!mempoolDuplicate.HaveCoin(txin.prevout)) fDependsWait = true; setParentCheck.insert(*it2); } else { assert(active_coins_tip.HaveCoin(txin.prevout)); @@ -751,6 +752,9 @@ void CTxMemPool::check(CChainState& active_chainstate) const assert(it->GetSizeWithAncestors() == nSizeCheck); assert(it->GetSigOpCostWithAncestors() == nSigOpCheck); assert(it->GetModFeesWithAncestors() == nFeesCheck); + // Sanity check: we are walking in ascending ancestor count order. + assert(prev_ancestor_count <= it->GetCountWithAncestors()); + prev_ancestor_count = it->GetCountWithAncestors(); // Check children against mapNextTx CTxMemPoolEntry::Children setChildrenCheck; |