diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/net_processing.cpp | 27 | ||||
-rw-r--r-- | src/txorphanage.cpp | 38 | ||||
-rw-r--r-- | src/txorphanage.h | 4 |
3 files changed, 40 insertions, 29 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 4ac50dc1f0..89586beba5 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1098,37 +1098,12 @@ static void AddToCompactExtraTransactions(const CTransactionRef& tx) EXCLUSIVE_L bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) { - const uint256& hash = tx->GetHash(); - if (mapOrphanTransactions.count(hash)) + if (!OrphanageAddTx(tx, peer)) { return false; - - // Ignore big transactions, to avoid a - // send-big-orphans memory exhaustion attack. If a peer has a legitimate - // large transaction with a missing parent then we assume - // it will rebroadcast it later, after the parent transaction(s) - // have been mined or received. - // 100 orphans, each of which is at most 100,000 bytes big is - // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case): - unsigned int sz = GetTransactionWeight(*tx); - if (sz > MAX_STANDARD_TX_WEIGHT) - { - LogPrint(BCLog::MEMPOOL, "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); - return false; - } - - auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME, g_orphan_list.size()}); - assert(ret.second); - g_orphan_list.push_back(ret.first); - // Allow for lookups in the orphan pool by wtxid, as well as txid - g_orphans_by_wtxid.emplace(tx->GetWitnessHash(), ret.first); - for (const CTxIn& txin : tx->vin) { - mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first); } AddToCompactExtraTransactions(tx); - LogPrint(BCLog::MEMPOOL, "stored orphan tx %s (mapsz %u outsz %u)\n", hash.ToString(), - mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size()); return true; } diff --git a/src/txorphanage.cpp b/src/txorphanage.cpp index 6baea9f69e..1527bdf5ea 100644 --- a/src/txorphanage.cpp +++ b/src/txorphanage.cpp @@ -10,6 +10,8 @@ #include <cassert> +/** Expiration time for orphan transactions in seconds */ +static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60; /** Minimum time between orphan transactions expire time checks in seconds */ static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60; @@ -22,6 +24,42 @@ std::map<uint256, std::map<uint256, COrphanTx>::iterator> g_orphans_by_wtxid GUA std::vector<std::map<uint256, COrphanTx>::iterator> g_orphan_list GUARDED_BY(g_cs_orphans); +bool OrphanageAddTx(const CTransactionRef& tx, NodeId peer) +{ + AssertLockHeld(g_cs_orphans); + + const uint256& hash = tx->GetHash(); + if (mapOrphanTransactions.count(hash)) + return false; + + // Ignore big transactions, to avoid a + // send-big-orphans memory exhaustion attack. If a peer has a legitimate + // large transaction with a missing parent then we assume + // it will rebroadcast it later, after the parent transaction(s) + // have been mined or received. + // 100 orphans, each of which is at most 100,000 bytes big is + // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case): + unsigned int sz = GetTransactionWeight(*tx); + if (sz > MAX_STANDARD_TX_WEIGHT) + { + LogPrint(BCLog::MEMPOOL, "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); + return false; + } + + auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME, g_orphan_list.size()}); + assert(ret.second); + g_orphan_list.push_back(ret.first); + // Allow for lookups in the orphan pool by wtxid, as well as txid + g_orphans_by_wtxid.emplace(tx->GetWitnessHash(), ret.first); + for (const CTxIn& txin : tx->vin) { + mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first); + } + + LogPrint(BCLog::MEMPOOL, "stored orphan tx %s (mapsz %u outsz %u)\n", hash.ToString(), + mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size()); + return true; +} + int EraseOrphanTx(const uint256& txid) { std::map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find(txid); diff --git a/src/txorphanage.h b/src/txorphanage.h index 1adc6f1d6c..1a72af175c 100644 --- a/src/txorphanage.h +++ b/src/txorphanage.h @@ -9,9 +9,6 @@ #include <primitives/transaction.h> #include <sync.h> -/** Expiration time for orphan transactions in seconds */ -static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60; - /** Guards orphan transactions and extra txs for compact blocks */ extern RecursiveMutex g_cs_orphans; @@ -29,6 +26,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRE void AddChildrenToWorkSet(const CTransaction& tx, std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans); bool HaveOrphanTx(const GenTxid& gtxid) EXCLUSIVE_LOCKS_REQUIRED(!g_cs_orphans); std::pair<CTransactionRef, NodeId> GetOrphanTx(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans); +bool OrphanageAddTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans); /** Map from txid to orphan transaction record. Limited by * -maxorphantx/DEFAULT_MAX_ORPHAN_TRANSACTIONS */ |