5151#include < optional>
5252#include < typeinfo>
5353
54- /* * How long a transaction has to be in the mempool before it can unconditionally be relayed. */
55- static constexpr auto UNCONDITIONAL_RELAY_DELAY = 2min;
5654/* * Headers download timeout.
5755 * Timeout = base + per_header * (expected number of headers) */
5856static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE = 15min;
@@ -149,15 +147,12 @@ static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL{2s};
149147/* * Maximum rate of inventory items to send per second.
150148 * Limits the impact of low-fee transaction floods. */
151149static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND = 7 ;
150+ /* * Target number of tx inventory items to send per transmission. */
151+ static constexpr unsigned int INVENTORY_BROADCAST_TARGET = INVENTORY_BROADCAST_PER_SECOND * count_seconds (INBOUND_INVENTORY_BROADCAST_INTERVAL);
152152/* * Maximum number of inventory items to send per transmission. */
153- static constexpr unsigned int INVENTORY_BROADCAST_MAX = INVENTORY_BROADCAST_PER_SECOND * count_seconds (INBOUND_INVENTORY_BROADCAST_INTERVAL);
154- /* * The number of most recently announced transactions a peer can request. */
155- static constexpr unsigned int INVENTORY_MAX_RECENT_RELAY = 3500 ;
156- /* * Verify that INVENTORY_MAX_RECENT_RELAY is enough to cache everything typically
157- * relayed before unconditional relay from the mempool kicks in. This is only a
158- * lower bound, and it should be larger to account for higher inv rate to outbound
159- * peers, and random variations in the broadcast mechanism. */
160- static_assert (INVENTORY_MAX_RECENT_RELAY >= INVENTORY_BROADCAST_PER_SECOND * UNCONDITIONAL_RELAY_DELAY / std::chrono::seconds{1 }, " INVENTORY_RELAY_MAX too low" );
153+ static constexpr unsigned int INVENTORY_BROADCAST_MAX = 1000 ;
154+ static_assert (INVENTORY_BROADCAST_MAX >= INVENTORY_BROADCAST_TARGET, " INVENTORY_BROADCAST_MAX too low" );
155+ static_assert (INVENTORY_BROADCAST_MAX <= MAX_PEER_TX_ANNOUNCEMENTS, " INVENTORY_BROADCAST_MAX too high" );
161156/* * Average delay between feefilter broadcasts in seconds. */
162157static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL{10min};
163158/* * Maximum feefilter broadcast delay after significant change. */
@@ -273,13 +268,10 @@ struct Peer {
273268 /* * A bloom filter for which transactions to announce to the peer. See BIP37. */
274269 std::unique_ptr<CBloomFilter> m_bloom_filter PT_GUARDED_BY (m_bloom_filter_mutex) GUARDED_BY(m_bloom_filter_mutex){nullptr };
275270
276- /* * A rolling bloom filter of all announced tx CInvs to this peer */
277- CRollingBloomFilter m_recently_announced_invs GUARDED_BY (NetEventsInterface::g_msgproc_mutex){INVENTORY_MAX_RECENT_RELAY, 0.000001 };
278-
279271 mutable RecursiveMutex m_tx_inventory_mutex;
280- /* * A filter of all the txids and wtxids that the peer has announced to
272+ /* * A filter of all the (w) txids that the peer has announced to
281273 * us or we have announced to the peer. We use this to avoid announcing
282- * the same txid/wtxid to a peer that already has the transaction. */
274+ * the same (w) txid to a peer that already has the transaction. */
283275 CRollingBloomFilter m_tx_inventory_known_filter GUARDED_BY (m_tx_inventory_mutex){50000 , 0.000001 };
284276 /* * Set of transaction ids we still have to announce (txid for
285277 * non-wtxid-relay peers, wtxid for wtxid-relay peers). We use the
@@ -290,11 +282,12 @@ struct Peer {
290282 * permitted if the peer has NetPermissionFlags::Mempool or we advertise
291283 * NODE_BLOOM. See BIP35. */
292284 bool m_send_mempool GUARDED_BY (m_tx_inventory_mutex){false };
293- /* * The last time a BIP35 `mempool` request was serviced. */
294- std::atomic<std::chrono::seconds> m_last_mempool_req{0s};
295285 /* * The next time after which we will send an `inv` message containing
296286 * transaction announcements to this peer. */
297287 std::chrono::microseconds m_next_inv_send_time GUARDED_BY (m_tx_inventory_mutex){0 };
288+ /* * The mempool sequence num at which we sent the last `inv` message to this peer.
289+ * Can relay txs with lower sequence numbers than this (see CTxMempool::info_for_relay). */
290+ uint64_t m_last_inv_sequence GUARDED_BY (NetEventsInterface::g_msgproc_mutex){1 };
298291
299292 /* * Minimum fee rate with which to filter transaction announcements to this node. See BIP133. */
300293 std::atomic<CAmount> m_fee_filter_received{0 };
@@ -907,7 +900,7 @@ class PeerManagerImpl final : public PeerManager
907900 std::atomic<std::chrono::seconds> m_last_tip_update{0s};
908901
909902 /* * Determine whether or not a peer can request a transaction, and return it (or nullptr if not found or not allowed). */
910- CTransactionRef FindTxForGetData (const Peer::TxRelay& tx_relay, const GenTxid& gtxid, const std::chrono::seconds mempool_req, const std::chrono::seconds now )
903+ CTransactionRef FindTxForGetData (const Peer::TxRelay& tx_relay, const GenTxid& gtxid)
911904 EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex, NetEventsInterface::g_msgproc_mutex);
912905
913906 void ProcessGetData (CNode& pfrom, Peer& peer, const std::atomic<bool >& interruptMsgProc)
@@ -2288,22 +2281,14 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
22882281 }
22892282}
22902283
2291- CTransactionRef PeerManagerImpl::FindTxForGetData (const Peer::TxRelay& tx_relay, const GenTxid& gtxid, const std::chrono::seconds mempool_req, const std::chrono::seconds now )
2284+ CTransactionRef PeerManagerImpl::FindTxForGetData (const Peer::TxRelay& tx_relay, const GenTxid& gtxid)
22922285{
2293- auto txinfo = m_mempool.info (gtxid);
2286+ // If a tx was in the mempool prior to the last INV for this peer, permit the request.
2287+ auto txinfo = m_mempool.info_for_relay (gtxid, tx_relay.m_last_inv_sequence );
22942288 if (txinfo.tx ) {
2295- // If a TX could have been INVed in reply to a MEMPOOL request,
2296- // or is older than UNCONDITIONAL_RELAY_DELAY, permit the request
2297- // unconditionally.
2298- if ((mempool_req.count () && txinfo.m_time <= mempool_req) || txinfo.m_time <= now - UNCONDITIONAL_RELAY_DELAY) {
2299- return std::move (txinfo.tx );
2300- }
2289+ return std::move (txinfo.tx );
23012290 }
23022291
2303- // Otherwise, the transaction might have been announced recently.
2304- bool recent = tx_relay.m_recently_announced_invs .contains (gtxid.GetHash ());
2305- if (recent && txinfo.tx ) return std::move (txinfo.tx );
2306-
23072292 // Or it might be from the most recent block
23082293 {
23092294 LOCK (m_most_recent_block_mutex);
@@ -2326,10 +2311,6 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
23262311 std::vector<CInv> vNotFound;
23272312 const CNetMsgMaker msgMaker (pfrom.GetCommonVersion ());
23282313
2329- const auto now{GetTime<std::chrono::seconds>()};
2330- // Get last mempool request time
2331- const auto mempool_req = tx_relay != nullptr ? tx_relay->m_last_mempool_req .load () : std::chrono::seconds::min ();
2332-
23332314 // Process as many TX items from the front of the getdata queue as
23342315 // possible, since they're common and it's efficient to batch process
23352316 // them.
@@ -2347,33 +2328,12 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
23472328 continue ;
23482329 }
23492330
2350- CTransactionRef tx = FindTxForGetData (*tx_relay, ToGenTxid (inv), mempool_req, now );
2331+ CTransactionRef tx = FindTxForGetData (*tx_relay, ToGenTxid (inv));
23512332 if (tx) {
23522333 // WTX and WITNESS_TX imply we serialize with witness
23532334 int nSendFlags = (inv.IsMsgTx () ? SERIALIZE_TRANSACTION_NO_WITNESS : 0 );
23542335 m_connman.PushMessage (&pfrom, msgMaker.Make (nSendFlags, NetMsgType::TX, *tx));
23552336 m_mempool.RemoveUnbroadcastTx (tx->GetHash ());
2356- // As we're going to send tx, make sure its unconfirmed parents are made requestable.
2357- std::vector<uint256> parent_ids_to_add;
2358- {
2359- LOCK (m_mempool.cs );
2360- auto tx_iter = m_mempool.GetIter (tx->GetHash ());
2361- if (tx_iter) {
2362- const CTxMemPoolEntry::Parents& parents = (*tx_iter)->GetMemPoolParentsConst ();
2363- parent_ids_to_add.reserve (parents.size ());
2364- for (const CTxMemPoolEntry& parent : parents) {
2365- if (parent.GetTime () > now - UNCONDITIONAL_RELAY_DELAY) {
2366- parent_ids_to_add.push_back (parent.GetTx ().GetHash ());
2367- }
2368- }
2369- }
2370- }
2371- for (const uint256& parent_txid : parent_ids_to_add) {
2372- // Relaying a transaction with a recent but unconfirmed parent.
2373- if (WITH_LOCK (tx_relay->m_tx_inventory_mutex , return !tx_relay->m_tx_inventory_known_filter .contains (parent_txid))) {
2374- tx_relay->m_recently_announced_invs .insert (parent_txid);
2375- }
2376- }
23772337 } else {
23782338 vNotFound.push_back (inv);
23792339 }
@@ -4131,14 +4091,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
41314091
41324092 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
41334093 AddKnownTx (*peer, hash);
4134- if (peer->m_wtxid_relay && txid != wtxid) {
4135- // Insert txid into m_tx_inventory_known_filter, even for
4136- // wtxidrelay peers. This prevents re-adding of
4137- // unconfirmed parents to the recently_announced
4138- // filter, when a child tx is requested. See
4139- // ProcessGetData().
4140- AddKnownTx (*peer, txid);
4141- }
41424094
41434095 LOCK (cs_main);
41444096
@@ -5684,7 +5636,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
56845636 std::vector<CInv> vInv;
56855637 {
56865638 LOCK (peer->m_block_inv_mutex );
5687- vInv.reserve (std::max<size_t >(peer->m_blocks_for_inv_relay .size (), INVENTORY_BROADCAST_MAX ));
5639+ vInv.reserve (std::max<size_t >(peer->m_blocks_for_inv_relay .size (), INVENTORY_BROADCAST_TARGET ));
56885640
56895641 // Add blocks
56905642 for (const uint256& hash : peer->m_blocks_for_inv_relay ) {
@@ -5736,14 +5688,12 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
57365688 if (!tx_relay->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
57375689 }
57385690 tx_relay->m_tx_inventory_known_filter .insert (hash);
5739- // Responses to MEMPOOL requests bypass the m_recently_announced_invs filter.
57405691 vInv.push_back (inv);
57415692 if (vInv.size () == MAX_INV_SZ) {
57425693 m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::INV, vInv));
57435694 vInv.clear ();
57445695 }
57455696 }
5746- tx_relay->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time);
57475697 }
57485698
57495699 // Determine transactions to relay
@@ -5763,8 +5713,8 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
57635713 // especially since we have many peers and some will draw much shorter delays.
57645714 unsigned int nRelayedTransactions = 0 ;
57655715 LOCK (tx_relay->m_bloom_filter_mutex );
5766- size_t broadcast_max{INVENTORY_BROADCAST_MAX + (tx_relay->m_tx_inventory_to_send .size ()/1000 )*5 };
5767- broadcast_max = std::min<size_t >(1000 , broadcast_max);
5716+ size_t broadcast_max{INVENTORY_BROADCAST_TARGET + (tx_relay->m_tx_inventory_to_send .size ()/1000 )*5 };
5717+ broadcast_max = std::min<size_t >(INVENTORY_BROADCAST_MAX , broadcast_max);
57685718 while (!vInvTx.empty () && nRelayedTransactions < broadcast_max) {
57695719 // Fetch the top element from the heap
57705720 std::pop_heap (vInvTx.begin (), vInvTx.end (), compareInvMempoolOrder);
@@ -5783,30 +5733,24 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
57835733 if (!txinfo.tx ) {
57845734 continue ;
57855735 }
5786- auto txid = txinfo.tx ->GetHash ();
57875736 // Peer told you to not send transactions at that feerate? Don't bother sending it.
57885737 if (txinfo.fee < filterrate.GetFee (txinfo.vsize )) {
57895738 continue ;
57905739 }
57915740 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
57925741 // Send
5793- tx_relay->m_recently_announced_invs .insert (hash);
57945742 vInv.push_back (inv);
57955743 nRelayedTransactions++;
57965744 if (vInv.size () == MAX_INV_SZ) {
57975745 m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::INV, vInv));
57985746 vInv.clear ();
57995747 }
58005748 tx_relay->m_tx_inventory_known_filter .insert (hash);
5801- if (hash != txid) {
5802- // Insert txid into m_tx_inventory_known_filter, even for
5803- // wtxidrelay peers. This prevents re-adding of
5804- // unconfirmed parents to the recently_announced
5805- // filter, when a child tx is requested. See
5806- // ProcessGetData().
5807- tx_relay->m_tx_inventory_known_filter .insert (txid);
5808- }
58095749 }
5750+
5751+ // Ensure we'll respond to GETDATA requests for anything we've just announced
5752+ LOCK (m_mempool.cs );
5753+ tx_relay->m_last_inv_sequence = m_mempool.GetSequence ();
58105754 }
58115755 }
58125756 if (!vInv.empty ())
0 commit comments