Skip to content

Commit 59ff590

Browse files
gmaxwellfurszy
authored andcommitted
Adds an expiration time for orphan tx.
This prevents higher order orphans and other junk from holding positions in the orphan map.  Parents delayed twenty minutes are more are unlikely to ever arrive. The freed space will improve the orphan matching success rate for other transactions.
1 parent d7461b8 commit 59ff590

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

src/net_processing.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct IteratorComparator
3434
struct COrphanTx {
3535
CTransactionRef tx;
3636
NodeId fromPeer;
37+
int64_t nTimeExpire;
3738
};
3839

3940
std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_main);
@@ -518,7 +519,7 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE
518519
return false;
519520
}
520521

521-
auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer});
522+
auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME});
522523
assert(ret.second);
523524
for (const CTxIn& txin : tx->vin) {
524525
mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first);
@@ -563,6 +564,25 @@ void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
563564
unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
564565
{
565566
unsigned int nEvicted = 0;
567+
static int64_t nNextSweep;
568+
int64_t nNow = GetTime();
569+
if (nNextSweep <= nNow) {
570+
// Sweep out expired orphan pool entries:
571+
int nErased = 0;
572+
int64_t nMinExpTime = nNow + ORPHAN_TX_EXPIRE_TIME - ORPHAN_TX_EXPIRE_INTERVAL;
573+
auto iter = mapOrphanTransactions.begin();
574+
while (iter != mapOrphanTransactions.end()) {
575+
auto maybeErase = iter++;
576+
if (maybeErase->second.nTimeExpire <= nNow) {
577+
nErased += EraseOrphanTx(maybeErase->second.tx->GetHash());
578+
} else {
579+
nMinExpTime = std::min(maybeErase->second.nTimeExpire, nMinExpTime);
580+
}
581+
}
582+
// Sweep again 5 minutes after the next entry that expires in order to batch the linear scan.
583+
nNextSweep = nMinExpTime + ORPHAN_TX_EXPIRE_INTERVAL;
584+
if (nErased > 0) LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx due to expiration\n", nErased);
585+
}
566586
FastRandomContext rng;
567587
while (mapOrphanTransactions.size() > nMaxOrphans) {
568588
// Evict a random orphan:

src/net_processing.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ extern RecursiveMutex cs_main; // !TODO: change mutex to cs_orphans
1414

1515
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
1616
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
17+
/** Expiration time for orphan transactions in seconds */
18+
static const int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60;
19+
/** Minimum time between orphan transactions expire time checks in seconds */
20+
static const int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60;
1721
/** Default for -blockspamfilter, use header spam filter */
1822
static const bool DEFAULT_BLOCK_SPAM_FILTER = true;
1923
/** Default for -blockspamfiltermaxsize, maximum size of the list of indexes in the block spam filter */

0 commit comments

Comments
 (0)