51
51
#include < optional>
52
52
#include < typeinfo>
53
53
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;
56
54
/* * Headers download timeout.
57
55
* Timeout = base + per_header * (expected number of headers) */
58
56
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE = 15min;
@@ -149,15 +147,12 @@ static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL{2s};
149
147
/* * Maximum rate of inventory items to send per second.
150
148
* Limits the impact of low-fee transaction floods. */
151
149
static 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);
152
152
/* * 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" );
161
156
/* * Average delay between feefilter broadcasts in seconds. */
162
157
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL{10min};
163
158
/* * Maximum feefilter broadcast delay after significant change. */
@@ -273,13 +268,10 @@ struct Peer {
273
268
/* * A bloom filter for which transactions to announce to the peer. See BIP37. */
274
269
std::unique_ptr<CBloomFilter> m_bloom_filter PT_GUARDED_BY (m_bloom_filter_mutex) GUARDED_BY(m_bloom_filter_mutex){nullptr };
275
270
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
-
279
271
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
281
273
* 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. */
283
275
CRollingBloomFilter m_tx_inventory_known_filter GUARDED_BY (m_tx_inventory_mutex){50000 , 0.000001 };
284
276
/* * Set of transaction ids we still have to announce (txid for
285
277
* non-wtxid-relay peers, wtxid for wtxid-relay peers). We use the
@@ -290,11 +282,12 @@ struct Peer {
290
282
* permitted if the peer has NetPermissionFlags::Mempool or we advertise
291
283
* NODE_BLOOM. See BIP35. */
292
284
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};
295
285
/* * The next time after which we will send an `inv` message containing
296
286
* transaction announcements to this peer. */
297
287
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 };
298
291
299
292
/* * Minimum fee rate with which to filter transaction announcements to this node. See BIP133. */
300
293
std::atomic<CAmount> m_fee_filter_received{0 };
@@ -907,7 +900,7 @@ class PeerManagerImpl final : public PeerManager
907
900
std::atomic<std::chrono::seconds> m_last_tip_update{0s};
908
901
909
902
/* * 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)
911
904
EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex, NetEventsInterface::g_msgproc_mutex);
912
905
913
906
void ProcessGetData (CNode& pfrom, Peer& peer, const std::atomic<bool >& interruptMsgProc)
@@ -2288,22 +2281,14 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
2288
2281
}
2289
2282
}
2290
2283
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)
2292
2285
{
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 );
2294
2288
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 );
2301
2290
}
2302
2291
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
-
2307
2292
// Or it might be from the most recent block
2308
2293
{
2309
2294
LOCK (m_most_recent_block_mutex);
@@ -2326,10 +2311,6 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
2326
2311
std::vector<CInv> vNotFound;
2327
2312
const CNetMsgMaker msgMaker (pfrom.GetCommonVersion ());
2328
2313
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
-
2333
2314
// Process as many TX items from the front of the getdata queue as
2334
2315
// possible, since they're common and it's efficient to batch process
2335
2316
// them.
@@ -2347,33 +2328,12 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
2347
2328
continue ;
2348
2329
}
2349
2330
2350
- CTransactionRef tx = FindTxForGetData (*tx_relay, ToGenTxid (inv), mempool_req, now );
2331
+ CTransactionRef tx = FindTxForGetData (*tx_relay, ToGenTxid (inv));
2351
2332
if (tx) {
2352
2333
// WTX and WITNESS_TX imply we serialize with witness
2353
2334
int nSendFlags = (inv.IsMsgTx () ? SERIALIZE_TRANSACTION_NO_WITNESS : 0 );
2354
2335
m_connman.PushMessage (&pfrom, msgMaker.Make (nSendFlags, NetMsgType::TX, *tx));
2355
2336
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
- }
2377
2337
} else {
2378
2338
vNotFound.push_back (inv);
2379
2339
}
@@ -4131,14 +4091,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4131
4091
4132
4092
const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4133
4093
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
- }
4142
4094
4143
4095
LOCK (cs_main);
4144
4096
@@ -5684,7 +5636,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
5684
5636
std::vector<CInv> vInv;
5685
5637
{
5686
5638
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 ));
5688
5640
5689
5641
// Add blocks
5690
5642
for (const uint256& hash : peer->m_blocks_for_inv_relay ) {
@@ -5736,14 +5688,12 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
5736
5688
if (!tx_relay->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
5737
5689
}
5738
5690
tx_relay->m_tx_inventory_known_filter .insert (hash);
5739
- // Responses to MEMPOOL requests bypass the m_recently_announced_invs filter.
5740
5691
vInv.push_back (inv);
5741
5692
if (vInv.size () == MAX_INV_SZ) {
5742
5693
m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::INV, vInv));
5743
5694
vInv.clear ();
5744
5695
}
5745
5696
}
5746
- tx_relay->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time);
5747
5697
}
5748
5698
5749
5699
// Determine transactions to relay
@@ -5763,8 +5713,8 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
5763
5713
// especially since we have many peers and some will draw much shorter delays.
5764
5714
unsigned int nRelayedTransactions = 0 ;
5765
5715
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);
5768
5718
while (!vInvTx.empty () && nRelayedTransactions < broadcast_max) {
5769
5719
// Fetch the top element from the heap
5770
5720
std::pop_heap (vInvTx.begin (), vInvTx.end (), compareInvMempoolOrder);
@@ -5783,30 +5733,24 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
5783
5733
if (!txinfo.tx ) {
5784
5734
continue ;
5785
5735
}
5786
- auto txid = txinfo.tx ->GetHash ();
5787
5736
// Peer told you to not send transactions at that feerate? Don't bother sending it.
5788
5737
if (txinfo.fee < filterrate.GetFee (txinfo.vsize )) {
5789
5738
continue ;
5790
5739
}
5791
5740
if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
5792
5741
// Send
5793
- tx_relay->m_recently_announced_invs .insert (hash);
5794
5742
vInv.push_back (inv);
5795
5743
nRelayedTransactions++;
5796
5744
if (vInv.size () == MAX_INV_SZ) {
5797
5745
m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::INV, vInv));
5798
5746
vInv.clear ();
5799
5747
}
5800
5748
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
- }
5809
5749
}
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 ();
5810
5754
}
5811
5755
}
5812
5756
if (!vInv.empty ())
0 commit comments