Skip to content

Commit e3fd7b2

Browse files
committed
Make orphan TX map limiting dependent on total TX size instead of TX count (#3121)
1 parent 87ff566 commit e3fd7b2

File tree

5 files changed

+24
-13
lines changed

5 files changed

+24
-13
lines changed

qa/rpc-tests/mempool_packages.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ def __init__(self):
1919

2020
def setup_network(self):
2121
self.nodes = []
22-
self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000"]))
23-
self.nodes.append(start_node(1, self.options.tmpdir, ["-maxorphantx=1000", "-limitancestorcount=5"]))
22+
self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantxsize=1000"]))
23+
self.nodes.append(start_node(1, self.options.tmpdir, ["-maxorphantxsize=1000", "-limitancestorcount=5"]))
2424
connect_nodes(self.nodes[0], 1)
2525
self.is_network_split = False
2626
self.sync_all()

qa/rpc-tests/smartfees.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ def setup_network(self):
156156
"""
157157
self.nodes = []
158158
# Use node0 to mine blocks for input splitting
159-
self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000",
159+
self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantxsize=1000",
160160
"-whitelist=127.0.0.1"]))
161161

162162
self.log.info("This test is time consuming, please be patient")
@@ -194,12 +194,12 @@ def setup_network(self):
194194
# (17k is room enough for 110 or so transactions)
195195
self.nodes.append(start_node(1, self.options.tmpdir,
196196
["-blockmaxsize=17000",
197-
"-maxorphantx=1000"]))
197+
"-maxorphantxsize=1000"]))
198198
connect_nodes(self.nodes[1], 0)
199199

200200
# Node2 is a stingy miner, that
201201
# produces too small blocks (room for only 55 or so transactions)
202-
node2args = ["-blockmaxsize=8000", "-maxorphantx=1000"]
202+
node2args = ["-blockmaxsize=8000", "-maxorphantxsize=1000"]
203203

204204
self.nodes.append(start_node(2, self.options.tmpdir, node2args))
205205
connect_nodes(self.nodes[0], 2)

src/init.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ std::string HelpMessage(HelpMessageMode mode)
444444
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
445445
strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
446446
strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup"));
447-
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
447+
strUsage += HelpMessageOpt("-maxorphantxsize=<n>", strprintf(_("Maximum total size of all orphan transactions in megabytes (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS_SIZE));
448448
strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
449449
strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
450450
strUsage += HelpMessageOpt("-blockreconstructionextratxn=<n>", strprintf(_("Extra transactions to keep in memory for compact block reconstructions (default: %u)"), DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN));
@@ -1402,6 +1402,10 @@ bool AppInitParameterInteraction()
14021402
return InitError("LLMQ type for ChainLocks can only be overridden on devnet.");
14031403
}
14041404

1405+
if (gArgs.IsArgSet("-maxorphantx")) {
1406+
InitWarning("-maxorphantx is not supported anymore. Use -maxorphantxsize instead.");
1407+
}
1408+
14051409
return true;
14061410
}
14071411

src/net_processing.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,12 @@ struct COrphanTx {
7676
CTransactionRef tx;
7777
NodeId fromPeer;
7878
int64_t nTimeExpire;
79+
size_t nTxSize;
7980
};
8081
static CCriticalSection g_cs_orphans;
8182
std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans);
8283
std::map<COutPoint, std::set<std::map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(g_cs_orphans);
84+
size_t nMapOrphanTransactionsSize = 0;
8385
void EraseOrphansFor(NodeId peer);
8486

8587
static size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0;
@@ -659,14 +661,16 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE
659661
return false;
660662
}
661663

662-
auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME});
664+
auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME, sz});
663665
assert(ret.second);
664666
BOOST_FOREACH(const CTxIn& txin, tx->vin) {
665667
mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first);
666668
}
667669

668670
AddToCompactExtraTransactions(tx);
669671

672+
nMapOrphanTransactionsSize += sz;
673+
670674
LogPrint("mempool", "stored orphan tx %s (mapsz %u outsz %u)\n", hash.ToString(),
671675
mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size());
672676
return true;
@@ -686,6 +690,8 @@ int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
686690
if (itPrev->second.empty())
687691
mapOrphanTransactionsByPrev.erase(itPrev);
688692
}
693+
assert(nMapOrphanTransactionsSize >= it->second.nTxSize);
694+
nMapOrphanTransactionsSize -= it->second.nTxSize;
689695
mapOrphanTransactions.erase(it);
690696
return 1;
691697
}
@@ -707,7 +713,7 @@ void EraseOrphansFor(NodeId peer)
707713
}
708714

709715

710-
unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
716+
unsigned int LimitOrphanTxSize(unsigned int nMaxOrphansSize)
711717
{
712718
LOCK(g_cs_orphans);
713719

@@ -732,7 +738,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
732738
nNextSweep = nMinExpTime + ORPHAN_TX_EXPIRE_INTERVAL;
733739
if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx due to expiration\n", nErased);
734740
}
735-
while (mapOrphanTransactions.size() > nMaxOrphans)
741+
while (!mapOrphanTransactions.empty() && nMapOrphanTransactionsSize > nMaxOrphansSize)
736742
{
737743
// Evict a random orphan:
738744
uint256 randomhash = GetRandHash();
@@ -2291,8 +2297,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
22912297
AddOrphanTx(ptx, pfrom->GetId());
22922298

22932299
// DoS prevention: do not allow mapOrphanTransactions to grow unbounded
2294-
unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS));
2295-
unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx);
2300+
unsigned int nMaxOrphanTxSize = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantxsize", DEFAULT_MAX_ORPHAN_TRANSACTIONS_SIZE)) * 1000000;
2301+
unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTxSize);
22962302
if (nEvicted > 0)
22972303
LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted);
22982304
} else {
@@ -3761,5 +3767,6 @@ class CNetProcessingCleanup
37613767
// orphan transactions
37623768
mapOrphanTransactions.clear();
37633769
mapOrphanTransactionsByPrev.clear();
3770+
nMapOrphanTransactionsSize = 0;
37643771
}
37653772
} instance_of_cnetprocessingcleanup;

src/net_processing.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
#include "net.h"
1010
#include "validationinterface.h"
1111

12-
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
13-
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
12+
/** Default for -maxorphantxsize, maximum size in megabytes the orphan map can grow before entries are removed */
13+
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS_SIZE = 10; // this allows around 100 TXs of max size (and many more of normal size)
1414
/** Expiration time for orphan transactions in seconds */
1515
static const int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60;
1616
/** Minimum time between orphan transactions expire time checks in seconds */

0 commit comments

Comments
 (0)