mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-10-09 19:13:28 +02:00
[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.
This commit is contained in:
@@ -693,13 +693,14 @@ void CTxMemPool::check(CChainState& active_chainstate) const
|
|||||||
uint64_t checkTotal = 0;
|
uint64_t checkTotal = 0;
|
||||||
CAmount check_total_fee{0};
|
CAmount check_total_fee{0};
|
||||||
uint64_t innerUsage = 0;
|
uint64_t innerUsage = 0;
|
||||||
|
uint64_t prev_ancestor_count{0};
|
||||||
|
|
||||||
CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
|
CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
|
||||||
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
|
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
|
||||||
const int64_t spendheight = active_chainstate.m_chain.Height() + 1;
|
const int64_t spendheight = active_chainstate.m_chain.Height() + 1;
|
||||||
|
|
||||||
std::list<const CTxMemPoolEntry*> waitingOnDependants;
|
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;
|
unsigned int i = 0;
|
||||||
checkTotal += it->GetTxSize();
|
checkTotal += it->GetTxSize();
|
||||||
check_total_fee += it->GetFee();
|
check_total_fee += it->GetFee();
|
||||||
@@ -714,7 +715,7 @@ void CTxMemPool::check(CChainState& active_chainstate) const
|
|||||||
if (it2 != mapTx.end()) {
|
if (it2 != mapTx.end()) {
|
||||||
const CTransaction& tx2 = it2->GetTx();
|
const CTransaction& tx2 = it2->GetTx();
|
||||||
assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
|
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);
|
setParentCheck.insert(*it2);
|
||||||
} else {
|
} else {
|
||||||
assert(active_coins_tip.HaveCoin(txin.prevout));
|
assert(active_coins_tip.HaveCoin(txin.prevout));
|
||||||
@@ -751,6 +752,9 @@ void CTxMemPool::check(CChainState& active_chainstate) const
|
|||||||
assert(it->GetSizeWithAncestors() == nSizeCheck);
|
assert(it->GetSizeWithAncestors() == nSizeCheck);
|
||||||
assert(it->GetSigOpCostWithAncestors() == nSigOpCheck);
|
assert(it->GetSigOpCostWithAncestors() == nSigOpCheck);
|
||||||
assert(it->GetModFeesWithAncestors() == nFeesCheck);
|
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
|
// Check children against mapNextTx
|
||||||
CTxMemPoolEntry::Children setChildrenCheck;
|
CTxMemPoolEntry::Children setChildrenCheck;
|
||||||
|
Reference in New Issue
Block a user