@@ -69,6 +69,7 @@ struct COrphanTx {
6969 CTransactionRef tx;
7070 NodeId fromPeer;
7171 int64_t nTimeExpire;
72+ size_t list_pos;
7273};
7374CCriticalSection g_cs_orphans;
7475std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY (g_cs_orphans);
@@ -170,6 +171,8 @@ namespace {
170171 };
171172 std::map<COutPoint, std::set<std::map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY (g_cs_orphans);
172173
174+ std::vector<std::map<uint256, COrphanTx>::iterator> g_orphan_list GUARDED_BY (g_cs_orphans); // ! For random eviction
175+
173176 static size_t vExtraTxnForCompactIt GUARDED_BY (g_cs_orphans) = 0;
174177 static std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY (g_cs_orphans);
175178} // namespace
@@ -706,8 +709,9 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE
706709 return false ;
707710 }
708711
709- auto ret = mapOrphanTransactions.emplace (hash, COrphanTx{tx, peer, GetTime () + ORPHAN_TX_EXPIRE_TIME});
712+ auto ret = mapOrphanTransactions.emplace (hash, COrphanTx{tx, peer, GetTime () + ORPHAN_TX_EXPIRE_TIME, g_orphan_list. size () });
710713 assert (ret.second );
714+ g_orphan_list.push_back (ret.first );
711715 for (const CTxIn& txin : tx->vin ) {
712716 mapOrphanTransactionsByPrev[txin.prevout ].insert (ret.first );
713717 }
@@ -733,6 +737,18 @@ int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
733737 if (itPrev->second .empty ())
734738 mapOrphanTransactionsByPrev.erase (itPrev);
735739 }
740+
741+ size_t old_pos = it->second .list_pos ;
742+ assert (g_orphan_list[old_pos] == it);
743+ if (old_pos + 1 != g_orphan_list.size ()) {
744+ // Unless we're deleting the last entry in g_orphan_list, move the last
745+ // entry to the position we're deleting.
746+ auto it_last = g_orphan_list.back ();
747+ g_orphan_list[old_pos] = it_last;
748+ it_last->second .list_pos = old_pos;
749+ }
750+ g_orphan_list.pop_back ();
751+
736752 mapOrphanTransactions.erase (it);
737753 return 1 ;
738754}
@@ -783,11 +799,8 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
783799 while (mapOrphanTransactions.size () > nMaxOrphans)
784800 {
785801 // Evict a random orphan:
786- uint256 randomhash = rng.rand256 ();
787- std::map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.lower_bound (randomhash);
788- if (it == mapOrphanTransactions.end ())
789- it = mapOrphanTransactions.begin ();
790- EraseOrphanTx (it->first );
802+ size_t randompos = rng.randrange (g_orphan_list.size ());
803+ EraseOrphanTx (g_orphan_list[randompos]->first );
791804 ++nEvicted;
792805 }
793806 return nEvicted;
0 commit comments