diff options
Diffstat (limited to 'src/txmempool.cpp')
-rw-r--r-- | src/txmempool.cpp | 61 |
1 files changed, 19 insertions, 42 deletions
diff --git a/src/txmempool.cpp b/src/txmempool.cpp index b8af5a8d07..502a27dc6b 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -5,6 +5,7 @@ #include <txmempool.h> +#include <coins.h> #include <consensus/consensus.h> #include <consensus/tx_verify.h> #include <consensus/validation.h> @@ -723,16 +724,7 @@ void CTxMemPool::clear() _clear(); } -static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& mempoolDuplicate, const int64_t spendheight) -{ - TxValidationState dummy_state; // Not used. CheckTxInputs() should always pass - CAmount txfee = 0; - bool fCheckResult = tx.IsCoinBase() || Consensus::CheckTxInputs(tx, dummy_state, mempoolDuplicate, spendheight, txfee); - assert(fCheckResult); - UpdateCoins(tx, mempoolDuplicate, std::numeric_limits<int>::max()); -} - -void CTxMemPool::check(CChainState& active_chainstate) const +void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendheight) const { if (m_check_ratio == 0) return; @@ -745,20 +737,16 @@ 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++) { - unsigned int i = 0; + for (const auto& it : GetSortedDepthAndScore()) { checkTotal += it->GetTxSize(); check_total_fee += it->GetFee(); innerUsage += it->DynamicMemoryUsage(); const CTransaction& tx = it->GetTx(); innerUsage += memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst()); - bool fDependsWait = false; CTxMemPoolEntry::Parents setParentCheck; for (const CTxIn &txin : tx.vin) { // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's. @@ -766,17 +754,17 @@ 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; setParentCheck.insert(*it2); - } else { - assert(active_coins_tip.HaveCoin(txin.prevout)); } + // We are iterating through the mempool entries sorted in order by ancestor count. + // All parents must have been checked before their children and their coins added to + // the mempoolDuplicate coins cache. + assert(mempoolDuplicate.HaveCoin(txin.prevout)); // Check whether its inputs are marked in mapNextTx. auto it3 = mapNextTx.find(txin.prevout); assert(it3 != mapNextTx.end()); assert(it3->first == &txin.prevout); assert(it3->second == &tx); - i++; } auto comp = [](const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) -> bool { return a.GetTx().GetHash() == b.GetTx().GetHash(); @@ -803,6 +791,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; @@ -821,24 +812,12 @@ void CTxMemPool::check(CChainState& active_chainstate) const // just a sanity check, not definitive that this calc is correct... assert(it->GetSizeWithDescendants() >= child_sizes + it->GetTxSize()); - if (fDependsWait) - waitingOnDependants.push_back(&(*it)); - else { - CheckInputsAndUpdateCoins(tx, mempoolDuplicate, spendheight); - } - } - unsigned int stepsSinceLastRemove = 0; - while (!waitingOnDependants.empty()) { - const CTxMemPoolEntry* entry = waitingOnDependants.front(); - waitingOnDependants.pop_front(); - if (!mempoolDuplicate.HaveInputs(entry->GetTx())) { - waitingOnDependants.push_back(entry); - stepsSinceLastRemove++; - assert(stepsSinceLastRemove < waitingOnDependants.size()); - } else { - CheckInputsAndUpdateCoins(entry->GetTx(), mempoolDuplicate, spendheight); - stepsSinceLastRemove = 0; - } + TxValidationState dummy_state; // Not used. CheckTxInputs() should always pass + CAmount txfee = 0; + assert(!tx.IsCoinBase()); + assert(Consensus::CheckTxInputs(tx, dummy_state, mempoolDuplicate, spendheight, txfee)); + for (const auto& input: tx.vin) mempoolDuplicate.SpendCoin(input.prevout); + AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max()); } for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) { uint256 hash = it->second->GetHash(); @@ -947,8 +926,6 @@ TxMempoolInfo CTxMemPool::info(const GenTxid& gtxid) const return GetInfo(i); } -TxMempoolInfo CTxMemPool::info(const uint256& txid) const { return info(GenTxid{false, txid}); } - void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeDelta) { { @@ -1021,7 +998,7 @@ CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) c bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const { for (unsigned int i = 0; i < tx.vin.size(); i++) - if (exists(tx.vin[i].prevout.hash)) + if (exists(GenTxid::Txid(tx.vin[i].prevout.hash))) return false; return true; } @@ -1192,7 +1169,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpends if (pvNoSpendsRemaining) { for (const CTransaction& tx : txn) { for (const CTxIn& txin : tx.vin) { - if (exists(txin.prevout.hash)) continue; + if (exists(GenTxid::Txid(txin.prevout.hash))) continue; pvNoSpendsRemaining->push_back(txin.prevout); } } |