@@ -69,6 +69,7 @@ struct COrphanTx {
69
69
CTransactionRef tx;
70
70
NodeId fromPeer;
71
71
int64_t nTimeExpire;
72
+ size_t list_pos;
72
73
};
73
74
CCriticalSection g_cs_orphans;
74
75
std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY (g_cs_orphans);
@@ -170,6 +171,8 @@ namespace {
170
171
};
171
172
std::map<COutPoint, std::set<std::map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY (g_cs_orphans);
172
173
174
+ std::vector<std::map<uint256, COrphanTx>::iterator> g_orphan_list GUARDED_BY (g_cs_orphans); // ! For random eviction
175
+
173
176
static size_t vExtraTxnForCompactIt GUARDED_BY (g_cs_orphans) = 0;
174
177
static std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY (g_cs_orphans);
175
178
} // namespace
@@ -706,8 +709,9 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE
706
709
return false ;
707
710
}
708
711
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 () });
710
713
assert (ret.second );
714
+ g_orphan_list.push_back (ret.first );
711
715
for (const CTxIn& txin : tx->vin ) {
712
716
mapOrphanTransactionsByPrev[txin.prevout ].insert (ret.first );
713
717
}
@@ -733,6 +737,18 @@ int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
733
737
if (itPrev->second .empty ())
734
738
mapOrphanTransactionsByPrev.erase (itPrev);
735
739
}
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
+
736
752
mapOrphanTransactions.erase (it);
737
753
return 1 ;
738
754
}
@@ -783,11 +799,8 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
783
799
while (mapOrphanTransactions.size () > nMaxOrphans)
784
800
{
785
801
// 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 );
791
804
++nEvicted;
792
805
}
793
806
return nEvicted;
0 commit comments