| 1966 | } |
| 1967 | |
| 1968 | void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic<bool>& interruptMsgProc) |
| 1969 | { |
| 1970 | AssertLockNotHeld(cs_main); |
| 1971 | |
| 1972 | std::deque<CInv>::iterator it = peer.m_getdata_requests.begin(); |
| 1973 | std::vector<CInv> vNotFound; |
| 1974 | const CNetMsgMaker msgMaker(pfrom.GetCommonVersion()); |
| 1975 | |
| 1976 | const auto now{GetTime<std::chrono::seconds>()}; |
| 1977 | // Get last mempool request time |
| 1978 | const auto mempool_req = pfrom.m_tx_relay != nullptr ? pfrom.m_tx_relay->m_last_mempool_req.load() : std::chrono::seconds::min(); |
| 1979 | |
| 1980 | // Process as many TX items from the front of the getdata queue as |
| 1981 | // possible, since they're common and it's efficient to batch process |
| 1982 | // them. |
| 1983 | while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) { |
| 1984 | if (interruptMsgProc) return; |
| 1985 | // The send buffer provides backpressure. If there's no space in |
| 1986 | // the buffer, pause processing until the next call. |
| 1987 | if (pfrom.fPauseSend) break; |
| 1988 | |
| 1989 | const CInv &inv = *it++; |
| 1990 | |
| 1991 | if (pfrom.m_tx_relay == nullptr) { |
| 1992 | // Ignore GETDATA requests for transactions from blocks-only peers. |
| 1993 | continue; |
| 1994 | } |
| 1995 | |
| 1996 | CTransactionRef tx = FindTxForGetData(pfrom, ToGenTxid(inv), mempool_req, now); |
| 1997 | if (tx) { |
| 1998 | // WTX and WITNESS_TX imply we serialize with witness |
| 1999 | int nSendFlags = (inv.IsMsgTx() ? SERIALIZE_TRANSACTION_NO_WITNESS : 0); |
| 2000 | m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *tx)); |
| 2001 | m_mempool.RemoveUnbroadcastTx(tx->GetHash()); |
| 2002 | // As we're going to send tx, make sure its unconfirmed parents are made requestable. |
| 2003 | std::vector<uint256> parent_ids_to_add; |
| 2004 | { |
| 2005 | LOCK(m_mempool.cs); |
| 2006 | auto txiter = m_mempool.GetIter(tx->GetHash()); |
| 2007 | if (txiter) { |
| 2008 | const CTxMemPoolEntry::Parents& parents = (*txiter)->GetMemPoolParentsConst(); |
| 2009 | parent_ids_to_add.reserve(parents.size()); |
| 2010 | for (const CTxMemPoolEntry& parent : parents) { |
| 2011 | if (parent.GetTime() > now - UNCONDITIONAL_RELAY_DELAY) { |
| 2012 | parent_ids_to_add.push_back(parent.GetTx().GetHash()); |
| 2013 | } |
| 2014 | } |
| 2015 | } |
| 2016 | } |
| 2017 | for (const uint256& parent_txid : parent_ids_to_add) { |
| 2018 | // Relaying a transaction with a recent but unconfirmed parent. |
| 2019 | if (WITH_LOCK(pfrom.m_tx_relay->cs_tx_inventory, return !pfrom.m_tx_relay->filterInventoryKnown.contains(parent_txid))) { |
| 2020 | LOCK(cs_main); |
| 2021 | State(pfrom.GetId())->m_recently_announced_invs.insert(parent_txid); |
| 2022 | } |
| 2023 | } |
| 2024 | } else { |
| 2025 | vNotFound.push_back(inv); |
nothing calls this directly
no test coverage detected