upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBitflash <btf01@proton.me>2026-07-28 15:25:29 -0300
committerGitHub <noreply@github.com>2026-07-28 15:25:29 -0300
commit8770e49d5264bdc9f6daec61dee74ca74dabdc0a (patch)
tree7899739b6619ee355cedda188b58baf9aacdb6c4
parent1635bc34f40c76ac2943dbe6ff15dd0180b62ea6 (diff)
main: cap orphan transactions held in memory (#16)
A transaction naming a parent the node does not have is never validated, just stored in mapOrphanTransactions -- and there was no ceiling. Sending them costs a peer nothing: no proof of work, no valid signature, no fee, and the node keeps every one. Any peer could grow that map until the node died of memory exhaustion. Cap at 100, evicting at random rather than in map order so an attacker cannot keep its own orphans resident by choosing hashes that sort low. Local policy, not consensus -- no effect on block or transaction validity.
-rw-r--r--src/main.cpp20
-rw-r--r--src/main.h6
2 files changed, 26 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
index a7298ea..17e446e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -249,6 +249,26 @@ void AddOrphanTx(const CDataStream& vMsg)
249 CDataStream* pvMsg = mapOrphanTransactions[hash] = new CDataStream(vMsg); 249 CDataStream* pvMsg = mapOrphanTransactions[hash] = new CDataStream(vMsg);
250 foreach(const CTxIn& txin, tx.vin) 250 foreach(const CTxIn& txin, tx.vin)
251 mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg)); 251 mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg));
252 LimitOrphanTx(MAX_ORPHAN_TRANSACTIONS);
253}
254
255// Orphans cost nothing to create -- a transaction naming a parent that does
256// not exist is never validated, just held -- so without a ceiling any peer can
257// grow this map until the node runs out of memory. Evict at random rather than
258// in map order, so an attacker cannot keep its own orphans resident by
259// choosing hashes that sort low.
260void LimitOrphanTx(unsigned int nMaxOrphans)
261{
262 while (mapOrphanTransactions.size() > nMaxOrphans)
263 {
264 uint256 randomhash;
265 for (int i = 0; i < 4; i++)
266 ((uint64*)&randomhash)[i] = GetRand(_UI64_MAX);
267 map<uint256, CDataStream*>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
268 if (it == mapOrphanTransactions.end())
269 it = mapOrphanTransactions.begin();
270 EraseOrphanTx(it->first);
271 }
252} 272}
253 273
254void EraseOrphanTx(uint256 hash) 274void EraseOrphanTx(uint256 hash)
diff --git a/src/main.h b/src/main.h
index 533974c..40f8d45 100644
--- a/src/main.h
+++ b/src/main.h
@@ -15,6 +15,9 @@ class CWalletTx;
15class CKeyItem; 15class CKeyItem;
16 16
17static const unsigned int MAX_SIZE = 0x02000000; 17static const unsigned int MAX_SIZE = 0x02000000;
18// Ceiling on transactions held waiting for a parent that has not arrived.
19// They cost a peer nothing to send and are never validated, only stored.
20static const unsigned int MAX_ORPHAN_TRANSACTIONS = 100;
18static const int64 COIN = 100000000; 21static const int64 COIN = 100000000;
19// Total Bitflash emission: identical to Bitcoin (21 million). 22// Total Bitflash emission: identical to Bitcoin (21 million).
20// MAX_MONEY guards against the value overflow bug (CVE-2010-5139), which in 23// MAX_MONEY guards against the value overflow bug (CVE-2010-5139), which in
@@ -106,6 +109,9 @@ void ReacceptWalletTransactions();
106void RelayWalletTransactions(); 109void RelayWalletTransactions();
107bool LoadBlockIndex(bool fAllowNew=true); 110bool LoadBlockIndex(bool fAllowNew=true);
108void PrintBlockTree(); 111void PrintBlockTree();
112void AddOrphanTx(const CDataStream& vMsg);
113void EraseOrphanTx(uint256 hash);
114void LimitOrphanTx(unsigned int nMaxOrphans);
109bool BitcoinMiner(); 115bool BitcoinMiner();
110void ThreadRPCServer(void* parg); // rpc.cpp -- .btf pool server 116void ThreadRPCServer(void* parg); // rpc.cpp -- .btf pool server
111void GetParticipantMiningStats(uint64& sharesSent, uint64& sharesAccepted, double& hashRate); 117void GetParticipantMiningStats(uint64& sharesSent, uint64& sharesAccepted, double& hashRate);