Skip to content

Commit 9db82f1

Browse files
committed
[net processing] Don't initialize TxRelay for non-tx-relay peers.
Delay initializing the TxRelay data structure for a peer until we receive a version message from that peer. At that point we'll know whether it will ever relay transactions. We only initialize the m_tx_relay data structure if: - this isn't an outbound block-relay-only connection; AND - fRelay=true OR we're offering NODE_BLOOM to this peer (NODE_BLOOM means that the peer may turn on tx relay later)
1 parent b0a4ac9 commit 9db82f1

File tree

1 file changed

+32
-16
lines changed

1 file changed

+32
-16
lines changed

src/net_processing.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

359368
using 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

Comments
 (0)