Skip to content

Commit 11cc143

Browse files
committed
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 db0ffe8 commit 11cc143

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/main.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ struct IteratorComparator
100100
struct COrphanTx {
101101
CTransaction tx;
102102
NodeId fromPeer;
103+
int64_t nTimeExpire;
103104
};
104105
map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_main);
105106
map<COutPoint, set<map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(cs_main);
@@ -641,7 +642,7 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c
641642
return false;
642643
}
643644

644-
auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer});
645+
auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME});
645646
assert(ret.second);
646647
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
647648
mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first);
@@ -689,6 +690,26 @@ void EraseOrphansFor(NodeId peer)
689690
unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
690691
{
691692
unsigned int nEvicted = 0;
693+
static int64_t nNextSweep;
694+
int64_t nNow = GetTime();
695+
if (nNextSweep <= nNow) {
696+
// Sweep out expired orphan pool entries:
697+
int nErased = 0;
698+
int64_t nMinExpTime = nNow + ORPHAN_TX_EXPIRE_TIME - ORPHAN_TX_EXPIRE_INTERVAL;
699+
map<uint256, COrphanTx>::iterator iter = mapOrphanTransactions.begin();
700+
while (iter != mapOrphanTransactions.end())
701+
{
702+
map<uint256, COrphanTx>::iterator maybeErase = iter++;
703+
if (maybeErase->second.nTimeExpire <= nNow) {
704+
nErased += EraseOrphanTx(maybeErase->second.tx.GetHash());
705+
} else {
706+
nMinExpTime = std::min(maybeErase->second.nTimeExpire, nMinExpTime);
707+
}
708+
}
709+
// Sweep again 5 minutes after the next entry that expires in order to batch the linear scan.
710+
nNextSweep = nMinExpTime + ORPHAN_TX_EXPIRE_INTERVAL;
711+
if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx due to expiration\n", nErased);
712+
}
692713
while (mapOrphanTransactions.size() > nMaxOrphans)
693714
{
694715
// Evict a random orphan:

src/main.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN;
5656
static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB;
5757
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
5858
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
59+
/** Expiration time for orphan transactions in seconds */
60+
static const int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60;
61+
/** Minimum time between orphan transactions expire time checks in seconds */
62+
static const int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60;
5963
/** Default for -limitancestorcount, max number of in-mempool ancestors */
6064
static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25;
6165
/** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */

0 commit comments

Comments
 (0)