aboutsummaryrefslogtreecommitdiff
path: root/src/txmempool.cpp
diff options
context:
space:
mode:
authorglozow <gloriajzhao@gmail.com>2021-09-30 09:08:40 +0100
committerglozow <gloriajzhao@gmail.com>2021-10-04 15:00:28 +0100
commit54c6f3c1da01090aee9691a2c2bee0984a054ce8 (patch)
tree2f0759ff420949138f3ddf882ef4fa4168ad4293 /src/txmempool.cpp
parent30e240f65e69c6dffcd033afc63895345bd51f53 (diff)
downloadbitcoin-54c6f3c1da01090aee9691a2c2bee0984a054ce8.tar.xz
[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.cpp8
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;