aboutsummaryrefslogtreecommitdiff
path: root/src/txmempool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/txmempool.cpp')
-rw-r--r--src/txmempool.cpp61
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);
}
}