LCOV - code coverage report
Current view: top level - src - txmempool.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 804 1172 68.6 %
Date: 2026-06-25 07:23:51 Functions: 79 97 81.4 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include <txmempool.h>
       7             : 
       8             : #include <chain.h>
       9             : #include <coins.h>
      10             : #include <consensus/consensus.h>
      11             : #include <consensus/tx_verify.h>
      12             : #include <consensus/validation.h>
      13             : #include <hash.h>
      14             : #include <index/addressindex_util.h>
      15             : #include <policy/fees.h>
      16             : #include <policy/policy.h>
      17             : #include <policy/settings.h>
      18             : #include <util/check.h>
      19             : #include <util/moneystr.h>
      20             : #include <util/overflow.h>
      21             : #include <util/system.h>
      22             : #include <util/time.h>
      23             : #include <validationinterface.h>
      24             : 
      25             : #include <evo/specialtx.h>
      26             : #include <evo/assetlocktx.h>
      27             : #include <evo/providertx.h>
      28             : #include <evo/deterministicmns.h>
      29             : #include <instantsend/instantsend.h>
      30             : 
      31             : #include <cmath>
      32             : #include <memory>
      33             : #include <optional>
      34             : #include <ranges>
      35             : 
      36             : // Forward declarations for index globals and utilities
      37             : class AddressIndex;
      38             : class SpentIndex;
      39             : extern std::unique_ptr<AddressIndex> g_addressindex;
      40             : extern std::unique_ptr<SpentIndex> g_spentindex;
      41             : 
      42           6 : bool TestLockPointValidity(CChain& active_chain, const LockPoints& lp)
      43             : {
      44           6 :     AssertLockHeld(cs_main);
      45             :     // If there are relative lock times then the maxInputBlock will be set
      46             :     // If there are no relative lock times, the LockPoints don't depend on the chain
      47           6 :     if (lp.maxInputBlock) {
      48             :         // Check whether active_chain is an extension of the block at which the LockPoints
      49             :         // calculation was valid.  If not LockPoints are no longer valid
      50           0 :         if (!active_chain.Contains(lp.maxInputBlock)) {
      51           0 :             return false;
      52             :         }
      53           0 :     }
      54             : 
      55             :     // LockPoints still valid
      56           6 :     return true;
      57           6 : }
      58             : 
      59       81225 : CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee,
      60             :                                  int64_t time, unsigned int entry_height,
      61             :                                  bool spends_coinbase, int64_t sigops_count, LockPoints lp)
      62       27075 :     : tx{tx},
      63       27075 :       nFee{fee},
      64       27075 :       nTxSize(tx->GetTotalSize()),
      65       27075 :       nUsageSize{RecursiveDynamicUsage(tx)},
      66       27075 :       nTime{time},
      67       27075 :       entryHeight{entry_height},
      68       27075 :       spendsCoinbase{spends_coinbase},
      69       27075 :       sigOpCount{sigops_count},
      70       27075 :       m_modified_fee{nFee},
      71       27075 :       lockPoints{lp},
      72             :       nSizeWithDescendants{GetTxSize()},
      73             :       nModFeesWithDescendants{nFee},
      74             :       nSizeWithAncestors{GetTxSize()},
      75             :       nModFeesWithAncestors{nFee},
      76       27075 :       nSigOpCountWithAncestors{sigOpCount} {}
      77             : 
      78           6 : void CTxMemPoolEntry::UpdateModifiedFee(CAmount newFeeDelta)
      79             : {
      80           6 :     nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, newFeeDelta);
      81           6 :     nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, newFeeDelta);
      82           6 :     m_modified_fee = SaturatingAdd(m_modified_fee, newFeeDelta);
      83           6 : }
      84             : 
      85           0 : void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
      86             : {
      87           0 :     lockPoints = lp;
      88           0 : }
      89             : 
      90    70976052 : size_t CTxMemPoolEntry::GetTxSize() const
      91             : {
      92    70976052 :     return GetVirtualTransactionSize(nTxSize, sigOpCount);
      93             : }
      94             : 
      95           0 : void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendants,
      96             :                                       const std::set<uint256>& setExclude, std::set<uint256>& descendants_to_remove,
      97             :                                       uint64_t ancestor_size_limit, uint64_t ancestor_count_limit)
      98             : {
      99           0 :     CTxMemPoolEntry::Children stageEntries, descendants;
     100           0 :     stageEntries = updateIt->GetMemPoolChildrenConst();
     101             : 
     102           0 :     while (!stageEntries.empty()) {
     103           0 :         const CTxMemPoolEntry& descendant = *stageEntries.begin();
     104           0 :         descendants.insert(descendant);
     105           0 :         stageEntries.erase(descendant);
     106           0 :         const CTxMemPoolEntry::Children& children = descendant.GetMemPoolChildrenConst();
     107           0 :         for (const CTxMemPoolEntry& childEntry : children) {
     108           0 :             cacheMap::iterator cacheIt = cachedDescendants.find(mapTx.iterator_to(childEntry));
     109           0 :             if (cacheIt != cachedDescendants.end()) {
     110             :                 // We've already calculated this one, just add the entries for this set
     111             :                 // but don't traverse again.
     112           0 :                 for (txiter cacheEntry : cacheIt->second) {
     113           0 :                     descendants.insert(*cacheEntry);
     114             :                 }
     115           0 :             } else if (!descendants.count(childEntry)) {
     116             :                 // Schedule for later processing
     117           0 :                 stageEntries.insert(childEntry);
     118           0 :             }
     119             :         }
     120             :     }
     121             :     // descendants now contains all in-mempool descendants of updateIt.
     122             :     // Update and add to cached descendant map
     123           0 :     int64_t modifySize = 0;
     124           0 :     CAmount modifyFee = 0;
     125           0 :     int64_t modifyCount = 0;
     126           0 :     for (const CTxMemPoolEntry& descendant : descendants) {
     127           0 :         if (!setExclude.count(descendant.GetTx().GetHash())) {
     128           0 :             modifySize += descendant.GetTxSize();
     129           0 :             modifyFee += descendant.GetModifiedFee();
     130           0 :             modifyCount++;
     131           0 :             cachedDescendants[updateIt].insert(mapTx.iterator_to(descendant));
     132             :             // Update ancestor state for each descendant
     133           0 :             mapTx.modify(mapTx.iterator_to(descendant), [=](CTxMemPoolEntry& e) {
     134           0 :                 e.UpdateAncestorState(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCount());
     135           0 :             });
     136             :             // Don't directly remove the transaction here -- doing so would
     137             :             // invalidate iterators in cachedDescendants. Mark it for removal
     138             :             // by inserting into descendants_to_remove.
     139           0 :             if (descendant.GetCountWithAncestors() > ancestor_count_limit || descendant.GetSizeWithAncestors() > ancestor_size_limit) {
     140           0 :                 descendants_to_remove.insert(descendant.GetTx().GetHash());
     141           0 :             }
     142           0 :         }
     143             :     }
     144           0 :     mapTx.modify(updateIt, [=](CTxMemPoolEntry& e) { e.UpdateDescendantState(modifySize, modifyFee, modifyCount); });
     145           0 : }
     146             : 
     147          17 : void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate, uint64_t ancestor_size_limit, uint64_t ancestor_count_limit)
     148             : {
     149          17 :     AssertLockHeld(cs);
     150             :     // For each entry in vHashesToUpdate, store the set of in-mempool, but not
     151             :     // in-vHashesToUpdate transactions, so that we don't have to recalculate
     152             :     // descendants when we come across a previously seen entry.
     153          17 :     cacheMap mapMemPoolDescendantsToUpdate;
     154             : 
     155             :     // Use a set for lookups into vHashesToUpdate (these entries are already
     156             :     // accounted for in the state of their ancestors)
     157          17 :     std::set<uint256> setAlreadyIncluded(vHashesToUpdate.begin(), vHashesToUpdate.end());
     158             : 
     159          17 :     std::set<uint256> descendants_to_remove;
     160             : 
     161             :     // Iterate in reverse, so that whenever we are looking at a transaction
     162             :     // we are sure that all in-mempool descendants have already been processed.
     163             :     // This maximizes the benefit of the descendant cache and guarantees that
     164             :     // CTxMemPoolEntry::m_children will be updated, an assumption made in
     165             :     // UpdateForDescendants.
     166          17 :     for (const uint256& hash : vHashesToUpdate | std::views::reverse) {
     167             :         // calculate children from mapNextTx
     168           0 :         txiter it = mapTx.find(hash);
     169           0 :         if (it == mapTx.end()) {
     170           0 :             continue;
     171             :         }
     172           0 :         auto iter = mapNextTx.lower_bound(COutPoint(hash, 0));
     173             :         // First calculate the children, and update CTxMemPoolEntry::m_children to
     174             :         // include them, and update their CTxMemPoolEntry::m_parents to include this tx.
     175             :         // we cache the in-mempool children to avoid duplicate updates
     176             :         {
     177           0 :             WITH_FRESH_EPOCH(m_epoch);
     178           0 :             for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
     179           0 :                 const uint256 &childHash = iter->second->GetHash();
     180           0 :                 txiter childIter = mapTx.find(childHash);
     181           0 :                 assert(childIter != mapTx.end());
     182             :                 // We can skip updating entries we've encountered before or that
     183             :                 // are in the block (which are already accounted for).
     184           0 :                 if (!visited(childIter) && !setAlreadyIncluded.count(childHash)) {
     185           0 :                     UpdateChild(it, childIter, true);
     186           0 :                     UpdateParent(childIter, it, true);
     187           0 :                 }
     188           0 :             }
     189           0 :         } // release epoch guard for UpdateForDescendants
     190           0 :         UpdateForDescendants(it, mapMemPoolDescendantsToUpdate, setAlreadyIncluded, descendants_to_remove, ancestor_size_limit, ancestor_count_limit);
     191             :     }
     192             : 
     193          17 :     for (const auto& txid : descendants_to_remove) {
     194             :         // This txid may have been removed already in a prior call to removeRecursive.
     195             :         // Therefore we ensure it is not yet removed already.
     196           0 :         if (const std::optional<txiter> txiter = GetIter(txid)) {
     197           0 :             removeRecursive((*txiter)->GetTx(), MemPoolRemovalReason::SIZELIMIT);
     198           0 :         }
     199             :     }
     200          17 : }
     201             : 
     202       52702 : bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
     203             :                                                   size_t entry_count,
     204             :                                                   setEntries& setAncestors,
     205             :                                                   CTxMemPoolEntry::Parents& staged_ancestors,
     206             :                                                   uint64_t limitAncestorCount,
     207             :                                                   uint64_t limitAncestorSize,
     208             :                                                   uint64_t limitDescendantCount,
     209             :                                                   uint64_t limitDescendantSize,
     210             :                                                   std::string &errString) const
     211             : {
     212       52702 :     size_t totalSizeWithAncestors = entry_size;
     213             : 
     214     1078808 :     while (!staged_ancestors.empty()) {
     215     1026106 :         const CTxMemPoolEntry& stage = staged_ancestors.begin()->get();
     216     1026106 :         txiter stageit = mapTx.iterator_to(stage);
     217             : 
     218     1026106 :         setAncestors.insert(stageit);
     219     1026106 :         staged_ancestors.erase(stage);
     220     1026106 :         totalSizeWithAncestors += stageit->GetTxSize();
     221             : 
     222     1026106 :         if (stageit->GetSizeWithDescendants() + entry_size > limitDescendantSize) {
     223           0 :             errString = strprintf("exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limitDescendantSize);
     224           0 :             return false;
     225     1026106 :         } else if (stageit->GetCountWithDescendants() + entry_count > limitDescendantCount) {
     226           0 :             errString = strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limitDescendantCount);
     227           0 :             return false;
     228     1026106 :         } else if (totalSizeWithAncestors > limitAncestorSize) {
     229           0 :             errString = strprintf("exceeds ancestor size limit [limit: %u]", limitAncestorSize);
     230           0 :             return false;
     231             :         }
     232             : 
     233     1026106 :         const CTxMemPoolEntry::Parents& parents = stageit->GetMemPoolParentsConst();
     234     2049886 :         for (const CTxMemPoolEntry& parent : parents) {
     235     1023780 :             txiter parent_it = mapTx.iterator_to(parent);
     236             : 
     237             :             // If this is a new ancestor, add it.
     238     1023780 :             if (setAncestors.count(parent_it) == 0) {
     239     1023772 :                 staged_ancestors.insert(parent);
     240     1023772 :             }
     241     1023780 :             if (staged_ancestors.size() + setAncestors.size() + entry_count > limitAncestorCount) {
     242           0 :                 errString = strprintf("too many unconfirmed ancestors [limit: %u]", limitAncestorCount);
     243           0 :                 return false;
     244             :             }
     245             :         }
     246             :     }
     247             : 
     248       52702 :     return true;
     249       52702 : }
     250             : 
     251           3 : bool CTxMemPool::CheckPackageLimits(const Package& package,
     252             :                                     uint64_t limitAncestorCount,
     253             :                                     uint64_t limitAncestorSize,
     254             :                                     uint64_t limitDescendantCount,
     255             :                                     uint64_t limitDescendantSize,
     256             :                                     std::string &errString) const
     257             : {
     258           3 :     CTxMemPoolEntry::Parents staged_ancestors;
     259           3 :     size_t total_size = 0;
     260           9 :     for (const auto& tx : package) {
     261           6 :         total_size += GetVirtualTransactionSize(*tx);
     262          12 :         for (const auto& input : tx->vin) {
     263           6 :             std::optional<txiter> piter = GetIter(input.prevout.hash);
     264           6 :             if (piter) {
     265           0 :                 staged_ancestors.insert(**piter);
     266           0 :                 if (staged_ancestors.size() + package.size() > limitAncestorCount) {
     267           0 :                     errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
     268           0 :                     return false;
     269             :                 }
     270           0 :             }
     271             :         }
     272             :     }
     273             :     // When multiple transactions are passed in, the ancestors and descendants of all transactions
     274             :     // considered together must be within limits even if they are not interdependent. This may be
     275             :     // stricter than the limits for each individual transaction.
     276           3 :     setEntries setAncestors;
     277           6 :     const auto ret = CalculateAncestorsAndCheckLimits(total_size, package.size(),
     278             :                                                       setAncestors, staged_ancestors,
     279           3 :                                                       limitAncestorCount, limitAncestorSize,
     280           3 :                                                       limitDescendantCount, limitDescendantSize, errString);
     281             :     // It's possible to overestimate the ancestor/descendant totals.
     282           3 :     if (!ret) errString.insert(0, "possibly ");
     283           3 :     return ret;
     284           3 : }
     285             : 
     286       52699 : bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
     287             :                                            setEntries &setAncestors,
     288             :                                            uint64_t limitAncestorCount,
     289             :                                            uint64_t limitAncestorSize,
     290             :                                            uint64_t limitDescendantCount,
     291             :                                            uint64_t limitDescendantSize,
     292             :                                            std::string &errString,
     293             :                                            bool fSearchForParents /* = true */) const
     294             : {
     295       52699 :     CTxMemPoolEntry::Parents staged_ancestors;
     296       52699 :     const CTransaction &tx = entry.GetTx();
     297             : 
     298       52699 :     if (fSearchForParents) {
     299             :         // Get parents of this transaction that are in the mempool
     300             :         // GetMemPoolParents() is only valid for entries in the mempool, so we
     301             :         // iterate mapTx to find parents.
     302       56129 :         for (unsigned int i = 0; i < tx.vin.size(); i++) {
     303       28289 :             std::optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
     304       28289 :             if (piter) {
     305        2179 :                 staged_ancestors.insert(**piter);
     306        2179 :                 if (staged_ancestors.size() + 1 > limitAncestorCount) {
     307           0 :                     errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
     308           0 :                     return false;
     309             :                 }
     310        2179 :             }
     311       28289 :         }
     312       27840 :     } else {
     313             :         // If we're not searching for parents, we require this to already be an
     314             :         // entry in the mempool and use the entry's cached parents.
     315       24859 :         txiter it = mapTx.iterator_to(entry);
     316       24859 :         staged_ancestors = it->GetMemPoolParentsConst();
     317             :     }
     318             : 
     319       52699 :     return CalculateAncestorsAndCheckLimits(entry.GetTxSize(), /*entry_count=*/1,
     320       52699 :                                             setAncestors, staged_ancestors,
     321       52699 :                                             limitAncestorCount, limitAncestorSize,
     322       52699 :                                             limitDescendantCount, limitDescendantSize, errString);
     323       52699 : }
     324             : 
     325       51605 : void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors)
     326             : {
     327       51605 :     const CTxMemPoolEntry::Parents& parents = it->GetMemPoolParentsConst();
     328             :     // add or remove this tx as a child of each parent
     329       53807 :     for (const CTxMemPoolEntry& parent : parents) {
     330        2202 :         UpdateChild(mapTx.iterator_to(parent), it, add);
     331             :     }
     332       51605 :     const int64_t updateCount = (add ? 1 : -1);
     333       51605 :     const int64_t updateSize = updateCount * it->GetTxSize();
     334       51605 :     const CAmount updateFee = updateCount * it->GetModifiedFee();
     335     1060851 :     for (txiter ancestorIt : setAncestors) {
     336     2018492 :         mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e) { e.UpdateDescendantState(updateSize, updateFee, updateCount); });
     337             :     }
     338       51605 : }
     339             : 
     340       26904 : void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncestors)
     341             : {
     342       26904 :     int64_t updateCount = setAncestors.size();
     343       26904 :     int64_t updateSize = 0;
     344       26904 :     CAmount updateFee = 0;
     345       26904 :     int updateSigOps = 0;
     346     1036118 :     for (txiter ancestorIt : setAncestors) {
     347     1009214 :         updateSize += ancestorIt->GetTxSize();
     348     1009214 :         updateFee += ancestorIt->GetModifiedFee();
     349     1009214 :         updateSigOps += ancestorIt->GetSigOpCount();
     350             :     }
     351       53808 :     mapTx.modify(it, [=](CTxMemPoolEntry& e){ e.UpdateAncestorState(updateSize, updateFee, updateCount, updateSigOps); });
     352       26904 : }
     353             : 
     354       24701 : void CTxMemPool::UpdateChildrenForRemoval(txiter it)
     355             : {
     356       24701 :     const CTxMemPoolEntry::Children& children = it->GetMemPoolChildrenConst();
     357       24702 :     for (const CTxMemPoolEntry& updateIt : children) {
     358           1 :         UpdateParent(mapTx.iterator_to(updateIt), it, false);
     359             :     }
     360       24701 : }
     361             : 
     362       25121 : void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants)
     363             : {
     364             :     // For each entry, walk back all ancestors and decrement size associated with this
     365             :     // transaction
     366       25121 :     const uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
     367       25121 :     if (updateDescendants) {
     368             :         // updateDescendants should be true whenever we're not recursively
     369             :         // removing a tx and all its descendants, eg when a transaction is
     370             :         // confirmed in a block.
     371             :         // Here we only update statistics and not data in CTxMemPool::Parents
     372             :         // and CTxMemPoolEntry::Children (which we need to preserve until we're
     373             :         // finished with all operations that need to traverse the mempool).
     374       49204 :         for (txiter removeIt : entriesToRemove) {
     375       24602 :             setEntries setDescendants;
     376       24602 :             CalculateDescendants(removeIt, setDescendants);
     377       24602 :             setDescendants.erase(removeIt); // don't update state for self
     378       24602 :             int64_t modifySize = -((int64_t)removeIt->GetTxSize());
     379       24602 :             CAmount modifyFee = -removeIt->GetModifiedFee();
     380       24602 :             int modifySigOps = -removeIt->GetSigOpCount();
     381       24603 :             for (txiter dit : setDescendants) {
     382           2 :                 mapTx.modify(dit, [=](CTxMemPoolEntry& e){ e.UpdateAncestorState(modifySize, modifyFee, -1, modifySigOps); });
     383             :             }
     384       24602 :         }
     385       24602 :     }
     386       49822 :     for (txiter removeIt : entriesToRemove) {
     387       24701 :         setEntries setAncestors;
     388       24701 :         const CTxMemPoolEntry &entry = *removeIt;
     389       24701 :         std::string dummy;
     390             :         // Since this is a tx that is already in the mempool, we can call CMPA
     391             :         // with fSearchForParents = false.  If the mempool is in a consistent
     392             :         // state, then using true or false should both be correct, though false
     393             :         // should be a bit faster.
     394             :         // However, if we happen to be in the middle of processing a reorg, then
     395             :         // the mempool can be in an inconsistent state.  In this case, the set
     396             :         // of ancestors reachable via GetMemPoolParents()/GetMemPoolChildren()
     397             :         // will be the same as the set of ancestors whose packages include this
     398             :         // transaction, because when we add a new transaction to the mempool in
     399             :         // addUnchecked(), we assume it has no children, and in the case of a
     400             :         // reorg where that assumption is false, the in-mempool children aren't
     401             :         // linked to the in-block tx's until UpdateTransactionsFromBlock() is
     402             :         // called.
     403             :         // So if we're being called during a reorg, ie before
     404             :         // UpdateTransactionsFromBlock() has been called, then
     405             :         // GetMemPoolParents()/GetMemPoolChildren() will differ from the set of
     406             :         // mempool parents we'd calculate by searching, and it's important that
     407             :         // we use the cached notion of ancestor transactions as the set of
     408             :         // things to update for removal.
     409       24701 :         CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
     410             :         // Note that UpdateAncestorsOf severs the child links that point to
     411             :         // removeIt in the entries for the parents of removeIt.
     412       24701 :         UpdateAncestorsOf(false, removeIt, setAncestors);
     413       24701 :     }
     414             :     // After updating all the ancestor sizes, we can now sever the link between each
     415             :     // transaction being removed and any mempool children (ie, update CTxMemPoolEntry::m_parents
     416             :     // for each direct child of a transaction being removed).
     417       49822 :     for (txiter removeIt : entriesToRemove) {
     418       24701 :         UpdateChildrenForRemoval(removeIt);
     419             :     }
     420       25121 : }
     421             : 
     422     1009248 : void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount)
     423             : {
     424     1009248 :     nSizeWithDescendants += modifySize;
     425     1009248 :     assert(int64_t(nSizeWithDescendants) > 0);
     426     1009248 :     nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, modifyFee);
     427     1009248 :     nCountWithDescendants += modifyCount;
     428     1009248 :     assert(int64_t(nCountWithDescendants) > 0);
     429     1009248 : }
     430             : 
     431       26905 : void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps)
     432             : {
     433       26905 :     nSizeWithAncestors += modifySize;
     434       26905 :     assert(int64_t(nSizeWithAncestors) > 0);
     435       26905 :     nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, modifyFee);
     436       26905 :     nCountWithAncestors += modifyCount;
     437       26905 :     assert(int64_t(nCountWithAncestors) > 0);
     438       26905 :     nSigOpCountWithAncestors += modifySigOps;
     439       26905 :     assert(int(nSigOpCountWithAncestors) >= 0);
     440       26905 : }
     441             : 
     442       47558 : CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator, int check_ratio)
     443       23779 :     : m_check_ratio(check_ratio), minerPolicyEstimator(estimator)
     444       23779 : {
     445             :     _clear(); //lock free clear
     446       23779 : }
     447             : 
     448         184 : void CTxMemPool::ConnectManagers(gsl::not_null<CDeterministicMNManager*> dmnman, gsl::not_null<llmq::CInstantSendManager*> isman)
     449             : {
     450             :     // Do not allow double-initialization
     451         184 :     assert(m_dmnman.load(std::memory_order_acquire) == nullptr);
     452         184 :     m_dmnman.store(dmnman, std::memory_order_release);
     453         184 :     assert(m_isman.load(std::memory_order_acquire) == nullptr);
     454         184 :     m_isman.store(isman, std::memory_order_release);
     455         184 : }
     456             : 
     457         180 : void CTxMemPool::DisconnectManagers()
     458             : {
     459         180 :     m_dmnman.store(nullptr, std::memory_order_release);
     460         180 :     m_isman.store(nullptr, std::memory_order_release);
     461         180 : }
     462             : 
     463           0 : bool CTxMemPool::isSpent(const COutPoint& outpoint) const
     464             : {
     465           0 :     LOCK(cs);
     466           0 :     return mapNextTx.count(outpoint);
     467           0 : }
     468             : 
     469           0 : unsigned int CTxMemPool::GetTransactionsUpdated() const
     470             : {
     471           0 :     return nTransactionsUpdated;
     472             : }
     473             : 
     474       24958 : void CTxMemPool::AddTransactionsUpdated(unsigned int n)
     475             : {
     476       24958 :     nTransactionsUpdated += n;
     477       24958 : }
     478             : 
     479       26904 : void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate)
     480             : {
     481             :     // Add to memory pool without checking anything.
     482             :     // Used by AcceptToMemoryPool(), which DOES do
     483             :     // all the appropriate checks.
     484       26904 :     indexed_transaction_set::iterator newit = mapTx.emplace(CTxMemPoolEntry::ExplicitCopy, entry).first;
     485             : 
     486             :     // Update transaction for any feeDelta created by PrioritiseTransaction
     487       26904 :     CAmount delta{0};
     488       26904 :     ApplyDelta(entry.GetTx().GetHash(), delta);
     489             :     // The following call to UpdateModifiedFee assumes no previous fee modifications
     490       26904 :     Assume(entry.GetFee() == entry.GetModifiedFee());
     491       26904 :     if (delta) {
     492           2 :         mapTx.modify(newit, [&delta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(delta); });
     493           1 :     }
     494             : 
     495             :     // Update cachedInnerUsage to include contained transaction's usage.
     496             :     // (When we update the entry for in-mempool parents, memory usage will be
     497             :     // further updated.)
     498       26904 :     cachedInnerUsage += entry.DynamicMemoryUsage();
     499             : 
     500       26904 :     const CTransaction& tx = newit->GetTx();
     501       26904 :     std::set<uint256> setParentTransactions;
     502       53830 :     for (unsigned int i = 0; i < tx.vin.size(); i++) {
     503       26926 :         mapNextTx.insert(std::make_pair(&tx.vin[i].prevout, &tx));
     504       26926 :         setParentTransactions.insert(tx.vin[i].prevout.hash);
     505       26926 :     }
     506             :     // Don't bother worrying about child transactions of this one.
     507             :     // Normal case of a new transaction arriving is that there can't be any
     508             :     // children, because such children would be orphans.
     509             :     // An exception to that is if a transaction enters that used to be in a block.
     510             :     // In that case, our disconnect block logic will call UpdateTransactionsFromBlock
     511             :     // to clean up the mess we're leaving here.
     512             : 
     513             :     // Update ancestors with information about this tx
     514       29085 :     for (const auto& pit : GetIterSet(setParentTransactions)) {
     515        2181 :             UpdateParent(newit, pit, true);
     516             :     }
     517       26904 :     UpdateAncestorsOf(true, newit, setAncestors);
     518       26904 :     UpdateEntryForAncestors(newit, setAncestors);
     519             : 
     520       26904 :     nTransactionsUpdated++;
     521       26904 :     totalTxSize += entry.GetTxSize();
     522       26904 :     m_total_fee += entry.GetFee();
     523       26904 :     if (minerPolicyEstimator) {
     524       26898 :         minerPolicyEstimator->processTransaction(entry, validFeeEstimate);
     525       26898 :     }
     526             : 
     527       26904 :     vTxHashes.emplace_back(entry.GetTx().GetHash(), newit);
     528       26904 :     newit->vTxHashesIdx = vTxHashes.size() - 1;
     529             : 
     530             :     // Invalid ProTxes should never get this far because transactions should be
     531             :     // fully checked by AcceptToMemoryPool() at this point, so we just assume that
     532             :     // everything is fine here.
     533       26904 :     if (auto dmnman = m_dmnman.load(std::memory_order_acquire); dmnman) {
     534        2304 :         addUncheckedProTx(*dmnman, newit, tx);
     535        2304 :     }
     536       26904 : }
     537             : 
     538          78 : void CTxMemPool::addAddressIndex(const CTxMemPoolEntry& entry, const CCoinsViewCache& view)
     539             : {
     540          78 :     if (!g_addressindex) return;
     541             : 
     542           0 :     LOCK(cs);
     543           0 :     const CTransaction& tx = entry.GetTx();
     544           0 :     std::vector<CMempoolAddressDeltaKey> inserted;
     545             : 
     546           0 :     uint256 txhash = tx.GetHash();
     547           0 :     for (unsigned int j = 0; j < tx.vin.size(); j++) {
     548           0 :         const CTxIn input = tx.vin[j];
     549           0 :         const Coin& coin = view.AccessCoin(input.prevout);
     550           0 :         const CTxOut &prevout = coin.out;
     551             : 
     552           0 :         AddressType address_type{AddressType::UNKNOWN};
     553           0 :         uint160 address_bytes;
     554             : 
     555           0 :         if (!AddressBytesFromScript(prevout.scriptPubKey, address_type, address_bytes)) {
     556           0 :             continue;
     557             :         }
     558             : 
     559           0 :         CMempoolAddressDeltaKey key(address_type, address_bytes, txhash, j, /* tx_spent */ true);
     560           0 :         CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n);
     561           0 :         mapAddress.insert(std::make_pair(key, delta));
     562           0 :         inserted.push_back(key);
     563           0 :     }
     564             : 
     565           0 :     for (unsigned int k = 0; k < tx.vout.size(); k++) {
     566           0 :         const CTxOut &out = tx.vout[k];
     567             : 
     568           0 :         AddressType address_type{AddressType::UNKNOWN};
     569           0 :         uint160 address_bytes;
     570             : 
     571           0 :         if (!AddressBytesFromScript(out.scriptPubKey, address_type, address_bytes)) {
     572           0 :             continue;
     573             :         }
     574             : 
     575           0 :         CMempoolAddressDeltaKey key(address_type, address_bytes, txhash, k, /* tx_spent */ false);
     576           0 :         mapAddress.insert(std::make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue)));
     577           0 :         inserted.push_back(key);
     578           0 :     }
     579             : 
     580           0 :     mapAddressInserted.insert(std::make_pair(txhash, inserted));
     581          78 : }
     582             : 
     583           0 : void CTxMemPool::getAddressIndex(const std::vector<CMempoolAddressDeltaKey>& addresses,
     584             :                                  std::vector<CMempoolAddressDeltaEntry>& results) const
     585             : {
     586           0 :     LOCK(cs);
     587           0 :     for (const auto& address : addresses) {
     588           0 :         auto ait = mapAddress.lower_bound(address);
     589           0 :         while (ait != mapAddress.end() && (*ait).first.m_address_bytes == address.m_address_bytes
     590           0 :                && (*ait).first.m_address_type == address.m_address_type) {
     591           0 :             results.push_back(*ait);
     592           0 :             ait++;
     593             :         }
     594             :     }
     595           0 : }
     596             : 
     597       24701 : void CTxMemPool::removeAddressIndex(const uint256 txhash)
     598             : {
     599       24701 :     LOCK(cs);
     600       24701 :     if (auto it = mapAddressInserted.find(txhash); it != mapAddressInserted.end()) {
     601           0 :         for (const auto& key : (*it).second) {
     602           0 :             mapAddress.erase(key);
     603             :         }
     604           0 :         mapAddressInserted.erase(it);
     605           0 :     }
     606       24701 : }
     607             : 
     608          78 : void CTxMemPool::addSpentIndex(const CTxMemPoolEntry& entry, const CCoinsViewCache& view)
     609             : {
     610          78 :     if (!g_spentindex) return;
     611             : 
     612           0 :     LOCK(cs);
     613             : 
     614           0 :     const CTransaction& tx = entry.GetTx();
     615           0 :     std::vector<CSpentIndexKey> inserted;
     616             : 
     617           0 :     uint256 txhash = tx.GetHash();
     618           0 :     for (unsigned int j = 0; j < tx.vin.size(); j++) {
     619           0 :         const CTxIn input = tx.vin[j];
     620           0 :         const Coin& coin = view.AccessCoin(input.prevout);
     621           0 :         const CTxOut &prevout = coin.out;
     622             : 
     623           0 :         AddressType address_type{AddressType::UNKNOWN};
     624           0 :         uint160 address_bytes;
     625             : 
     626           0 :         if (!AddressBytesFromScript(prevout.scriptPubKey, address_type, address_bytes)) {
     627           0 :             continue;
     628             :         }
     629             : 
     630           0 :         CSpentIndexKey key = CSpentIndexKey(input.prevout.hash, input.prevout.n);
     631           0 :         CSpentIndexValue value = CSpentIndexValue(txhash, j, -1, prevout.nValue, address_type, address_bytes);
     632             : 
     633           0 :         mapSpent.insert(std::make_pair(key, value));
     634           0 :         inserted.push_back(key);
     635           0 :     }
     636             : 
     637           0 :     mapSpentInserted.insert(make_pair(txhash, inserted));
     638          78 : }
     639             : 
     640           0 : bool CTxMemPool::getSpentIndex(const CSpentIndexKey& key, CSpentIndexValue& value) const
     641             : {
     642           0 :     LOCK(cs);
     643           0 :     if (auto it = mapSpent.find(key); it != mapSpent.end()) {
     644           0 :         value = it->second;
     645           0 :         return true;
     646             :     }
     647           0 :     return false;
     648           0 : }
     649             : 
     650       24701 : void CTxMemPool::removeSpentIndex(const uint256 txhash)
     651             : {
     652       24701 :     LOCK(cs);
     653       24701 :     if (auto it = mapSpentInserted.find(txhash); it != mapSpentInserted.end()) {
     654           0 :         for (const auto& key : (*it).second) {
     655           0 :             mapSpent.erase(key);
     656             :         }
     657           0 :         mapSpentInserted.erase(it);
     658           0 :     }
     659       24701 : }
     660             : 
     661        2304 : void CTxMemPool::addUncheckedProTx(CDeterministicMNManager& dmnman, indexed_transaction_set::iterator& newit,
     662             :                                    const CTransaction& tx)
     663             : {
     664        2304 :     const uint256 tx_hash{tx.GetHash()};
     665        2304 :     if (tx.nType == TRANSACTION_PROVIDER_REGISTER) {
     666           4 :         auto proTx = *Assert(GetTxPayload<CProRegTx>(tx));
     667           4 :         if (!proTx.collateralOutpoint.hash.IsNull()) {
     668           2 :             mapProTxRefs.emplace(tx_hash, proTx.collateralOutpoint.hash);
     669           2 :         }
     670           8 :         for (const auto& entry : proTx.netInfo->GetEntries()) {
     671           4 :             mapProTxAddresses.emplace(entry, tx_hash);
     672             :         }
     673           4 :         mapProTxPubKeyIDs.emplace(proTx.keyIDOwner, tx_hash);
     674           4 :         mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx_hash);
     675           4 :         if (!proTx.collateralOutpoint.hash.IsNull()) {
     676           2 :             mapProTxCollaterals.emplace(proTx.collateralOutpoint, tx_hash);
     677           2 :         } else {
     678           2 :             mapProTxCollaterals.emplace(COutPoint(tx_hash, proTx.collateralOutpoint.n), tx_hash);
     679             :         }
     680        2304 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
     681           2 :         auto proTx = *Assert(GetTxPayload<CProUpServTx>(tx));
     682           2 :         mapProTxRefs.emplace(proTx.proTxHash, tx_hash);
     683           4 :         for (const auto& entry : proTx.netInfo->GetEntries()) {
     684           2 :             mapProTxAddresses.emplace(entry, tx_hash);
     685             :         }
     686        2300 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
     687           0 :         auto proTx = *Assert(GetTxPayload<CProUpRegTx>(tx));
     688           0 :         mapProTxRefs.emplace(proTx.proTxHash, tx_hash);
     689           0 :         mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx_hash);
     690           0 :         auto dmn = Assert(dmnman.GetListAtChainTip().GetMN(proTx.proTxHash));
     691           0 :         newit->validForProTxKey = ::SerializeHash(dmn->pdmnState->pubKeyOperator);
     692           0 :         if (dmn->pdmnState->pubKeyOperator != proTx.pubKeyOperator) {
     693           0 :             newit->isKeyChangeProTx = true;
     694           0 :         }
     695        2298 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) {
     696           0 :         auto proTx = *Assert(GetTxPayload<CProUpRevTx>(tx));
     697           0 :         mapProTxRefs.emplace(proTx.proTxHash, tx_hash);
     698           0 :         auto dmn = Assert(dmnman.GetListAtChainTip().GetMN(proTx.proTxHash));
     699           0 :         newit->validForProTxKey = ::SerializeHash(dmn->pdmnState->pubKeyOperator);
     700           0 :         if (dmn->pdmnState->pubKeyOperator.Get() != CBLSPublicKey()) {
     701           0 :             newit->isKeyChangeProTx = true;
     702           0 :         }
     703        2298 :     } else if (tx.nType == TRANSACTION_ASSET_UNLOCK) {
     704           0 :         auto assetUnlockTx = *Assert(GetTxPayload<CAssetUnlockPayload>(tx));
     705           0 :         mapAssetUnlockExpiry.insert({tx_hash, assetUnlockTx.getHeightToExpiry()});
     706        2298 :     } else if (tx.nType == TRANSACTION_MNHF_SIGNAL) {
     707           0 :         PrioritiseTransaction(tx_hash, 0.1 * COIN);
     708           0 :     }
     709        2304 : }
     710             : 
     711       24701 : void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
     712             : {
     713             :     // We increment mempool sequence value no matter removal reason
     714             :     // even if not directly reported below.
     715       24701 :     uint64_t mempool_sequence = GetAndIncrementSequence();
     716             : 
     717       24701 :     if (reason != MemPoolRemovalReason::BLOCK) {
     718             :         // Notify clients that a transaction has been removed from the mempool
     719             :         // for any reason except being included in a block. Clients interested
     720             :         // in transactions included in blocks can subscribe to the BlockConnected
     721             :         // notification.
     722          99 :         GetMainSignals().TransactionRemovedFromMempool(it->GetSharedTx(), reason, mempool_sequence);
     723          99 :     }
     724             : 
     725       24701 :     const uint256 hash = it->GetTx().GetHash();
     726       49419 :     for (const CTxIn& txin : it->GetTx().vin)
     727       24718 :         mapNextTx.erase(txin.prevout);
     728             : 
     729       24701 :     RemoveUnbroadcastTx(hash, true /* add logging because unchecked */ );
     730             : 
     731       24701 :     if (vTxHashes.size() > 1) {
     732       24268 :         vTxHashes[it->vTxHashesIdx] = std::move(vTxHashes.back());
     733       24268 :         vTxHashes[it->vTxHashesIdx].second->vTxHashesIdx = it->vTxHashesIdx;
     734       24268 :         vTxHashes.pop_back();
     735       24268 :         if (vTxHashes.size() * 2 < vTxHashes.capacity())
     736        2208 :             vTxHashes.shrink_to_fit();
     737       24268 :     } else
     738         433 :         vTxHashes.clear();
     739             : 
     740       24701 :     if (m_dmnman.load(std::memory_order_acquire)) {
     741         101 :         removeUncheckedProTx(it->GetTx());
     742         101 :     }
     743             : 
     744       24701 :     totalTxSize -= it->GetTxSize();
     745       24701 :     m_total_fee -= it->GetFee();
     746       24701 :     cachedInnerUsage -= it->DynamicMemoryUsage();
     747       24701 :     cachedInnerUsage -= memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst());
     748       24701 :     mapTx.erase(it);
     749       24701 :     nTransactionsUpdated++;
     750       24701 :     if (minerPolicyEstimator) {minerPolicyEstimator->removeTx(hash, false);}
     751       24701 :     removeAddressIndex(hash);
     752       24701 :     removeSpentIndex(hash);
     753       24701 : }
     754             : 
     755         101 : void CTxMemPool::removeUncheckedProTx(const CTransaction& tx)
     756             : {
     757         105 :     auto eraseProTxRef = [&](const uint256& proTxHash, const uint256& txHash) {
     758           4 :         auto its = mapProTxRefs.equal_range(proTxHash);
     759           8 :         for (auto it = its.first; it != its.second;) {
     760           4 :             if (it->second == txHash) {
     761           2 :                 it = mapProTxRefs.erase(it);
     762           2 :             } else {
     763           2 :                 ++it;
     764             :             }
     765             :         }
     766           4 :     };
     767             : 
     768         101 :     const uint256 tx_hash{tx.GetHash()};
     769         101 :     if (tx.nType == TRANSACTION_PROVIDER_REGISTER) {
     770           2 :         auto proTx = *Assert(GetTxPayload<CProRegTx>(tx));
     771           2 :         if (!proTx.collateralOutpoint.IsNull()) {
     772           2 :             eraseProTxRef(tx_hash, proTx.collateralOutpoint.hash);
     773           2 :         }
     774           4 :         for (const auto& entry : proTx.netInfo->GetEntries()) {
     775           2 :             mapProTxAddresses.erase(entry);
     776             :         }
     777           2 :         mapProTxPubKeyIDs.erase(proTx.keyIDOwner);
     778           2 :         mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash());
     779           2 :         mapProTxCollaterals.erase(proTx.collateralOutpoint);
     780           2 :         mapProTxCollaterals.erase(COutPoint(tx_hash, proTx.collateralOutpoint.n));
     781         101 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
     782           2 :         auto proTx = *Assert(GetTxPayload<CProUpServTx>(tx));
     783           2 :         eraseProTxRef(proTx.proTxHash, tx_hash);
     784           4 :         for (const auto& entry : proTx.netInfo->GetEntries()) {
     785           2 :             mapProTxAddresses.erase(entry);
     786             :         }
     787          99 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
     788           0 :         auto proTx = *Assert(GetTxPayload<CProUpRegTx>(tx));
     789           0 :         eraseProTxRef(proTx.proTxHash, tx_hash);
     790           0 :         mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash());
     791          97 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) {
     792           0 :         auto proTx = *Assert(GetTxPayload<CProUpRevTx>(tx));
     793           0 :         eraseProTxRef(proTx.proTxHash, tx_hash);
     794          97 :     } else if (tx.nType == TRANSACTION_ASSET_UNLOCK) {
     795           0 :         mapAssetUnlockExpiry.erase(tx_hash);
     796           0 :     }
     797         101 : }
     798             : 
     799             : // Calculates descendants of entry that are not already in setDescendants, and adds to
     800             : // setDescendants. Assumes entryit is already a tx in the mempool and CTxMemPoolEntry::m_children
     801             : // is correct for tx and all descendants.
     802             : // Also assumes that if an entry is in setDescendants already, then all
     803             : // in-mempool descendants of it are already in setDescendants as well, so that we
     804             : // can save time by not iterating over those entries.
     805       26730 : void CTxMemPool::CalculateDescendants(txiter entryit, setEntries& setDescendants) const
     806             : {
     807       26730 :     setEntries stage;
     808       26730 :     if (setDescendants.count(entryit) == 0) {
     809       26730 :         stage.insert(entryit);
     810       26730 :     }
     811             :     // Traverse down the children of entry, only adding children that are not
     812             :     // accounted for in setDescendants already (because those children have either
     813             :     // already been walked, or will be walked in this iteration).
     814     1054482 :     while (!stage.empty()) {
     815     1027752 :         txiter it = *stage.begin();
     816     1027752 :         setDescendants.insert(it);
     817     1027752 :         stage.erase(it);
     818             : 
     819     1027752 :         const CTxMemPoolEntry::Children& children = it->GetMemPoolChildrenConst();
     820     2028774 :         for (const CTxMemPoolEntry& child : children) {
     821     1001022 :             txiter childiter = mapTx.iterator_to(child);
     822     1001022 :             if (!setDescendants.count(childiter)) {
     823     1001022 :                 stage.insert(childiter);
     824     1001022 :             }
     825             :         }
     826             :     }
     827       26730 : }
     828             : 
     829         403 : void CTxMemPool::removeRecursive(const CTransaction &origTx, MemPoolRemovalReason reason)
     830             : {
     831             :     // Remove transaction from memory pool
     832         403 :     AssertLockHeld(cs);
     833         403 :         setEntries txToRemove;
     834         403 :         txiter origit = mapTx.find(origTx.GetHash());
     835         403 :         if (origit != mapTx.end()) {
     836          12 :             txToRemove.insert(origit);
     837          12 :         } else {
     838             :             // When recursively removing but origTx isn't in the mempool
     839             :             // be sure to remove any children that are in the pool. This can
     840             :             // happen during chain re-orgs if origTx isn't re-accepted into
     841             :             // the mempool for any reason.
     842        1157 :             for (unsigned int i = 0; i < origTx.vout.size(); i++) {
     843         766 :                 auto it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
     844         766 :                 if (it == mapNextTx.end())
     845         697 :                     continue;
     846          69 :                 txiter nextit = mapTx.find(it->second->GetHash());
     847          69 :                 assert(nextit != mapTx.end());
     848          69 :                 txToRemove.insert(nextit);
     849          69 :             }
     850             :         }
     851         403 :         setEntries setAllRemoves;
     852         484 :         for (txiter it : txToRemove) {
     853          81 :             CalculateDescendants(it, setAllRemoves);
     854             :         }
     855             : 
     856         403 :         RemoveStaged(setAllRemoves, false, reason);
     857         403 : }
     858             : 
     859          17 : void CTxMemPool::removeForReorg(CChain& chain, std::function<bool(txiter)> check_final_and_mature) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
     860             : {
     861             :     // Remove transactions spending a coinbase which are now immature and no-longer-final transactions
     862          17 :     AssertLockHeld(cs);
     863          17 :     AssertLockHeld(::cs_main);
     864             : 
     865          17 :     setEntries txToRemove;
     866          21 :     for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
     867           4 :         if (check_final_and_mature(it)) txToRemove.insert(it);
     868           4 :     }
     869          17 :     setEntries setAllRemoves;
     870          18 :     for (txiter it : txToRemove) {
     871           1 :         CalculateDescendants(it, setAllRemoves);
     872             :     }
     873          17 :     RemoveStaged(setAllRemoves, false, MemPoolRemovalReason::REORG);
     874          20 :     for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
     875           3 :         assert(TestLockPointValidity(chain, it->GetLockPoints()));
     876           3 :     }
     877          17 : }
     878             : 
     879       63710 : void CTxMemPool::removeConflicts(const CTransaction &tx)
     880             : {
     881             :     // Remove transactions which depend on inputs of tx, recursively
     882       63710 :     AssertLockHeld(cs);
     883      113031 :     for (const CTxIn &txin : tx.vin) {
     884       49321 :         auto it = mapNextTx.find(txin.prevout);
     885       49321 :         if (it != mapNextTx.end()) {
     886           2 :             const CTransaction &txConflict = *it->second;
     887           2 :             if (txConflict != tx)
     888             :             {
     889           2 :                 if (txConflict.nType == TRANSACTION_PROVIDER_REGISTER) {
     890             :                     // Remove all other protxes which refer to this protx
     891             :                     // NOTE: Can't use equal_range here as every call to removeRecursive might invalidate iterators
     892           6 :                     while (true) {
     893           6 :                         auto itPro = mapProTxRefs.find(txConflict.GetHash());
     894           6 :                         if (itPro == mapProTxRefs.end()) {
     895           2 :                             break;
     896             :                         }
     897           4 :                         auto txit = mapTx.find(itPro->second);
     898           4 :                         if (txit != mapTx.end()) {
     899           2 :                             ClearPrioritisation(txit->GetTx().GetHash());
     900           2 :                             removeRecursive(txit->GetTx(), MemPoolRemovalReason::CONFLICT);
     901           2 :                         } else {
     902           2 :                             mapProTxRefs.erase(itPro);
     903             :                         }
     904             :                     }
     905           2 :                 }
     906           2 :                 ClearPrioritisation(txConflict.GetHash());
     907           2 :                 removeRecursive(txConflict, MemPoolRemovalReason::CONFLICT);
     908           2 :             }
     909           2 :         }
     910             :     }
     911       63710 : }
     912             : 
     913          34 : void CTxMemPool::removeProTxPubKeyConflicts(const CTransaction &tx, const CKeyID &keyId)
     914             : {
     915          34 :     if (mapProTxPubKeyIDs.count(keyId)) {
     916           0 :         uint256 conflictHash = mapProTxPubKeyIDs[keyId];
     917           0 :         if (conflictHash != tx.GetHash() && mapTx.count(conflictHash)) {
     918           0 :             removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
     919           0 :         }
     920           0 :     }
     921          34 : }
     922             : 
     923          37 : void CTxMemPool::removeProTxPubKeyConflicts(const CTransaction &tx, const CBLSLazyPublicKey &pubKey)
     924             : {
     925          37 :     if (mapProTxBlsPubKeyHashes.count(pubKey.GetHash())) {
     926           0 :         uint256 conflictHash = mapProTxBlsPubKeyHashes[pubKey.GetHash()];
     927           0 :         if (conflictHash != tx.GetHash() && mapTx.count(conflictHash)) {
     928           0 :             removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
     929           0 :         }
     930           0 :     }
     931          37 : }
     932             : 
     933          34 : void CTxMemPool::removeProTxCollateralConflicts(const CTransaction &tx, const COutPoint &collateralOutpoint)
     934             : {
     935          34 :     if (mapProTxCollaterals.count(collateralOutpoint)) {
     936           0 :         uint256 conflictHash = mapProTxCollaterals[collateralOutpoint];
     937           0 :         if (conflictHash != tx.GetHash() && mapTx.count(conflictHash)) {
     938           0 :             removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
     939           0 :         }
     940           0 :     }
     941          34 : }
     942             : 
     943       39110 : void CTxMemPool::removeProTxSpentCollateralConflicts(const CTransaction &tx)
     944             : {
     945       39110 :     auto dmnman = Assert(m_dmnman.load(std::memory_order_acquire));
     946             : 
     947             :     // Remove TXs that refer to a MN for which the collateral was spent
     948       39112 :     auto removeSpentCollateralConflict = [&](const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(cs) {
     949             :         // Can't use equal_range here as every call to removeRecursive might invalidate iterators
     950           2 :         AssertLockHeld(cs);
     951           2 :         while (true) {
     952           2 :             auto it = mapProTxRefs.find(proTxHash);
     953           2 :             if (it == mapProTxRefs.end()) {
     954           2 :                 break;
     955             :             }
     956           0 :             auto conflictIt = mapTx.find(it->second);
     957           0 :             if (conflictIt != mapTx.end()) {
     958           0 :                 removeRecursive(conflictIt->GetTx(), MemPoolRemovalReason::CONFLICT);
     959           0 :             } else {
     960             :                 // Should not happen as we track referencing TXs in addUnchecked/removeUnchecked.
     961             :                 // But lets be on the safe side and not run into an endless loop...
     962           0 :                 LogPrint(BCLog::MEMPOOL, "%s: ERROR: found invalid TX ref in mapProTxRefs, proTxHash=%s, txHash=%s\n", __func__, proTxHash.ToString(), it->second.ToString());
     963           0 :                 mapProTxRefs.erase(it);
     964             :             }
     965             :         }
     966           2 :     };
     967       39110 :     auto mnList = dmnman->GetListAtChainTip();
     968       63831 :     for (const auto& in : tx.vin) {
     969       24721 :         auto collateralIt = mapProTxCollaterals.find(in.prevout);
     970       24721 :         if (collateralIt != mapProTxCollaterals.end()) {
     971             :             // These are not yet mined ProRegTxs
     972           0 :             removeSpentCollateralConflict(collateralIt->second);
     973           0 :         }
     974       24721 :         auto dmn = mnList.GetMNByCollateral(in.prevout);
     975       24721 :         if (dmn) {
     976             :             // These are updates referring to a mined ProRegTx
     977           2 :             removeSpentCollateralConflict(dmn->proTxHash);
     978           2 :         }
     979       24721 :     }
     980       39110 : }
     981             : 
     982           6 : void CTxMemPool::removeProTxKeyChangedConflicts(const CTransaction &tx, const uint256& proTxHash, const uint256& newKeyHash)
     983             : {
     984           6 :     std::set<uint256> conflictingTxs;
     985           6 :     for (auto its = mapProTxRefs.equal_range(proTxHash); its.first != its.second; ++its.first) {
     986           0 :         auto txit = mapTx.find(its.first->second);
     987           0 :         if (txit == mapTx.end()) {
     988           0 :             continue;
     989             :         }
     990           0 :         if (txit->validForProTxKey != newKeyHash) {
     991           0 :             conflictingTxs.emplace(txit->GetTx().GetHash());
     992           0 :         }
     993           0 :     }
     994           6 :     for (const auto& txHash : conflictingTxs) {
     995           0 :         auto& tx = mapTx.find(txHash)->GetTx();
     996           0 :         removeRecursive(tx, MemPoolRemovalReason::CONFLICT);
     997             :     }
     998           6 : }
     999             : 
    1000       39110 : void CTxMemPool::removeProTxConflicts(const CTransaction &tx)
    1001             : {
    1002       39110 :     removeProTxSpentCollateralConflicts(tx);
    1003             : 
    1004       39110 :     const uint256 tx_hash{tx.GetHash()};
    1005       39110 :     if (tx.nType == TRANSACTION_PROVIDER_REGISTER) {
    1006          34 :         const auto opt_proTx = GetTxPayload<CProRegTx>(tx);
    1007          34 :         if (!opt_proTx) {
    1008           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString());
    1009           0 :             return;
    1010             :         }
    1011          34 :         auto& proTx = *opt_proTx;
    1012             : 
    1013          68 :         for (const auto& entry : proTx.netInfo->GetEntries()) {
    1014          34 :             if (mapProTxAddresses.count(entry)) {
    1015           0 :                 uint256 conflictHash = mapProTxAddresses[entry];
    1016           0 :                 if (conflictHash != tx_hash && mapTx.count(conflictHash)) {
    1017           0 :                     removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
    1018           0 :                 }
    1019           0 :             }
    1020             :         }
    1021          34 :         removeProTxPubKeyConflicts(tx, proTx.keyIDOwner);
    1022          34 :         removeProTxPubKeyConflicts(tx, proTx.pubKeyOperator);
    1023          34 :         if (!proTx.collateralOutpoint.hash.IsNull()) {
    1024           1 :             removeProTxCollateralConflicts(tx, proTx.collateralOutpoint);
    1025           1 :         } else {
    1026          33 :             removeProTxCollateralConflicts(tx, COutPoint(tx_hash, proTx.collateralOutpoint.n));
    1027             :         }
    1028       39110 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
    1029           4 :         const auto opt_proTx = GetTxPayload<CProUpServTx>(tx);
    1030           4 :         if (!opt_proTx) {
    1031           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString());
    1032           0 :             return;
    1033             :         }
    1034             : 
    1035           8 :         for (const auto& entry : opt_proTx->netInfo->GetEntries()) {
    1036           4 :             if (mapProTxAddresses.count(entry)) {
    1037           0 :                 uint256 conflictHash = mapProTxAddresses[entry];
    1038           0 :                 if (conflictHash != tx_hash && mapTx.count(conflictHash)) {
    1039           0 :                     removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
    1040           0 :                 }
    1041           0 :             }
    1042             :         }
    1043       39076 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
    1044           3 :         const auto opt_proTx = GetTxPayload<CProUpRegTx>(tx);
    1045           3 :         if (!opt_proTx) {
    1046           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString());
    1047           0 :             return;
    1048             :         }
    1049             : 
    1050           3 :         removeProTxPubKeyConflicts(tx, opt_proTx->pubKeyOperator);
    1051           3 :         removeProTxKeyChangedConflicts(tx, opt_proTx->proTxHash, ::SerializeHash(opt_proTx->pubKeyOperator));
    1052       39072 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) {
    1053           3 :         const auto opt_proTx = GetTxPayload<CProUpRevTx>(tx);
    1054           3 :         if (!opt_proTx) {
    1055           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString());
    1056           0 :             return;
    1057             :         }
    1058             : 
    1059           3 :         removeProTxKeyChangedConflicts(tx, opt_proTx->proTxHash, ::SerializeHash(CBLSPublicKey()));
    1060           3 :     }
    1061       39110 : }
    1062             : 
    1063             : /**
    1064             :  * Called when a block is connected. Removes from mempool and updates the miner fee estimator.
    1065             :  */
    1066       25242 : void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight)
    1067             : {
    1068       25242 :     AssertLockHeld(cs);
    1069       25242 :     std::vector<const CTxMemPoolEntry*> entries;
    1070       88952 :     for (const auto& tx : vtx)
    1071             :     {
    1072       63710 :         uint256 hash = tx->GetHash();
    1073             : 
    1074       63710 :         indexed_transaction_set::iterator i = mapTx.find(hash);
    1075       63710 :         if (i != mapTx.end())
    1076       24602 :             entries.push_back(&*i);
    1077             :     }
    1078             :     // Before the txs in the new block have been removed from the mempool, update policy estimates
    1079       25242 :     if (minerPolicyEstimator) {minerPolicyEstimator->processBlock(nBlockHeight, entries);}
    1080       88952 :     for (const auto& tx : vtx)
    1081             :     {
    1082       63710 :         txiter it = mapTx.find(tx->GetHash());
    1083       63710 :         if (it != mapTx.end()) {
    1084       24602 :             setEntries stage;
    1085       24602 :             stage.insert(it);
    1086       24602 :             RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK);
    1087       24602 :         }
    1088       63710 :         removeConflicts(*tx);
    1089       63710 :         if (m_dmnman.load(std::memory_order_acquire)) {
    1090       39110 :             removeProTxConflicts(*tx);
    1091       39110 :         }
    1092       63710 :         ClearPrioritisation(tx->GetHash());
    1093             :     }
    1094       25242 :     lastRollingFeeUpdate = GetTime();
    1095       25242 :     blockSinceLastRollingFeeBump = true;
    1096       25242 : }
    1097             : 
    1098             : /**
    1099             :   * Called when a length of chain is increased. Removes from mempool expired asset-unlock transactions
    1100             :   */
    1101       24572 : void CTxMemPool::removeExpiredAssetUnlock(int nBlockHeight)
    1102             : {
    1103       24572 :     AssertLockHeld(cs);
    1104             :     // items to removed should be firstly collected to independent list,
    1105             :     // because removing items by `removeRecursive` changes the mapAssetUnlockExpiry
    1106       24572 :     std::vector<CTransactionRef> entries;
    1107       24572 :     for (const auto& item: mapAssetUnlockExpiry) {
    1108           0 :         if (item.second < nBlockHeight) {
    1109           0 :             entries.push_back(get(item.first));
    1110           0 :         }
    1111             :     }
    1112       24572 :     for (const auto& tx : entries) {
    1113           0 :         removeRecursive(*tx, MemPoolRemovalReason::EXPIRY);
    1114             :     }
    1115       24572 : }
    1116             : 
    1117       23791 : void CTxMemPool::_clear()
    1118             : {
    1119       23791 :     vTxHashes.clear();
    1120       23791 :     mapTx.clear();
    1121       23791 :     mapNextTx.clear();
    1122       23791 :     mapProTxAddresses.clear();
    1123       23791 :     mapProTxPubKeyIDs.clear();
    1124       23791 :     totalTxSize = 0;
    1125       23791 :     m_total_fee = 0;
    1126       23791 :     cachedInnerUsage = 0;
    1127       23791 :     lastRollingFeeUpdate = GetTime();
    1128       23791 :     blockSinceLastRollingFeeBump = false;
    1129       23791 :     rollingMinimumFeeRate = 0;
    1130       23791 :     ++nTransactionsUpdated;
    1131       23791 : }
    1132             : 
    1133          12 : void CTxMemPool::clear()
    1134             : {
    1135          12 :     LOCK(cs);
    1136          12 :     _clear();
    1137          12 : }
    1138             : 
    1139       24273 : void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendheight) const
    1140             : {
    1141       24273 :     if (m_check_ratio == 0) return;
    1142             : 
    1143       24273 :     if (GetRand(m_check_ratio) >= 1) return;
    1144             : 
    1145       24273 :     AssertLockHeld(::cs_main);
    1146       24273 :     LOCK(cs);
    1147       24273 :     LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
    1148             : 
    1149       24273 :     uint64_t checkTotal = 0;
    1150       24273 :     CAmount check_total_fee{0};
    1151       24273 :     uint64_t innerUsage = 0;
    1152       24273 :     uint64_t prev_ancestor_count{0};
    1153             : 
    1154       24273 :     CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
    1155             : 
    1156       25045 :     for (const auto& it : GetSortedDepthAndScore()) {
    1157         772 :         checkTotal += it->GetTxSize();
    1158         772 :         check_total_fee += it->GetFee();
    1159         772 :         innerUsage += it->DynamicMemoryUsage();
    1160         772 :         const CTransaction& tx = it->GetTx();
    1161         772 :         innerUsage += memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst());
    1162         772 :         CTxMemPoolEntry::Parents setParentCheck;
    1163        1544 :         for (const CTxIn &txin : tx.vin) {
    1164             :             // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
    1165         772 :             indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
    1166         772 :             if (it2 != mapTx.end()) {
    1167           0 :                 const CTransaction& tx2 = it2->GetTx();
    1168           0 :                 assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
    1169           0 :                 setParentCheck.insert(*it2);
    1170           0 :             }
    1171             :             // We are iterating through the mempool entries sorted in order by ancestor count.
    1172             :             // All parents must have been checked before their children and their coins added to
    1173             :             // the mempoolDuplicate coins cache.
    1174         772 :             assert(mempoolDuplicate.HaveCoin(txin.prevout));
    1175             :             // Check whether its inputs are marked in mapNextTx.
    1176         772 :             auto it3 = mapNextTx.find(txin.prevout);
    1177         772 :             assert(it3 != mapNextTx.end());
    1178         772 :             assert(it3->first == &txin.prevout);
    1179         772 :             assert(it3->second == &tx);
    1180             :         }
    1181         772 :         auto comp = [](const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) -> bool {
    1182           0 :             return a.GetTx().GetHash() == b.GetTx().GetHash();
    1183             :         };
    1184         772 :         assert(setParentCheck.size() == it->GetMemPoolParentsConst().size());
    1185         772 :         assert(std::equal(setParentCheck.begin(), setParentCheck.end(), it->GetMemPoolParentsConst().begin(), comp));
    1186             :         // Verify ancestor state is correct.
    1187         772 :         setEntries setAncestors;
    1188         772 :         uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
    1189         772 :         std::string dummy;
    1190         772 :         CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);
    1191         772 :         uint64_t nCountCheck = setAncestors.size() + 1;
    1192         772 :         uint64_t nSizeCheck = it->GetTxSize();
    1193         772 :         CAmount nFeesCheck = it->GetModifiedFee();
    1194         772 :         unsigned int nSigOpCheck = it->GetSigOpCount();
    1195             : 
    1196         772 :         for (txiter ancestorIt : setAncestors) {
    1197           0 :             nSizeCheck += ancestorIt->GetTxSize();
    1198           0 :             nFeesCheck += ancestorIt->GetModifiedFee();
    1199           0 :             nSigOpCheck += ancestorIt->GetSigOpCount();
    1200             :         }
    1201             : 
    1202         772 :         assert(it->GetCountWithAncestors() == nCountCheck);
    1203         772 :         assert(it->GetSizeWithAncestors() == nSizeCheck);
    1204         772 :         assert(it->GetSigOpCountWithAncestors() == nSigOpCheck);
    1205         772 :         assert(it->GetModFeesWithAncestors() == nFeesCheck);
    1206             :         // Sanity check: we are walking in ascending ancestor count order.
    1207         772 :         assert(prev_ancestor_count <= it->GetCountWithAncestors());
    1208         772 :         prev_ancestor_count = it->GetCountWithAncestors();
    1209             : 
    1210             :         // Check children against mapNextTx
    1211         772 :         CTxMemPoolEntry::Children setChildrenCheck;
    1212         772 :         auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
    1213         772 :         uint64_t child_sizes = 0;
    1214        1395 :         for (; iter != mapNextTx.end() && iter->first->hash == it->GetTx().GetHash(); ++iter) {
    1215           0 :             txiter childit = mapTx.find(iter->second->GetHash());
    1216           0 :             assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions
    1217           0 :             if (setChildrenCheck.insert(*childit).second) {
    1218           0 :                 child_sizes += childit->GetTxSize();
    1219           0 :             }
    1220           0 :         }
    1221         772 :         assert(setChildrenCheck.size() == it->GetMemPoolChildrenConst().size());
    1222         772 :         assert(std::equal(setChildrenCheck.begin(), setChildrenCheck.end(), it->GetMemPoolChildrenConst().begin(), comp));
    1223             :         // Also check to make sure size is greater than sum with immediate children.
    1224             :         // just a sanity check, not definitive that this calc is correct...
    1225         772 :         assert(it->GetSizeWithDescendants() >= child_sizes + it->GetTxSize());
    1226             : 
    1227         772 :         TxValidationState dummy_state; // Not used. CheckTxInputs() should always pass
    1228         772 :         CAmount txfee = 0;
    1229         772 :         assert(!tx.IsCoinBase());
    1230         772 :         assert(Consensus::CheckTxInputs(tx, dummy_state, mempoolDuplicate, spendheight, txfee));
    1231        1544 :         for (const auto& input: tx.vin) mempoolDuplicate.SpendCoin(input.prevout);
    1232         772 :         AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
    1233         772 :     }
    1234       25045 :     for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) {
    1235         772 :         uint256 hash = it->second->GetHash();
    1236         772 :         indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
    1237         772 :         const CTransaction& tx = it2->GetTx();
    1238         772 :         assert(it2 != mapTx.end());
    1239         772 :         assert(&tx == it->second);
    1240         772 :     }
    1241             : 
    1242       24273 :     assert(totalTxSize == checkTotal);
    1243       24273 :     assert(m_total_fee == check_total_fee);
    1244       24273 :     assert(innerUsage == cachedInnerUsage);
    1245       24273 : }
    1246             : 
    1247           0 : bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb)
    1248             : {
    1249             :     /* Return `true` if hasha should be considered sooner than hashb. Namely when:
    1250             :      *   a is not in the mempool, but b is
    1251             :      *   both are in the mempool and a has fewer ancestors than b
    1252             :      *   both are in the mempool and a has a higher score than b
    1253             :      */
    1254           0 :     LOCK(cs);
    1255           0 :     indexed_transaction_set::const_iterator j = mapTx.find(hashb);
    1256           0 :     if (j == mapTx.end()) return false;
    1257           0 :     indexed_transaction_set::const_iterator i = mapTx.find(hasha);
    1258           0 :     if (i == mapTx.end()) return true;
    1259           0 :     uint64_t counta = i->GetCountWithAncestors();
    1260           0 :     uint64_t countb = j->GetCountWithAncestors();
    1261           0 :     if (counta == countb) {
    1262           0 :         return CompareTxMemPoolEntryByScore()(*i, *j);
    1263             :     }
    1264           0 :     return counta < countb;
    1265           0 : }
    1266             : 
    1267             : namespace {
    1268             : class DepthAndScoreComparator
    1269             : {
    1270             : public:
    1271        3138 :     bool operator()(const CTxMemPool::indexed_transaction_set::const_iterator& a, const CTxMemPool::indexed_transaction_set::const_iterator& b)
    1272             :     {
    1273        3138 :         uint64_t counta = a->GetCountWithAncestors();
    1274        3138 :         uint64_t countb = b->GetCountWithAncestors();
    1275        3138 :         if (counta == countb) {
    1276        3138 :             return CompareTxMemPoolEntryByScore()(*a, *b);
    1277             :         }
    1278           0 :         return counta < countb;
    1279        3138 :     }
    1280             : };
    1281             : } // namespace
    1282             : 
    1283       24273 : std::vector<CTxMemPool::indexed_transaction_set::const_iterator> CTxMemPool::GetSortedDepthAndScore() const
    1284             : {
    1285       24273 :     std::vector<indexed_transaction_set::const_iterator> iters;
    1286       24273 :     AssertLockHeld(cs);
    1287             : 
    1288       24273 :     iters.reserve(mapTx.size());
    1289             : 
    1290       25045 :     for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
    1291         772 :         iters.push_back(mi);
    1292         772 :     }
    1293       24273 :     std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
    1294       24273 :     return iters;
    1295       24273 : }
    1296             : 
    1297           0 : void CTxMemPool::queryHashes(std::vector<uint256>& vtxid) const
    1298             : {
    1299           0 :     LOCK(cs);
    1300           0 :     auto iters = GetSortedDepthAndScore();
    1301             : 
    1302           0 :     vtxid.clear();
    1303           0 :     vtxid.reserve(mapTx.size());
    1304             : 
    1305           0 :     for (auto it : iters) {
    1306           0 :         vtxid.push_back(it->GetTx().GetHash());
    1307             :     }
    1308           0 : }
    1309             : 
    1310           0 : static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) {
    1311           0 :     return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), it->GetFee(), it->GetTxSize(), it->GetModifiedFee() - it->GetFee()};
    1312           0 : }
    1313             : 
    1314           0 : std::vector<TxMempoolInfo> CTxMemPool::infoAll() const
    1315             : {
    1316           0 :     LOCK(cs);
    1317           0 :     auto iters = GetSortedDepthAndScore();
    1318             : 
    1319           0 :     std::vector<TxMempoolInfo> ret;
    1320           0 :     ret.reserve(mapTx.size());
    1321           0 :     for (auto it : iters) {
    1322           0 :         ret.push_back(GetInfo(it));
    1323             :     }
    1324             : 
    1325           0 :     return ret;
    1326           0 : }
    1327             : 
    1328       24958 : CTransactionRef CTxMemPool::get(const uint256& hash) const
    1329             : {
    1330       24958 :     LOCK(cs);
    1331       24958 :     indexed_transaction_set::const_iterator i = mapTx.find(hash);
    1332       24958 :     if (i == mapTx.end())
    1333         349 :         return nullptr;
    1334       24609 :     return i->GetSharedTx();
    1335       24958 : }
    1336             : 
    1337           0 : TxMempoolInfo CTxMemPool::info(const uint256& hash) const
    1338             : {
    1339           0 :     LOCK(cs);
    1340           0 :     indexed_transaction_set::const_iterator i = mapTx.find(hash);
    1341           0 :     if (i == mapTx.end())
    1342           0 :         return TxMempoolInfo();
    1343           0 :     return GetInfo(i);
    1344           0 : }
    1345             : 
    1346          86 : bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const {
    1347          86 :     auto dmnman = Assert(m_dmnman.load(std::memory_order_acquire));
    1348             : 
    1349          86 :     LOCK(cs);
    1350             : 
    1351          86 :     auto hasKeyChangeInMempool = [&](const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(cs) {
    1352           0 :         AssertLockHeld(cs);
    1353           0 :         for (auto its = mapProTxRefs.equal_range(proTxHash); its.first != its.second; ++its.first) {
    1354           0 :             auto txit = mapTx.find(its.first->second);
    1355           0 :             if (txit == mapTx.end()) {
    1356           0 :                 continue;
    1357             :             }
    1358           0 :             if (txit->isKeyChangeProTx) {
    1359           0 :                 return true;
    1360             :             }
    1361           0 :         }
    1362           0 :         return false;
    1363           0 :     };
    1364             : 
    1365          86 :     const uint256 tx_hash{tx.GetHash()};
    1366          86 :     if (tx.nType == TRANSACTION_PROVIDER_REGISTER) {
    1367           2 :         const auto opt_proTx = GetTxPayload<CProRegTx>(tx);
    1368           2 :         if (!opt_proTx) {
    1369           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString());
    1370           0 :             return true; // i.e. can't decode payload == conflict
    1371             :         }
    1372           2 :         auto& proTx = *opt_proTx;
    1373           4 :         for (const auto& entry : proTx.netInfo->GetEntries()) {
    1374           2 :             if (mapProTxAddresses.count(entry)) {
    1375           0 :                 return true;
    1376             :             }
    1377             :         }
    1378           2 :         if (mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxBlsPubKeyHashes.count(proTx.pubKeyOperator.GetHash())) {
    1379           0 :             return true;
    1380             :         }
    1381           2 :         if (!proTx.collateralOutpoint.hash.IsNull()) {
    1382           2 :             if (mapProTxCollaterals.count(proTx.collateralOutpoint)) {
    1383             :                 // there is another ProRegTx that refers to the same collateral
    1384           2 :                 return true;
    1385             :             }
    1386           0 :             if (mapNextTx.count(proTx.collateralOutpoint)) {
    1387             :                 // there is another tx that spends the collateral
    1388           0 :                 return true;
    1389             :             }
    1390           0 :         }
    1391           0 :         return false;
    1392          86 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
    1393           0 :         const auto opt_proTx = GetTxPayload<CProUpServTx>(tx);
    1394           0 :         if (!opt_proTx) {
    1395           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString());
    1396           0 :             return true; // i.e. can't decode payload == conflict
    1397             :         }
    1398           0 :         for (const auto& entry : opt_proTx->netInfo->GetEntries()) {
    1399           0 :             auto it = mapProTxAddresses.find(entry);
    1400           0 :             if (it != mapProTxAddresses.end() && it->second != opt_proTx->proTxHash) {
    1401           0 :                 return true;
    1402             :             }
    1403             :         }
    1404          84 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
    1405           0 :         const auto opt_proTx = GetTxPayload<CProUpRegTx>(tx);
    1406           0 :         if (!opt_proTx) {
    1407           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString());
    1408           0 :             return true; // i.e. can't decode payload == conflict
    1409             :         }
    1410           0 :         auto& proTx = *opt_proTx;
    1411             : 
    1412             :         // this method should only be called with validated ProTxs
    1413           0 :         auto dmn = dmnman->GetListAtChainTip().GetMN(proTx.proTxHash);
    1414           0 :         if (!dmn) {
    1415           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Masternode is not in the list, proTxHash: %s\n", __func__, proTx.proTxHash.ToString());
    1416           0 :             return true; // i.e. failed to find validated ProTx == conflict
    1417             :         }
    1418             :         // only allow one operator key change in the mempool
    1419           0 :         if (dmn->pdmnState->pubKeyOperator != proTx.pubKeyOperator) {
    1420           0 :             if (hasKeyChangeInMempool(proTx.proTxHash)) {
    1421           0 :                 return true;
    1422             :             }
    1423           0 :         }
    1424             : 
    1425           0 :         auto it = mapProTxBlsPubKeyHashes.find(proTx.pubKeyOperator.GetHash());
    1426           0 :         return it != mapProTxBlsPubKeyHashes.end() && it->second != proTx.proTxHash;
    1427          84 :     } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) {
    1428           0 :         const auto opt_proTx = GetTxPayload<CProUpRevTx>(tx);
    1429           0 :         if (!opt_proTx) {
    1430           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString());
    1431           0 :             return true; // i.e. can't decode payload == conflict
    1432             :         }
    1433           0 :         auto& proTx = *opt_proTx;
    1434             :         // this method should only be called with validated ProTxs
    1435           0 :         auto dmn = dmnman->GetListAtChainTip().GetMN(proTx.proTxHash);
    1436           0 :         if (!dmn) {
    1437           0 :             LogPrint(BCLog::MEMPOOL, "%s: ERROR: Masternode is not in the list, proTxHash: %s\n", __func__, proTx.proTxHash.ToString());
    1438           0 :             return true; // i.e. failed to find validated ProTx == conflict
    1439             :         }
    1440             :         // only allow one operator key change in the mempool
    1441           0 :         if (dmn->pdmnState->pubKeyOperator.Get() != CBLSPublicKey()) {
    1442           0 :             if (hasKeyChangeInMempool(proTx.proTxHash)) {
    1443           0 :                 return true;
    1444             :             }
    1445           0 :         }
    1446           0 :     }
    1447          84 :     return false;
    1448          86 : }
    1449             : 
    1450           7 : void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeDelta)
    1451             : {
    1452             :     {
    1453           7 :         LOCK(cs);
    1454           7 :         CAmount &delta = mapDeltas[hash];
    1455           7 :         delta = SaturatingAdd(delta, nFeeDelta);
    1456           7 :         txiter it = mapTx.find(hash);
    1457           7 :         if (it != mapTx.end()) {
    1458          10 :             mapTx.modify(it, [&nFeeDelta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(nFeeDelta); });
    1459             :             // Now update all ancestors' modified fees with descendants
    1460           5 :             setEntries setAncestors;
    1461           5 :             uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
    1462           5 :             std::string dummy;
    1463           5 :             CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
    1464           7 :             for (txiter ancestorIt : setAncestors) {
    1465           4 :                 mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e){ e.UpdateDescendantState(0, nFeeDelta, 0);});
    1466             :             }
    1467             :             // Now update all descendants' modified fees with ancestors
    1468           5 :             setEntries setDescendants;
    1469           5 :             CalculateDescendants(it, setDescendants);
    1470           5 :             setDescendants.erase(it);
    1471           5 :             for (txiter descendantIt : setDescendants) {
    1472           0 :                 mapTx.modify(descendantIt, [=](CTxMemPoolEntry& e){ e.UpdateAncestorState(0, nFeeDelta, 0, 0); });
    1473             :             }
    1474           5 :             ++nTransactionsUpdated;
    1475           5 :         }
    1476           7 :     }
    1477           7 :     LogPrint(BCLog::MEMPOOL, "PrioritiseTransaction: %s fee += %s\n", hash.ToString(), FormatMoney(nFeeDelta));
    1478           7 : }
    1479             : 
    1480       26995 : void CTxMemPool::ApplyDelta(const uint256& hash, CAmount &nFeeDelta) const
    1481             : {
    1482       26995 :     AssertLockHeld(cs);
    1483       26995 :     std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
    1484       26995 :     if (pos == mapDeltas.end())
    1485       26991 :         return;
    1486           4 :     const CAmount &delta = pos->second;
    1487           4 :     nFeeDelta += delta;
    1488       26995 : }
    1489             : 
    1490       63715 : void CTxMemPool::ClearPrioritisation(const uint256& hash)
    1491             : {
    1492       63715 :     AssertLockHeld(cs);
    1493       63715 :     mapDeltas.erase(hash);
    1494       63715 : }
    1495             : 
    1496          95 : const CTransaction* CTxMemPool::GetConflictTx(const COutPoint& prevout) const
    1497             : {
    1498          95 :     const auto it = mapNextTx.find(prevout);
    1499          95 :     return it == mapNextTx.end() ? nullptr : it->second;
    1500             : }
    1501             : 
    1502       55222 : std::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
    1503             : {
    1504       55222 :     auto it = mapTx.find(txid);
    1505       55222 :     if (it != mapTx.end()) return it;
    1506       50860 :     return std::nullopt;
    1507       55222 : }
    1508             : 
    1509       26904 : CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) const
    1510             : {
    1511       26904 :     CTxMemPool::setEntries ret;
    1512       53829 :     for (const auto& h : hashes) {
    1513       26925 :         const auto mi = GetIter(h);
    1514       26925 :         if (mi) ret.insert(*mi);
    1515             :     }
    1516       26904 :     return ret;
    1517       26904 : }
    1518             : 
    1519           8 : bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
    1520             : {
    1521          15 :     for (unsigned int i = 0; i < tx.vin.size(); i++)
    1522           8 :         if (exists(tx.vin[i].prevout.hash))
    1523           1 :             return false;
    1524           7 :     return true;
    1525           8 : }
    1526             : 
    1527         192 : CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
    1528             : 
    1529         100 : bool CCoinsViewMemPool::GetCoin(const COutPoint &outpoint, Coin &coin) const {
    1530             :     // Check to see if the inputs are made available by another tx in the package.
    1531             :     // These Coins would not be available in the underlying CoinsView.
    1532         100 :     if (auto it = m_temp_added.find(outpoint); it != m_temp_added.end()) {
    1533           4 :         coin = it->second;
    1534           4 :         return true;
    1535             :     }
    1536             : 
    1537             :     // If an entry in the mempool exists, always return that one, as it's guaranteed to never
    1538             :     // conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
    1539             :     // transactions. First checking the underlying cache risks returning a pruned entry instead.
    1540          96 :     CTransactionRef ptx = mempool.get(outpoint.hash);
    1541          96 :     if (ptx) {
    1542           6 :         if (outpoint.n < ptx->vout.size()) {
    1543           6 :             coin = Coin(ptx->vout[outpoint.n], MEMPOOL_HEIGHT, false);
    1544           6 :             return true;
    1545             :         } else {
    1546           0 :             return false;
    1547             :         }
    1548             :     }
    1549          90 :     return base->GetCoin(outpoint, coin);
    1550         100 : }
    1551             : 
    1552           8 : void CCoinsViewMemPool::PackageAddTransaction(const CTransactionRef& tx)
    1553             : {
    1554          16 :     for (unsigned int n = 0; n < tx->vout.size(); ++n) {
    1555           8 :         m_temp_added.emplace(COutPoint(tx->GetHash(), n), Coin(tx->vout[n], MEMPOOL_HEIGHT, false));
    1556           8 :     }
    1557           8 : }
    1558             : 
    1559       73760 : size_t CTxMemPool::DynamicMemoryUsage() const {
    1560       73760 :     LOCK(cs);
    1561             :     // Estimate the overhead of mapTx to be 12 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented.
    1562       73760 :     return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 12 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(vTxHashes) + cachedInnerUsage;
    1563       73760 : }
    1564             : 
    1565       24701 : void CTxMemPool::RemoveUnbroadcastTx(const uint256& txid, const bool unchecked) {
    1566       24701 :     LOCK(cs);
    1567             : 
    1568       24701 :     if (m_unbroadcast_txids.erase(txid))
    1569             :     {
    1570           0 :         LogPrint(BCLog::MEMPOOL, "Removed %i from set of unbroadcast txns%s\n", txid.GetHex(), (unchecked ? " before confirmation that txn was sent out" : ""));
    1571           0 :     }
    1572       24701 : }
    1573             : 
    1574       25121 : void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) {
    1575       25121 :     AssertLockHeld(cs);
    1576       25121 :     UpdateForRemoveFromMempool(stage, updateDescendants);
    1577       49822 :     for (txiter it : stage) {
    1578       24701 :         removeUnchecked(it, reason);
    1579             :     }
    1580       25121 : }
    1581             : 
    1582          93 : int CTxMemPool::Expire(std::chrono::seconds time)
    1583             : {
    1584          93 :     AssertLockHeld(cs);
    1585          93 :     auto isman = Assert(m_isman.load(std::memory_order_acquire));
    1586          93 :     indexed_transaction_set::index<entry_time>::type::iterator it = mapTx.get<entry_time>().begin();
    1587          93 :     setEntries toremove;
    1588          93 :     while (it != mapTx.get<entry_time>().end() && it->GetTime() < time) {
    1589             :         // locked txes do not expire until mined and have sufficient confirmations
    1590           0 :         if (isman->IsLocked(it->GetTx().GetHash())) {
    1591           0 :             it++;
    1592           0 :             continue;
    1593             :         }
    1594           0 :         toremove.insert(mapTx.project<0>(it));
    1595           0 :         it++;
    1596             :     }
    1597          93 :     setEntries stage;
    1598          93 :     for (txiter removeit : toremove) {
    1599           0 :         CalculateDescendants(removeit, stage);
    1600             :     }
    1601          93 :     RemoveStaged(stage, false, MemPoolRemovalReason::EXPIRY);
    1602          93 :     return stage.size();
    1603          93 : }
    1604             : 
    1605       26822 : void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, bool validFeeEstimate)
    1606             : {
    1607       26822 :     setEntries setAncestors;
    1608       26822 :     uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
    1609       26822 :     std::string dummy;
    1610       26822 :     CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);
    1611       26822 :     return addUnchecked(entry, setAncestors, validFeeEstimate);
    1612       26822 : }
    1613             : 
    1614        2202 : void CTxMemPool::UpdateChild(txiter entry, txiter child, bool add)
    1615             : {
    1616        2202 :     AssertLockHeld(cs);
    1617        2202 :     CTxMemPoolEntry::Children s;
    1618        2202 :     if (add && entry->GetMemPoolChildren().insert(*child).second) {
    1619        2181 :         cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
    1620        2202 :     } else if (!add && entry->GetMemPoolChildren().erase(*child)) {
    1621          21 :         cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
    1622          21 :     }
    1623        2202 : }
    1624             : 
    1625        2182 : void CTxMemPool::UpdateParent(txiter entry, txiter parent, bool add)
    1626             : {
    1627        2182 :     AssertLockHeld(cs);
    1628        2182 :     CTxMemPoolEntry::Parents s;
    1629        2182 :     if (add && entry->GetMemPoolParents().insert(*parent).second) {
    1630        2181 :         cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
    1631        2182 :     } else if (!add && entry->GetMemPoolParents().erase(*parent)) {
    1632           1 :         cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
    1633           1 :     }
    1634        2182 : }
    1635             : 
    1636         116 : CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
    1637         116 :     LOCK(cs);
    1638         116 :     if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
    1639         111 :         return CFeeRate(llround(rollingMinimumFeeRate));
    1640             : 
    1641           5 :     int64_t time = GetTime();
    1642           5 :     if (time > lastRollingFeeUpdate + 10) {
    1643           5 :         double halflife = ROLLING_FEE_HALFLIFE;
    1644           5 :         if (DynamicMemoryUsage() < sizelimit / 4)
    1645           1 :             halflife /= 4;
    1646           4 :         else if (DynamicMemoryUsage() < sizelimit / 2)
    1647           1 :             halflife /= 2;
    1648             : 
    1649           5 :         rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
    1650           5 :         lastRollingFeeUpdate = time;
    1651             : 
    1652           5 :         if (rollingMinimumFeeRate < (double)incrementalRelayFee.GetFeePerK() / 2) {
    1653           1 :             rollingMinimumFeeRate = 0;
    1654           1 :             return CFeeRate(0);
    1655             :         }
    1656           4 :     }
    1657           4 :     return std::max(CFeeRate(llround(rollingMinimumFeeRate)), incrementalRelayFee);
    1658         116 : }
    1659             : 
    1660           6 : void CTxMemPool::trackPackageRemoved(const CFeeRate& rate) {
    1661           6 :     AssertLockHeld(cs);
    1662           6 :     if (rate.GetFeePerK() > rollingMinimumFeeRate) {
    1663           4 :         rollingMinimumFeeRate = rate.GetFeePerK();
    1664           4 :         blockSinceLastRollingFeeBump = false;
    1665           4 :     }
    1666           6 : }
    1667             : 
    1668         100 : void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpendsRemaining) {
    1669         100 :     AssertLockHeld(cs);
    1670             : 
    1671         100 :     unsigned nTxnRemoved = 0;
    1672         100 :     CFeeRate maxFeeRateRemoved(0);
    1673         106 :     while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) {
    1674           6 :         indexed_transaction_set::index<descendant_score>::type::iterator it = mapTx.get<descendant_score>().begin();
    1675             : 
    1676             :         // We set the new mempool min fee to the feerate of the removed set, plus the
    1677             :         // "minimum reasonable fee rate" (ie some value under which we consider txn
    1678             :         // to have 0 fee). This way, we don't allow txn to enter mempool with feerate
    1679             :         // equal to txn which were removed with no block in between.
    1680           6 :         CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
    1681           6 :         removed += incrementalRelayFee;
    1682           6 :         trackPackageRemoved(removed);
    1683           6 :         maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
    1684             : 
    1685           6 :         setEntries stage;
    1686           6 :         CalculateDescendants(mapTx.project<0>(it), stage);
    1687           6 :         nTxnRemoved += stage.size();
    1688             : 
    1689           6 :         std::vector<CTransaction> txn;
    1690           6 :         if (pvNoSpendsRemaining) {
    1691           0 :             txn.reserve(stage.size());
    1692           0 :             for (txiter iter : stage)
    1693           0 :                 txn.push_back(iter->GetTx());
    1694           0 :         }
    1695           6 :         RemoveStaged(stage, false, MemPoolRemovalReason::SIZELIMIT);
    1696           6 :         if (pvNoSpendsRemaining) {
    1697           0 :             for (const CTransaction& tx : txn) {
    1698           0 :                 for (const CTxIn& txin : tx.vin) {
    1699           0 :                     if (exists(txin.prevout.hash)) continue;
    1700           0 :                     pvNoSpendsRemaining->push_back(txin.prevout);
    1701             :                 }
    1702             :             }
    1703           0 :         }
    1704           6 :     }
    1705             : 
    1706         100 :     if (maxFeeRateRemoved > CFeeRate(0)) {
    1707           6 :         LogPrint(BCLog::MEMPOOL, "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString());
    1708           6 :     }
    1709         100 : }
    1710             : 
    1711          29 : uint64_t CTxMemPool::CalculateDescendantMaximum(txiter entry) const {
    1712             :     // find parent with highest descendant count
    1713          29 :     std::vector<txiter> candidates;
    1714          29 :     setEntries counted;
    1715          29 :     candidates.push_back(entry);
    1716          29 :     uint64_t maximum = 0;
    1717         107 :     while (candidates.size()) {
    1718          78 :         txiter candidate = candidates.back();
    1719          78 :         candidates.pop_back();
    1720          78 :         if (!counted.insert(candidate).second) continue;
    1721          77 :         const CTxMemPoolEntry::Parents& parents = candidate->GetMemPoolParentsConst();
    1722          77 :         if (parents.size() == 0) {
    1723          30 :             maximum = std::max(maximum, candidate->GetCountWithDescendants());
    1724          30 :         } else {
    1725          96 :             for (const CTxMemPoolEntry& i : parents) {
    1726          49 :                 candidates.push_back(mapTx.iterator_to(i));
    1727             :             }
    1728             :         }
    1729             :     }
    1730          29 :     return maximum;
    1731          29 : }
    1732             : 
    1733      598572 : void CTxMemPool::GetTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants, size_t* const ancestorsize, CAmount* const ancestorfees) const {
    1734      598572 :     LOCK(cs);
    1735      598572 :     auto it = mapTx.find(txid);
    1736      598572 :     ancestors = descendants = 0;
    1737      598572 :     if (it != mapTx.end()) {
    1738          29 :         ancestors = it->GetCountWithAncestors();
    1739          29 :         if (ancestorsize) *ancestorsize = it->GetSizeWithAncestors();
    1740          29 :         if (ancestorfees) *ancestorfees = it->GetModFeesWithAncestors();
    1741          29 :         descendants = CalculateDescendantMaximum(it);
    1742          29 :     }
    1743      598572 : }
    1744             : 
    1745           0 : bool CTxMemPool::IsLoaded() const
    1746             : {
    1747           0 :     LOCK(cs);
    1748           0 :     return m_is_loaded;
    1749           0 : }
    1750             : 
    1751           0 : void CTxMemPool::SetIsLoaded(bool loaded)
    1752             : {
    1753           0 :     LOCK(cs);
    1754           0 :     m_is_loaded = loaded;
    1755           0 : }
    1756             : 
    1757             : 
    1758         198 : std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept
    1759             : {
    1760         198 :     switch (r) {
    1761           2 :         case MemPoolRemovalReason::EXPIRY: return "expiry";
    1762          19 :         case MemPoolRemovalReason::SIZELIMIT: return "sizelimit";
    1763         133 :         case MemPoolRemovalReason::REORG: return "reorg";
    1764           0 :         case MemPoolRemovalReason::BLOCK: return "block";
    1765           8 :         case MemPoolRemovalReason::CONFLICT: return "conflict";
    1766          38 :         case MemPoolRemovalReason::MANUAL: return "manual";
    1767             :     }
    1768           0 :     assert(false);
    1769         198 : }

Generated by: LCOV version 1.16