10
10
11
11
#include < cassert>
12
12
13
+ /* * Expiration time for orphan transactions in seconds */
14
+ static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60 ;
13
15
/* * Minimum time between orphan transactions expire time checks in seconds */
14
16
static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60 ;
15
17
@@ -22,6 +24,42 @@ std::map<uint256, std::map<uint256, COrphanTx>::iterator> g_orphans_by_wtxid GUA
22
24
23
25
std::vector<std::map<uint256, COrphanTx>::iterator> g_orphan_list GUARDED_BY (g_cs_orphans);
24
26
27
+ bool OrphanageAddTx (const CTransactionRef& tx, NodeId peer)
28
+ {
29
+ AssertLockHeld (g_cs_orphans);
30
+
31
+ const uint256& hash = tx->GetHash ();
32
+ if (mapOrphanTransactions.count (hash))
33
+ return false ;
34
+
35
+ // Ignore big transactions, to avoid a
36
+ // send-big-orphans memory exhaustion attack. If a peer has a legitimate
37
+ // large transaction with a missing parent then we assume
38
+ // it will rebroadcast it later, after the parent transaction(s)
39
+ // have been mined or received.
40
+ // 100 orphans, each of which is at most 100,000 bytes big is
41
+ // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case):
42
+ unsigned int sz = GetTransactionWeight (*tx);
43
+ if (sz > MAX_STANDARD_TX_WEIGHT)
44
+ {
45
+ LogPrint (BCLog::MEMPOOL, " ignoring large orphan tx (size: %u, hash: %s)\n " , sz, hash.ToString ());
46
+ return false ;
47
+ }
48
+
49
+ auto ret = mapOrphanTransactions.emplace (hash, COrphanTx{tx, peer, GetTime () + ORPHAN_TX_EXPIRE_TIME, g_orphan_list.size ()});
50
+ assert (ret.second );
51
+ g_orphan_list.push_back (ret.first );
52
+ // Allow for lookups in the orphan pool by wtxid, as well as txid
53
+ g_orphans_by_wtxid.emplace (tx->GetWitnessHash (), ret.first );
54
+ for (const CTxIn& txin : tx->vin ) {
55
+ mapOrphanTransactionsByPrev[txin.prevout ].insert (ret.first );
56
+ }
57
+
58
+ LogPrint (BCLog::MEMPOOL, " stored orphan tx %s (mapsz %u outsz %u)\n " , hash.ToString (),
59
+ mapOrphanTransactions.size (), mapOrphanTransactionsByPrev.size ());
60
+ return true ;
61
+ }
62
+
25
63
int EraseOrphanTx (const uint256& txid)
26
64
{
27
65
std::map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find (txid);
0 commit comments