@@ -280,12 +280,14 @@ struct Peer {
280280 std::atomic<CAmount> m_fee_filter_received{0 };
281281 };
282282
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+ };
289291
290292 TxRelay* GetTxRelay ()
291293 {
@@ -350,10 +352,17 @@ struct Peer {
350352 /* * Work queue of items requested by this peer **/
351353 std::deque<CInv> m_getdata_requests GUARDED_BY (m_getdata_requests_mutex);
352354
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}
356357 {}
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);
357366};
358367
359368using PeerRef = std::shared_ptr<Peer>;
@@ -1210,7 +1219,7 @@ void PeerManagerImpl::PushNodeVersion(CNode& pnode, const Peer& peer)
12101219 CService addr_you = addr.IsRoutable () && !IsProxy (addr) && addr.IsAddrV1Compatible () ? addr : CService ();
12111220 uint64_t your_services{addr.nServices };
12121221
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 ();
12141223 m_connman.PushMessage (&pnode, CNetMsgMaker (INIT_PROTO_VERSION).Make (NetMsgType::VERSION, PROTOCOL_VERSION, my_services, nTime,
12151224 your_services, addr_you, // Together the pre-version-31402 serialization of CAddress "addrYou" (without nTime)
12161225 my_services, CService (), // Together the pre-version-31402 serialization of CAddress "addrMe" (without nTime)
@@ -1265,7 +1274,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode)
12651274 m_node_states.emplace_hint (m_node_states.end (), std::piecewise_construct, std::forward_as_tuple (nodeid), std::forward_as_tuple (pnode->IsInboundConn ()));
12661275 assert (m_txrequest.Count (nodeid) == 0 );
12671276 }
1268- PeerRef peer = std::make_shared<Peer>(nodeid, /* tx_relay= */ !pnode-> IsBlockOnlyConn () );
1277+ PeerRef peer = std::make_shared<Peer>(nodeid);
12691278 {
12701279 LOCK (m_peer_mutex);
12711280 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
20852094 const CInv &inv = *it++;
20862095
20872096 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.
20892099 continue ;
20902100 }
20912101
@@ -2748,7 +2758,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
27482758 // set nodes not capable of serving the complete blockchain history as "limited nodes"
27492759 pfrom.m_limited_node = (!(nServices & NODE_NETWORK) && (nServices & NODE_NETWORK_LIMITED));
27502760
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 ();
27522768 {
27532769 LOCK (tx_relay->m_bloom_filter_mutex );
27542770 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,
30813097
30823098 // Reject tx INVs when the -blocksonly setting is enabled, or this is a
30833099 // 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 ( )};
30853101
30863102 // Allow peers with relay permission to send data other than blocks in blocks only mode
30873103 if (pfrom.HasPermission (NetPermissionFlags::Relay)) {
@@ -3356,9 +3372,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
33563372
33573373 if (msg_type == NetMsgType::TX) {
33583374 // 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
33603376 // 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 ( )) {
33623378 LogPrint (BCLog::NET, " transaction sent in violation of protocol peer=%d\n " , pfrom.GetId ());
33633379 pfrom.fDisconnect = true ;
33643380 return ;
0 commit comments