mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-03 09:56:38 -05:00
[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)
This commit is contained in:
parent
b0a4ac9c26
commit
9db82f1bca
1 changed files with 32 additions and 16 deletions
|
@ -280,12 +280,14 @@ struct Peer {
|
||||||
std::atomic<CAmount> m_fee_filter_received{0};
|
std::atomic<CAmount> m_fee_filter_received{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
Mutex m_tx_relay_mutex;
|
/* Initializes a TxRelay struct for this peer. Can be called at most once for a peer. */
|
||||||
|
TxRelay* SetTxRelay()
|
||||||
/** 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).
|
LOCK(m_tx_relay_mutex);
|
||||||
* Users should access this with the GetTxRelay() getter. */
|
Assume(!m_tx_relay);
|
||||||
std::unique_ptr<TxRelay> m_tx_relay GUARDED_BY(m_tx_relay_mutex);
|
m_tx_relay = std::make_unique<Peer::TxRelay>();
|
||||||
|
return m_tx_relay.get();
|
||||||
|
};
|
||||||
|
|
||||||
TxRelay* GetTxRelay()
|
TxRelay* GetTxRelay()
|
||||||
{
|
{
|
||||||
|
@ -350,10 +352,17 @@ struct Peer {
|
||||||
/** Work queue of items requested by this peer **/
|
/** Work queue of items requested by this peer **/
|
||||||
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
|
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
|
||||||
|
|
||||||
explicit Peer(NodeId id, bool tx_relay)
|
Peer(NodeId id)
|
||||||
: m_id(id)
|
: m_id{id}
|
||||||
, m_tx_relay(tx_relay ? std::make_unique<TxRelay>() : nullptr)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
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>;
|
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();
|
CService addr_you = addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible() ? addr : CService();
|
||||||
uint64_t your_services{addr.nServices};
|
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,
|
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)
|
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)
|
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()));
|
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);
|
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);
|
LOCK(m_peer_mutex);
|
||||||
m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
|
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++;
|
const CInv &inv = *it++;
|
||||||
|
|
||||||
if (tx_relay == nullptr) {
|
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;
|
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"
|
// set nodes not capable of serving the complete blockchain history as "limited nodes"
|
||||||
pfrom.m_limited_node = (!(nServices & NODE_NETWORK) && (nServices & NODE_NETWORK_LIMITED));
|
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);
|
LOCK(tx_relay->m_bloom_filter_mutex);
|
||||||
tx_relay->m_relay_txs = fRelay; // set to true after we get the first filter* message
|
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
|
// Reject tx INVs when the -blocksonly setting is enabled, or this is a
|
||||||
// block-relay-only peer
|
// 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
|
// Allow peers with relay permission to send data other than blocks in blocks only mode
|
||||||
if (pfrom.HasPermission(NetPermissionFlags::Relay)) {
|
if (pfrom.HasPermission(NetPermissionFlags::Relay)) {
|
||||||
|
@ -3356,9 +3372,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
||||||
|
|
||||||
if (msg_type == NetMsgType::TX) {
|
if (msg_type == NetMsgType::TX) {
|
||||||
// Stop processing the transaction early if
|
// 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
|
// 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());
|
LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom.GetId());
|
||||||
pfrom.fDisconnect = true;
|
pfrom.fDisconnect = true;
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Add table
Reference in a new issue