diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -126,6 +126,7 @@ CTransactionRef tx; NodeId fromPeer; int64_t nTimeExpire; + size_t list_pos; }; RecursiveMutex g_cs_orphans; @@ -246,6 +247,10 @@ std::set::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(g_cs_orphans); +//! For random eviction +std::vector::iterator> + g_orphan_list GUARDED_BY(g_cs_orphans); + static size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0; static std::vector> vExtraTxnForCompact GUARDED_BY(g_cs_orphans); @@ -1044,8 +1049,10 @@ } auto ret = mapOrphanTransactions.emplace( - txid, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME}); + txid, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME, + g_orphan_list.size()}); assert(ret.second); + g_orphan_list.push_back(ret.first); for (const CTxIn &txin : tx->vin) { mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first); } @@ -1073,6 +1080,18 @@ 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; } @@ -1126,12 +1145,8 @@ FastRandomContext rng; while (mapOrphanTransactions.size() > nMaxOrphans) { // Evict a random orphan: - const TxId randomTxId(rng.rand256()); - auto it = mapOrphanTransactions.lower_bound(randomTxId); - if (it == mapOrphanTransactions.end()) { - it = mapOrphanTransactions.begin(); - } - EraseOrphanTx(it->first); + size_t randompos = rng.randrange(g_orphan_list.size()); + EraseOrphanTx(g_orphan_list[randompos]->first); ++nEvicted; } return nEvicted;