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;
@@ -151,13 +149,6 @@ static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL{2s};
151
149
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND = 7 ;
152
150
/* * Maximum number of inventory items to send per transmission. */
153
151
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" );
161
152
/* * Average delay between feefilter broadcasts in seconds. */
162
153
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL{10min};
163
154
/* * Maximum feefilter broadcast delay after significant change. */
@@ -273,9 +264,6 @@ struct Peer {
273
264
/* * A bloom filter for which transactions to announce to the peer. See BIP37. */
274
265
std::unique_ptr<CBloomFilter> m_bloom_filter PT_GUARDED_BY (m_bloom_filter_mutex) GUARDED_BY(m_bloom_filter_mutex){nullptr };
275
266
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
267
mutable RecursiveMutex m_tx_inventory_mutex;
280
268
/* * A filter of all the txids and wtxids that the peer has announced to
281
269
* us or we have announced to the peer. We use this to avoid announcing
@@ -290,11 +278,12 @@ struct Peer {
290
278
* permitted if the peer has NetPermissionFlags::Mempool or we advertise
291
279
* NODE_BLOOM. See BIP35. */
292
280
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
281
/* * The next time after which we will send an `inv` message containing
296
282
* transaction announcements to this peer. */
297
283
std::chrono::microseconds m_next_inv_send_time GUARDED_BY (m_tx_inventory_mutex){0 };
284
+ /* * The mempool sequence num at which we sent the last `inv` message to this peer.
285
+ * Can relay txs with lower sequence numbers than this (see CTxMempool::info_for_relay). */
286
+ uint64_t m_last_inv_sequence GUARDED_BY (NetEventsInterface::g_msgproc_mutex){1 };
298
287
299
288
/* * Minimum fee rate with which to filter transaction announcements to this node. See BIP133. */
300
289
std::atomic<CAmount> m_fee_filter_received{0 };
@@ -908,7 +897,7 @@ class PeerManagerImpl final : public PeerManager
908
897
std::atomic<std::chrono::seconds> m_last_tip_update{0s};
909
898
910
899
/* * Determine whether or not a peer can request a transaction, and return it (or nullptr if not found or not allowed). */
911
- CTransactionRef FindTxForGetData (const Peer::TxRelay& tx_relay, const GenTxid& gtxid, const std::chrono::seconds mempool_req, const std::chrono::seconds now )
900
+ CTransactionRef FindTxForGetData (const Peer::TxRelay& tx_relay, const GenTxid& gtxid)
912
901
EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex, NetEventsInterface::g_msgproc_mutex);
913
902
914
903
void ProcessGetData (CNode& pfrom, Peer& peer, const std::atomic<bool >& interruptMsgProc)
@@ -2290,22 +2279,14 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
2290
2279
}
2291
2280
}
2292
2281
2293
- CTransactionRef PeerManagerImpl::FindTxForGetData (const Peer::TxRelay& tx_relay, const GenTxid& gtxid, const std::chrono::seconds mempool_req, const std::chrono::seconds now )
2282
+ CTransactionRef PeerManagerImpl::FindTxForGetData (const Peer::TxRelay& tx_relay, const GenTxid& gtxid)
2294
2283
{
2295
- auto txinfo = m_mempool.info (gtxid);
2284
+ // If a tx was in the mempool prior to the last INV for this peer, permit the request.
2285
+ auto txinfo = m_mempool.info_for_relay (gtxid, tx_relay.m_last_inv_sequence );
2296
2286
if (txinfo.tx ) {
2297
- // If a TX could have been INVed in reply to a MEMPOOL request,
2298
- // or is older than UNCONDITIONAL_RELAY_DELAY, permit the request
2299
- // unconditionally.
2300
- if ((mempool_req.count () && txinfo.m_time <= mempool_req) || txinfo.m_time <= now - UNCONDITIONAL_RELAY_DELAY) {
2301
- return std::move (txinfo.tx );
2302
- }
2287
+ return std::move (txinfo.tx );
2303
2288
}
2304
2289
2305
- // Otherwise, the transaction might have been announced recently.
2306
- bool recent = tx_relay.m_recently_announced_invs .contains (gtxid.GetHash ());
2307
- if (recent && txinfo.tx ) return std::move (txinfo.tx );
2308
-
2309
2290
// Or it might be from the most recent block
2310
2291
{
2311
2292
LOCK (m_most_recent_block_mutex);
@@ -2328,10 +2309,6 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
2328
2309
std::vector<CInv> vNotFound;
2329
2310
const CNetMsgMaker msgMaker (pfrom.GetCommonVersion ());
2330
2311
2331
- const auto now{GetTime<std::chrono::seconds>()};
2332
- // Get last mempool request time
2333
- const auto mempool_req = tx_relay != nullptr ? tx_relay->m_last_mempool_req .load () : std::chrono::seconds::min ();
2334
-
2335
2312
// Process as many TX items from the front of the getdata queue as
2336
2313
// possible, since they're common and it's efficient to batch process
2337
2314
// them.
@@ -2349,33 +2326,12 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
2349
2326
continue ;
2350
2327
}
2351
2328
2352
- CTransactionRef tx = FindTxForGetData (*tx_relay, ToGenTxid (inv), mempool_req, now );
2329
+ CTransactionRef tx = FindTxForGetData (*tx_relay, ToGenTxid (inv));
2353
2330
if (tx) {
2354
2331
// WTX and WITNESS_TX imply we serialize with witness
2355
2332
int nSendFlags = (inv.IsMsgTx () ? SERIALIZE_TRANSACTION_NO_WITNESS : 0 );
2356
2333
m_connman.PushMessage (&pfrom, msgMaker.Make (nSendFlags, NetMsgType::TX, *tx));
2357
2334
m_mempool.RemoveUnbroadcastTx (tx->GetHash ());
2358
- // As we're going to send tx, make sure its unconfirmed parents are made requestable.
2359
- std::vector<uint256> parent_ids_to_add;
2360
- {
2361
- LOCK (m_mempool.cs );
2362
- auto tx_iter = m_mempool.GetIter (tx->GetHash ());
2363
- if (tx_iter) {
2364
- const CTxMemPoolEntry::Parents& parents = (*tx_iter)->GetMemPoolParentsConst ();
2365
- parent_ids_to_add.reserve (parents.size ());
2366
- for (const CTxMemPoolEntry& parent : parents) {
2367
- if (parent.GetTime () > now - UNCONDITIONAL_RELAY_DELAY) {
2368
- parent_ids_to_add.push_back (parent.GetTx ().GetHash ());
2369
- }
2370
- }
2371
- }
2372
- }
2373
- for (const uint256& parent_txid : parent_ids_to_add) {
2374
- // Relaying a transaction with a recent but unconfirmed parent.
2375
- if (WITH_LOCK (tx_relay->m_tx_inventory_mutex , return !tx_relay->m_tx_inventory_known_filter .contains (parent_txid))) {
2376
- tx_relay->m_recently_announced_invs .insert (parent_txid);
2377
- }
2378
- }
2379
2335
} else {
2380
2336
vNotFound.push_back (inv);
2381
2337
}
@@ -5734,14 +5690,12 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
5734
5690
if (!tx_relay->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
5735
5691
}
5736
5692
tx_relay->m_tx_inventory_known_filter .insert (hash);
5737
- // Responses to MEMPOOL requests bypass the m_recently_announced_invs filter.
5738
5693
vInv.push_back (inv);
5739
5694
if (vInv.size () == MAX_INV_SZ) {
5740
5695
m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::INV, vInv));
5741
5696
vInv.clear ();
5742
5697
}
5743
5698
}
5744
- tx_relay->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time);
5745
5699
}
5746
5700
5747
5701
// Determine transactions to relay
@@ -5781,30 +5735,32 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
5781
5735
if (!txinfo.tx ) {
5782
5736
continue ;
5783
5737
}
5784
- auto txid = txinfo.tx ->GetHash ();
5785
5738
// Peer told you to not send transactions at that feerate? Don't bother sending it.
5786
5739
if (txinfo.fee < filterrate.GetFee (txinfo.vsize )) {
5787
5740
continue ;
5788
5741
}
5789
5742
if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter ->IsRelevantAndUpdate (*txinfo.tx )) continue ;
5790
5743
// Send
5791
- tx_relay->m_recently_announced_invs .insert (hash);
5792
5744
vInv.push_back (inv);
5793
5745
nRelayedTransactions++;
5794
5746
if (vInv.size () == MAX_INV_SZ) {
5795
5747
m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::INV, vInv));
5796
5748
vInv.clear ();
5797
5749
}
5798
5750
tx_relay->m_tx_inventory_known_filter .insert (hash);
5799
- if (hash != txid ) {
5751
+ if (peer-> m_wtxid_relay && hash != txinfo. tx -> GetHash () ) {
5800
5752
// Insert txid into m_tx_inventory_known_filter, even for
5801
5753
// wtxidrelay peers. This prevents re-adding of
5802
5754
// unconfirmed parents to the recently_announced
5803
5755
// filter, when a child tx is requested. See
5804
5756
// ProcessGetData().
5805
- tx_relay->m_tx_inventory_known_filter .insert (txid );
5757
+ tx_relay->m_tx_inventory_known_filter .insert (txinfo. tx -> GetHash () );
5806
5758
}
5807
5759
}
5760
+
5761
+ // Ensure we'll respond to GETDATA requests for anything we've just announced
5762
+ LOCK (m_mempool.cs );
5763
+ tx_relay->m_last_inv_sequence = m_mempool.GetSequence ();
5808
5764
}
5809
5765
}
5810
5766
if (!vInv.empty ())
0 commit comments