| 2546 | } |
| 2547 | |
| 2548 | void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic<bool>& interruptMsgProc) |
| 2549 | { |
| 2550 | AssertLockNotHeld(cs_main); |
| 2551 | |
| 2552 | auto tx_relay = peer.GetTxRelay(); |
| 2553 | |
| 2554 | std::deque<CInv>::iterator it = peer.m_getdata_requests.begin(); |
| 2555 | std::vector<CInv> vNotFound; |
| 2556 | |
| 2557 | // Process as many TX items from the front of the getdata queue as |
| 2558 | // possible, since they're common and it's efficient to batch process |
| 2559 | // them. |
| 2560 | while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) { |
| 2561 | if (interruptMsgProc) return; |
| 2562 | // The send buffer provides backpressure. If there's no space in |
| 2563 | // the buffer, pause processing until the next call. |
| 2564 | if (pfrom.fPauseSend) break; |
| 2565 | |
| 2566 | const CInv &inv = *it++; |
| 2567 | |
| 2568 | if (tx_relay == nullptr) { |
| 2569 | // Ignore GETDATA requests for transactions from block-relay-only |
| 2570 | // peers and peers that asked us not to announce transactions. |
| 2571 | continue; |
| 2572 | } |
| 2573 | |
| 2574 | if (auto tx{FindTxForGetData(*tx_relay, ToGenTxid(inv))}) { |
| 2575 | // WTX and WITNESS_TX imply we serialize with witness |
| 2576 | const auto maybe_with_witness = (inv.IsMsgTx() ? TX_NO_WITNESS : TX_WITH_WITNESS); |
| 2577 | MakeAndPushMessage(pfrom, NetMsgType::TX, maybe_with_witness(*tx)); |
| 2578 | m_mempool.RemoveUnbroadcastTx(tx->GetHash()); |
| 2579 | } else { |
| 2580 | vNotFound.push_back(inv); |
| 2581 | } |
| 2582 | } |
| 2583 | |
| 2584 | // Only process one BLOCK item per call, since they're uncommon and can be |
| 2585 | // expensive to process. |
| 2586 | if (it != peer.m_getdata_requests.end() && !pfrom.fPauseSend) { |
| 2587 | const CInv &inv = *it++; |
| 2588 | if (inv.IsGenBlkMsg()) { |
| 2589 | ProcessGetBlockData(pfrom, peer, inv); |
| 2590 | } |
| 2591 | // else: If the first item on the queue is an unknown type, we erase it |
| 2592 | // and continue processing the queue on the next call. |
| 2593 | // NOTE: previously we wouldn't do so and the peer sending us a malformed GETDATA could |
| 2594 | // result in never making progress and this thread using 100% allocated CPU. See |
| 2595 | // https://bitcoincore.org/en/2024/07/03/disclose-getdata-cpu. |
| 2596 | } |
| 2597 | |
| 2598 | peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it); |
| 2599 | |
| 2600 | if (!vNotFound.empty()) { |
| 2601 | // Let the peer know that we didn't find what it asked for, so it doesn't |
| 2602 | // have to wait around forever. |
| 2603 | // SPV clients care about this message: it's needed when they are |
| 2604 | // recursively walking the dependencies of relevant unconfirmed |
| 2605 | // transactions. SPV clients want to do that because they want to know |
nothing calls this directly
no test coverage detected