diff --git a/src/txorphanage.cpp b/src/txorphanage.cpp index 8b8b2e845..81ec866d5 100644 --- a/src/txorphanage.cpp +++ b/src/txorphanage.cpp @@ -1,113 +1,113 @@ // Copyright (c) 2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include /** Minimum time between orphan transactions expire time checks in seconds */ static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60; RecursiveMutex g_cs_orphans; std::map mapOrphanTransactions GUARDED_BY(g_cs_orphans); std::map::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(g_cs_orphans); std::vector::iterator> g_orphan_list GUARDED_BY(g_cs_orphans); -int EraseOrphanTx(TxId id) { - std::map::iterator it = mapOrphanTransactions.find(id); +int EraseOrphanTx(const TxId &txid) { + std::map::iterator it = mapOrphanTransactions.find(txid); if (it == mapOrphanTransactions.end()) { return 0; } for (const CTxIn &txin : it->second.tx->vin) { auto itPrev = mapOrphanTransactionsByPrev.find(txin.prevout); if (itPrev == mapOrphanTransactionsByPrev.end()) { continue; } itPrev->second.erase(it); if (itPrev->second.empty()) { mapOrphanTransactionsByPrev.erase(itPrev); } } size_t old_pos = it->second.list_pos; assert(g_orphan_list[old_pos] == it); if (old_pos + 1 != g_orphan_list.size()) { // Unless we're deleting the last entry in g_orphan_list, move the last // entry to the position we're deleting. auto it_last = g_orphan_list.back(); g_orphan_list[old_pos] = it_last; it_last->second.list_pos = old_pos; } g_orphan_list.pop_back(); mapOrphanTransactions.erase(it); return 1; } void EraseOrphansFor(NodeId peer) { LOCK(g_cs_orphans); int nErased = 0; std::map::iterator iter = mapOrphanTransactions.begin(); while (iter != mapOrphanTransactions.end()) { std::map::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid if (maybeErase->second.fromPeer == peer) { nErased += EraseOrphanTx(maybeErase->second.tx->GetId()); } } if (nErased > 0) { LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx from peer=%d\n", nErased, peer); } } unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) { LOCK(g_cs_orphans); unsigned int nEvicted = 0; static int64_t nNextSweep; int64_t nNow = GetTime(); if (nNextSweep <= nNow) { // Sweep out expired orphan pool entries: int nErased = 0; int64_t nMinExpTime = nNow + ORPHAN_TX_EXPIRE_TIME - ORPHAN_TX_EXPIRE_INTERVAL; std::map::iterator iter = mapOrphanTransactions.begin(); while (iter != mapOrphanTransactions.end()) { std::map::iterator maybeErase = iter++; if (maybeErase->second.nTimeExpire <= nNow) { nErased += EraseOrphanTx(maybeErase->second.tx->GetId()); } else { nMinExpTime = std::min(maybeErase->second.nTimeExpire, nMinExpTime); } } // Sweep again 5 minutes after the next entry that expires in order to // batch the linear scan. nNextSweep = nMinExpTime + ORPHAN_TX_EXPIRE_INTERVAL; if (nErased > 0) { LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx due to expiration\n", nErased); } } FastRandomContext rng; while (mapOrphanTransactions.size() > nMaxOrphans) { // Evict a random orphan: size_t randompos = rng.randrange(g_orphan_list.size()); EraseOrphanTx(g_orphan_list[randompos]->first); ++nEvicted; } return nEvicted; } diff --git a/src/txorphanage.h b/src/txorphanage.h index f690c84b7..2d2d5be8b 100644 --- a/src/txorphanage.h +++ b/src/txorphanage.h @@ -1,54 +1,54 @@ // Copyright (c) 2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_TXORPHANAGE_H #define BITCOIN_TXORPHANAGE_H #include #include #include /** Expiration time for orphan transactions in seconds */ static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60; /** Guards orphan transactions and extra txs for compact blocks */ extern RecursiveMutex g_cs_orphans; struct COrphanTx { // When modifying, adapt the copy of this definition in tests/DoS_tests. CTransactionRef tx; NodeId fromPeer; int64_t nTimeExpire; size_t list_pos; }; -int EraseOrphanTx(TxId id) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans); +int EraseOrphanTx(const TxId &txid) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans); void EraseOrphansFor(NodeId peer); unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans); /** * Map from txid to orphan transaction record. Limited by * -maxorphantx/DEFAULT_MAX_ORPHAN_TRANSACTIONS */ extern std::map mapOrphanTransactions GUARDED_BY(g_cs_orphans); struct IteratorComparator { template bool operator()(const I &a, const I &b) const { return &(*a) < &(*b); } }; /** * Index from the parents' COutPoint into the mapOrphanTransactions. Used * to remove orphan transactions from the mapOrphanTransactions */ extern std::map::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(g_cs_orphans); /** Orphan transactions in vector for quick random eviction */ extern std::vector::iterator> g_orphan_list GUARDED_BY(g_cs_orphans); #endif // BITCOIN_TXORPHANAGE_H