| 18 | RecursiveMutex g_cs_orphans; |
| 19 | |
| 20 | bool TxOrphanage::AddTx(const CTransactionRef& tx, NodeId peer) |
| 21 | { |
| 22 | AssertLockHeld(g_cs_orphans); |
| 23 | |
| 24 | const uint256& hash = tx->GetHash(); |
| 25 | if (m_orphans.count(hash)) |
| 26 | return false; |
| 27 | |
| 28 | // Ignore big transactions, to avoid a |
| 29 | // send-big-orphans memory exhaustion attack. If a peer has a legitimate |
| 30 | // large transaction with a missing parent then we assume |
| 31 | // it will rebroadcast it later, after the parent transaction(s) |
| 32 | // have been mined or received. |
| 33 | // 100 orphans, each of which is at most 100,000 bytes big is |
| 34 | // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case): |
| 35 | unsigned int sz = GetTransactionWeight(*tx); |
| 36 | if (sz > MAX_STANDARD_TX_WEIGHT) |
| 37 | { |
| 38 | LogPrint(BCLog::MEMPOOL, "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); |
| 39 | return false; |
| 40 | } |
| 41 | |
| 42 | auto ret = m_orphans.emplace(hash, OrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME, m_orphan_list.size()}); |
| 43 | assert(ret.second); |
| 44 | m_orphan_list.push_back(ret.first); |
| 45 | // Allow for lookups in the orphan pool by wtxid, as well as txid |
| 46 | m_wtxid_to_orphan_it.emplace(tx->GetWitnessHash(), ret.first); |
| 47 | for (const CTxIn& txin : tx->vin) { |
| 48 | m_outpoint_to_orphan_it[txin.prevout].insert(ret.first); |
| 49 | } |
| 50 | |
| 51 | LogPrint(BCLog::MEMPOOL, "stored orphan tx %s (mapsz %u outsz %u)\n", hash.ToString(), |
| 52 | m_orphans.size(), m_outpoint_to_orphan_it.size()); |
| 53 | return true; |
| 54 | } |
| 55 | |
| 56 | int TxOrphanage::EraseTx(const uint256& txid) |
| 57 | { |