Skip to content

Commit 7257353

Browse files
committed
Select orphan transaction uniformly for eviction
The previous code was biased towards evicting transactions whose txid has a larger gap (lexicographically) with the previous txid in the orphan pool.
1 parent 9a43344 commit 7257353

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

src/net_processing.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct COrphanTx {
6969
CTransactionRef tx;
7070
NodeId fromPeer;
7171
int64_t nTimeExpire;
72+
size_t list_pos;
7273
};
7374
CCriticalSection g_cs_orphans;
7475
std::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

Comments
 (0)