| 305 | } |
| 306 | |
| 307 | bool TxOrphanageImpl::AddTx(const CTransactionRef& tx, NodeId peer) |
| 308 | { |
| 309 | const auto& wtxid{tx->GetWitnessHash()}; |
| 310 | const auto& txid{tx->GetHash()}; |
| 311 | |
| 312 | // Ignore transactions above max standard size to avoid a send-big-orphans memory exhaustion attack. |
| 313 | TxOrphanage::Usage sz = GetTransactionWeight(*tx); |
| 314 | if (sz > MAX_STANDARD_TX_WEIGHT) { |
| 315 | LogDebug(BCLog::TXPACKAGES, "ignoring large orphan tx (size: %u, txid: %s, wtxid: %s)\n", sz, txid.ToString(), wtxid.ToString()); |
| 316 | return false; |
| 317 | } |
| 318 | |
| 319 | // We will return false if the tx already exists under a different peer. |
| 320 | const bool brand_new{!HaveTx(wtxid)}; |
| 321 | |
| 322 | auto [iter, inserted] = m_orphans.get<ByWtxid>().emplace(tx, peer, m_current_sequence); |
| 323 | // If the announcement (same wtxid, same peer) already exists, emplacement fails. Return false. |
| 324 | if (!inserted) return false; |
| 325 | |
| 326 | ++m_current_sequence; |
| 327 | auto& peer_info = m_peer_orphanage_info.try_emplace(peer).first->second; |
| 328 | peer_info.Add(*iter); |
| 329 | |
| 330 | // Add links in m_outpoint_to_orphan_wtxids |
| 331 | if (brand_new) { |
| 332 | for (const auto& input : tx->vin) { |
| 333 | auto& wtxids_for_prevout = m_outpoint_to_orphan_wtxids.try_emplace(input.prevout).first->second; |
| 334 | wtxids_for_prevout.emplace(wtxid); |
| 335 | } |
| 336 | |
| 337 | m_unique_orphans += 1; |
| 338 | m_unique_orphan_usage += iter->GetMemUsage(); |
| 339 | m_unique_rounded_input_scores += iter->GetLatencyScore() - 1; |
| 340 | |
| 341 | LogDebug(BCLog::TXPACKAGES, "stored orphan tx %s (wtxid=%s), weight: %u (mapsz %u outsz %u)\n", |
| 342 | txid.ToString(), wtxid.ToString(), sz, m_orphans.size(), m_outpoint_to_orphan_wtxids.size()); |
| 343 | Assume(IsUnique(iter)); |
| 344 | } else { |
| 345 | LogDebug(BCLog::TXPACKAGES, "added peer=%d as announcer of orphan tx %s (wtxid=%s)\n", |
| 346 | peer, txid.ToString(), wtxid.ToString()); |
| 347 | Assume(!IsUnique(iter)); |
| 348 | } |
| 349 | |
| 350 | // DoS prevention: do not allow m_orphanage to grow unbounded (see CVE-2012-3789) |
| 351 | LimitOrphans(); |
| 352 | return brand_new; |
| 353 | } |
| 354 | |
| 355 | bool TxOrphanageImpl::AddAnnouncer(const Wtxid& wtxid, NodeId peer) |
| 356 | { |