@@ -280,12 +280,14 @@ struct Peer {
280
280
std::atomic<CAmount> m_fee_filter_received{0 };
281
281
};
282
282
283
- Mutex m_tx_relay_mutex;
284
-
285
- /* * Transaction relay data. Will be a nullptr if we're not relaying
286
- * transactions with this peer (e.g. if it's a block-relay-only peer).
287
- * Users should access this with the GetTxRelay() getter. */
288
- std::unique_ptr<TxRelay> m_tx_relay GUARDED_BY (m_tx_relay_mutex);
283
+ /* Initializes a TxRelay struct for this peer. Can be called at most once for a peer. */
284
+ TxRelay* SetTxRelay ()
285
+ {
286
+ LOCK (m_tx_relay_mutex);
287
+ Assume (!m_tx_relay);
288
+ m_tx_relay = std::make_unique<Peer::TxRelay>();
289
+ return m_tx_relay.get ();
290
+ };
289
291
290
292
TxRelay* GetTxRelay ()
291
293
{
@@ -350,10 +352,17 @@ struct Peer {
350
352
/* * Work queue of items requested by this peer **/
351
353
std::deque<CInv> m_getdata_requests GUARDED_BY (m_getdata_requests_mutex);
352
354
353
- explicit Peer (NodeId id, bool tx_relay)
354
- : m_id(id)
355
- , m_tx_relay(tx_relay ? std::make_unique<TxRelay>() : nullptr)
355
+ Peer (NodeId id)
356
+ : m_id{id}
356
357
{}
358
+
359
+ private:
360
+ Mutex m_tx_relay_mutex;
361
+
362
+ /* * Transaction relay data. Will be a nullptr if we're not relaying
363
+ * transactions with this peer (e.g. if it's a block-relay-only peer or
364
+ * the peer has sent us fRelay=false with bloom filters disabled). */
365
+ std::unique_ptr<TxRelay> m_tx_relay GUARDED_BY (m_tx_relay_mutex);
357
366
};
358
367
359
368
using PeerRef = std::shared_ptr<Peer>;
@@ -1210,7 +1219,7 @@ void PeerManagerImpl::PushNodeVersion(CNode& pnode, const Peer& peer)
1210
1219
CService addr_you = addr.IsRoutable () && !IsProxy (addr) && addr.IsAddrV1Compatible () ? addr : CService ();
1211
1220
uint64_t your_services{addr.nServices };
1212
1221
1213
- const bool tx_relay = !m_ignore_incoming_txs && peer. m_tx_relay != nullptr && !pnode.IsFeelerConn ();
1222
+ const bool tx_relay = !m_ignore_incoming_txs && !pnode. IsBlockOnlyConn () && !pnode.IsFeelerConn ();
1214
1223
m_connman.PushMessage (&pnode, CNetMsgMaker (INIT_PROTO_VERSION).Make (NetMsgType::VERSION, PROTOCOL_VERSION, my_services, nTime,
1215
1224
your_services, addr_you, // Together the pre-version-31402 serialization of CAddress "addrYou" (without nTime)
1216
1225
my_services, CService (), // Together the pre-version-31402 serialization of CAddress "addrMe" (without nTime)
@@ -1265,7 +1274,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode)
1265
1274
m_node_states.emplace_hint (m_node_states.end (), std::piecewise_construct, std::forward_as_tuple (nodeid), std::forward_as_tuple (pnode->IsInboundConn ()));
1266
1275
assert (m_txrequest.Count (nodeid) == 0 );
1267
1276
}
1268
- PeerRef peer = std::make_shared<Peer>(nodeid, /* tx_relay= */ !pnode-> IsBlockOnlyConn () );
1277
+ PeerRef peer = std::make_shared<Peer>(nodeid);
1269
1278
{
1270
1279
LOCK (m_peer_mutex);
1271
1280
m_peer_map.emplace_hint (m_peer_map.end (), nodeid, peer);
@@ -2085,7 +2094,8 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
2085
2094
const CInv &inv = *it++;
2086
2095
2087
2096
if (tx_relay == nullptr ) {
2088
- // Ignore GETDATA requests for transactions from blocks-only peers.
2097
+ // Ignore GETDATA requests for transactions from block-relay-only
2098
+ // peers and peers that asked us not to announce transactions.
2089
2099
continue ;
2090
2100
}
2091
2101
@@ -2748,7 +2758,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
2748
2758
// set nodes not capable of serving the complete blockchain history as "limited nodes"
2749
2759
pfrom.m_limited_node = (!(nServices & NODE_NETWORK) && (nServices & NODE_NETWORK_LIMITED));
2750
2760
2751
- if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
2761
+ // We only initialize the m_tx_relay data structure if:
2762
+ // - this isn't an outbound block-relay-only connection; and
2763
+ // - fRelay=true or we're offering NODE_BLOOM to this peer
2764
+ // (NODE_BLOOM means that the peer may turn on tx relay later)
2765
+ if (!pfrom.IsBlockOnlyConn () &&
2766
+ (fRelay || (pfrom.GetLocalServices () & NODE_BLOOM))) {
2767
+ auto * const tx_relay = peer->SetTxRelay ();
2752
2768
{
2753
2769
LOCK (tx_relay->m_bloom_filter_mutex );
2754
2770
tx_relay->m_relay_txs = fRelay ; // set to true after we get the first filter* message
@@ -3081,7 +3097,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3081
3097
3082
3098
// Reject tx INVs when the -blocksonly setting is enabled, or this is a
3083
3099
// block-relay-only peer
3084
- bool reject_tx_invs{m_ignore_incoming_txs || (peer-> GetTxRelay () == nullptr )};
3100
+ bool reject_tx_invs{m_ignore_incoming_txs || pfrom. IsBlockOnlyConn ( )};
3085
3101
3086
3102
// Allow peers with relay permission to send data other than blocks in blocks only mode
3087
3103
if (pfrom.HasPermission (NetPermissionFlags::Relay)) {
@@ -3356,9 +3372,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3356
3372
3357
3373
if (msg_type == NetMsgType::TX) {
3358
3374
// Stop processing the transaction early if
3359
- // 1) We are in blocks only mode and peer has no relay permission
3375
+ // 1) We are in blocks only mode and peer has no relay permission; OR
3360
3376
// 2) This peer is a block-relay-only peer
3361
- if ((m_ignore_incoming_txs && !pfrom.HasPermission (NetPermissionFlags::Relay)) || (peer-> GetTxRelay () == nullptr )) {
3377
+ if ((m_ignore_incoming_txs && !pfrom.HasPermission (NetPermissionFlags::Relay)) || pfrom. IsBlockOnlyConn ( )) {
3362
3378
LogPrint (BCLog::NET, " transaction sent in violation of protocol peer=%d\n " , pfrom.GetId ());
3363
3379
pfrom.fDisconnect = true ;
3364
3380
return ;
0 commit comments