aboutsummaryrefslogtreecommitdiff
path: root/src/net_processing.cpp
diff options
context:
space:
mode:
authorJohn Newbery <john@johnnewbery.com>2021-02-06 00:50:46 +0000
committerJohn Newbery <john@johnnewbery.com>2022-05-18 17:08:24 +0100
commit9db82f1bca0bb51c2180ca4a4ad63ba490e79da4 (patch)
tree05b2db770be69d70c1a99819126006c43a5ce971 /src/net_processing.cpp
parentb0a4ac9c26f60fd4993d89f45cafffaa389db2d4 (diff)
downloadbitcoin-9db82f1bca0bb51c2180ca4a4ad63ba490e79da4.tar.xz
[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)
Diffstat (limited to 'src/net_processing.cpp')
-rw-r--r--src/net_processing.cpp48
1 files changed, 32 insertions, 16 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 379b12f840..ae6ab8553a 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -280,12 +280,14 @@ struct Peer {
std::atomic<CAmount> m_fee_filter_received{0};
};
- Mutex m_tx_relay_mutex;
-
- /** Transaction relay data. Will be a nullptr if we're not relaying
- * transactions with this peer (e.g. if it's a block-relay-only peer).
- * Users should access this with the GetTxRelay() getter. */
- std::unique_ptr<TxRelay> m_tx_relay GUARDED_BY(m_tx_relay_mutex);
+ /* Initializes a TxRelay struct for this peer. Can be called at most once for a peer. */
+ TxRelay* SetTxRelay()
+ {
+ LOCK(m_tx_relay_mutex);
+ Assume(!m_tx_relay);
+ m_tx_relay = std::make_unique<Peer::TxRelay>();
+ return m_tx_relay.get();
+ };
TxRelay* GetTxRelay()
{
@@ -350,10 +352,17 @@ struct Peer {
/** Work queue of items requested by this peer **/
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
- explicit Peer(NodeId id, bool tx_relay)
- : m_id(id)
- , m_tx_relay(tx_relay ? std::make_unique<TxRelay>() : nullptr)
+ Peer(NodeId id)
+ : m_id{id}
{}
+
+private:
+ Mutex m_tx_relay_mutex;
+
+ /** Transaction relay data. Will be a nullptr if we're not relaying
+ * transactions with this peer (e.g. if it's a block-relay-only peer or
+ * the peer has sent us fRelay=false with bloom filters disabled). */
+ std::unique_ptr<TxRelay> m_tx_relay GUARDED_BY(m_tx_relay_mutex);
};
using PeerRef = std::shared_ptr<Peer>;
@@ -1210,7 +1219,7 @@ void PeerManagerImpl::PushNodeVersion(CNode& pnode, const Peer& peer)
CService addr_you = addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible() ? addr : CService();
uint64_t your_services{addr.nServices};
- const bool tx_relay = !m_ignore_incoming_txs && peer.m_tx_relay != nullptr && !pnode.IsFeelerConn();
+ const bool tx_relay = !m_ignore_incoming_txs && !pnode.IsBlockOnlyConn() && !pnode.IsFeelerConn();
m_connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, my_services, nTime,
your_services, addr_you, // Together the pre-version-31402 serialization of CAddress "addrYou" (without nTime)
my_services, CService(), // Together the pre-version-31402 serialization of CAddress "addrMe" (without nTime)
@@ -1265,7 +1274,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode)
m_node_states.emplace_hint(m_node_states.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(pnode->IsInboundConn()));
assert(m_txrequest.Count(nodeid) == 0);
}
- PeerRef peer = std::make_shared<Peer>(nodeid, /*tx_relay=*/ !pnode->IsBlockOnlyConn());
+ PeerRef peer = std::make_shared<Peer>(nodeid);
{
LOCK(m_peer_mutex);
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
const CInv &inv = *it++;
if (tx_relay == nullptr) {
- // Ignore GETDATA requests for transactions from blocks-only peers.
+ // Ignore GETDATA requests for transactions from block-relay-only
+ // peers and peers that asked us not to announce transactions.
continue;
}
@@ -2748,7 +2758,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// set nodes not capable of serving the complete blockchain history as "limited nodes"
pfrom.m_limited_node = (!(nServices & NODE_NETWORK) && (nServices & NODE_NETWORK_LIMITED));
- if (auto tx_relay = peer->GetTxRelay(); tx_relay != nullptr) {
+ // 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)
+ if (!pfrom.IsBlockOnlyConn() &&
+ (fRelay || (pfrom.GetLocalServices() & NODE_BLOOM))) {
+ auto* const tx_relay = peer->SetTxRelay();
{
LOCK(tx_relay->m_bloom_filter_mutex);
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,
// Reject tx INVs when the -blocksonly setting is enabled, or this is a
// block-relay-only peer
- bool reject_tx_invs{m_ignore_incoming_txs || (peer->GetTxRelay() == nullptr)};
+ bool reject_tx_invs{m_ignore_incoming_txs || pfrom.IsBlockOnlyConn()};
// Allow peers with relay permission to send data other than blocks in blocks only mode
if (pfrom.HasPermission(NetPermissionFlags::Relay)) {
@@ -3356,9 +3372,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (msg_type == NetMsgType::TX) {
// Stop processing the transaction early if
- // 1) We are in blocks only mode and peer has no relay permission
+ // 1) We are in blocks only mode and peer has no relay permission; OR
// 2) This peer is a block-relay-only peer
- if ((m_ignore_incoming_txs && !pfrom.HasPermission(NetPermissionFlags::Relay)) || (peer->GetTxRelay() == nullptr)) {
+ if ((m_ignore_incoming_txs && !pfrom.HasPermission(NetPermissionFlags::Relay)) || pfrom.IsBlockOnlyConn()) {
LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom.GetId());
pfrom.fDisconnect = true;
return;