diff options
author | John Newbery <john@johnnewbery.com> | 2020-07-20 14:01:05 +0100 |
---|---|---|
committer | dergoegge <n.goeggi@gmail.com> | 2022-07-14 14:44:44 +0200 |
commit | 1f52c47d5c09b59fd3153700751c74e63edc7d7e (patch) | |
tree | 1daebbb2837b9764a348f280e7afd9ea0128644b | |
parent | 31c6309cc60ae3fee2d3ecc2aff9576596fb98ac (diff) | |
download | bitcoin-1f52c47d5c09b59fd3153700751c74e63edc7d7e.tar.xz |
[net processing] Add m_our_services and m_their_services to Peer
Track services offered by us and the peer in the Peer object.
-rw-r--r-- | src/net.cpp | 4 | ||||
-rw-r--r-- | src/net.h | 16 | ||||
-rw-r--r-- | src/net_processing.cpp | 39 | ||||
-rw-r--r-- | src/test/denialofservice_tests.cpp | 12 | ||||
-rw-r--r-- | src/test/net_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/util/net.cpp | 2 |
6 files changed, 42 insertions, 33 deletions
diff --git a/src/net.cpp b/src/net.cpp index 90c73d583e..5082d6eb68 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1026,7 +1026,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock, pnode->AddRef(); pnode->m_permissionFlags = permissionFlags; pnode->m_prefer_evict = discouraged; - m_msgproc->InitializeNode(pnode); + m_msgproc->InitializeNode(*pnode, nodeServices); LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString()); @@ -1964,7 +1964,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai if (grantOutbound) grantOutbound->MoveTo(pnode->grantOutbound); - m_msgproc->InitializeNode(pnode); + m_msgproc->InitializeNode(*pnode, nLocalServices); { LOCK(m_nodes_mutex); m_nodes.push_back(pnode); @@ -592,20 +592,6 @@ private: std::atomic<int> m_greatest_common_version{INIT_PROTO_VERSION}; //! Services offered to this peer. - //! - //! This is supplied by the parent CConnman during peer connection - //! (CConnman::ConnectNode()) from its attribute of the same name. - //! - //! This is const because there is no protocol defined for renegotiating - //! services initially offered to a peer. The set of local services we - //! offer should not change after initialization. - //! - //! An interesting example of this is NODE_NETWORK and initial block - //! download: a node which starts up from scratch doesn't have any blocks - //! to serve, but still advertises NODE_NETWORK because it will eventually - //! fulfill this role after IBD completes. P2P code is written in such a - //! way that it can gracefully handle peers who don't make good on their - //! service advertisements. const ServiceFlags nLocalServices; std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread @@ -625,7 +611,7 @@ class NetEventsInterface { public: /** Initialize a peer (setup state, queue any initial messages) */ - virtual void InitializeNode(CNode* pnode) = 0; + virtual void InitializeNode(CNode& node, ServiceFlags our_services) = 0; /** Handle removal of a peer (clear state) */ virtual void FinalizeNode(const CNode& node) = 0; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index c33dd29923..7c403d73db 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -207,6 +207,27 @@ struct Peer { /** Same id as the CNode object for this peer */ const NodeId m_id{0}; + /** Services we offered to this peer. + * + * This is supplied by CConnman during peer initialization. It's const + * because there is no protocol defined for renegotiating services + * initially offered to a peer. The set of local services we offer should + * not change after initialization. + * + * An interesting example of this is NODE_NETWORK and initial block + * download: a node which starts up from scratch doesn't have any blocks + * to serve, but still advertises NODE_NETWORK because it will eventually + * fulfill this role after IBD completes. P2P code is written in such a + * way that it can gracefully handle peers who don't make good on their + * service advertisements. + * + * TODO: remove redundant CNode::nLocalServices*/ + const ServiceFlags m_our_services; + /** Services this peer offered to us. + * + * TODO: remove redundant CNode::nServices */ + std::atomic<ServiceFlags> m_their_services{NODE_NONE}; + /** Protects misbehavior data members */ Mutex m_misbehavior_mutex; /** Accumulated misbehavior score for this peer */ @@ -360,8 +381,9 @@ struct Peer { /** Time of the last getheaders message to this peer */ std::atomic<NodeClock::time_point> m_last_getheaders_timestamp{NodeSeconds{}}; - Peer(NodeId id) + explicit Peer(NodeId id, ServiceFlags our_services) : m_id{id} + , m_our_services{our_services} {} private: @@ -482,7 +504,7 @@ public: EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex); /** Implement NetEventsInterface */ - void InitializeNode(CNode* pnode) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); + void InitializeNode(CNode& node, ServiceFlags our_services) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); void FinalizeNode(const CNode& node) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex); @@ -1299,21 +1321,21 @@ void PeerManagerImpl::UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_s if (state) state->m_last_block_announcement = time_in_seconds; } -void PeerManagerImpl::InitializeNode(CNode *pnode) +void PeerManagerImpl::InitializeNode(CNode& node, ServiceFlags our_services) { - NodeId nodeid = pnode->GetId(); + NodeId nodeid = node.GetId(); { LOCK(cs_main); - 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(node.IsInboundConn())); assert(m_txrequest.Count(nodeid) == 0); } - PeerRef peer = std::make_shared<Peer>(nodeid); + PeerRef peer = std::make_shared<Peer>(nodeid, our_services); { LOCK(m_peer_mutex); m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer); } - if (!pnode->IsInboundConn()) { - PushNodeVersion(*pnode, *peer); + if (!node.IsInboundConn()) { + PushNodeVersion(node, *peer); } } @@ -2843,6 +2865,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK)); pfrom.nServices = nServices; + peer->m_their_services = nServices; pfrom.SetAddrLocal(addrMe); { LOCK(pfrom.m_subver_mutex); diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index c87ed82c88..d77099f921 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) /*inbound_onion=*/false}; dummyNode1.SetCommonVersion(PROTOCOL_VERSION); - peerLogic->InitializeNode(&dummyNode1); + peerLogic->InitializeNode(dummyNode1, dummyNode1.GetLocalServices()); dummyNode1.fSuccessfullyConnected = true; // This test requires that we have a chain with non-zero work. @@ -124,7 +124,7 @@ static void AddRandomOutboundPeer(NodeId& id, std::vector<CNode*>& vNodes, PeerM CNode &node = *vNodes.back(); node.SetCommonVersion(PROTOCOL_VERSION); - peerLogic.InitializeNode(&node); + peerLogic.InitializeNode(node, node.GetLocalServices()); node.fSuccessfullyConnected = true; connman.AddTestNode(node); @@ -302,7 +302,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) ConnectionType::INBOUND, /*inbound_onion=*/false}; nodes[0]->SetCommonVersion(PROTOCOL_VERSION); - peerLogic->InitializeNode(nodes[0]); + peerLogic->InitializeNode(*nodes[0], nodes[0]->GetLocalServices()); nodes[0]->fSuccessfullyConnected = true; connman->AddTestNode(*nodes[0]); peerLogic->UnitTestMisbehaving(nodes[0]->GetId(), DISCOURAGEMENT_THRESHOLD); // Should be discouraged @@ -325,7 +325,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) ConnectionType::INBOUND, /*inbound_onion=*/false}; nodes[1]->SetCommonVersion(PROTOCOL_VERSION); - peerLogic->InitializeNode(nodes[1]); + peerLogic->InitializeNode(*nodes[1], nodes[1]->GetLocalServices()); nodes[1]->fSuccessfullyConnected = true; connman->AddTestNode(*nodes[1]); peerLogic->UnitTestMisbehaving(nodes[1]->GetId(), DISCOURAGEMENT_THRESHOLD - 1); @@ -363,7 +363,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) ConnectionType::OUTBOUND_FULL_RELAY, /*inbound_onion=*/false}; nodes[2]->SetCommonVersion(PROTOCOL_VERSION); - peerLogic->InitializeNode(nodes[2]); + peerLogic->InitializeNode(*nodes[2], nodes[2]->GetLocalServices()); nodes[2]->fSuccessfullyConnected = true; connman->AddTestNode(*nodes[2]); peerLogic->UnitTestMisbehaving(nodes[2]->GetId(), DISCOURAGEMENT_THRESHOLD); @@ -408,7 +408,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) ConnectionType::INBOUND, /*inbound_onion=*/false}; dummyNode.SetCommonVersion(PROTOCOL_VERSION); - peerLogic->InitializeNode(&dummyNode); + peerLogic->InitializeNode(dummyNode, dummyNode.GetLocalServices()); dummyNode.fSuccessfullyConnected = true; peerLogic->UnitTestMisbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD); diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 115c4b9b24..0ac508bea9 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -857,7 +857,7 @@ BOOST_AUTO_TEST_CASE(initial_advertise_from_version_message) *static_cast<TestChainState*>(&m_node.chainman->ActiveChainstate()); chainstate.JumpOutOfIbd(); - m_node.peerman->InitializeNode(&peer); + m_node.peerman->InitializeNode(peer, peer.GetLocalServices()); std::atomic<bool> interrupt_dummy{false}; std::chrono::microseconds time_received_dummy{0}; diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp index e70ad036bd..90a49d52d7 100644 --- a/src/test/util/net.cpp +++ b/src/test/util/net.cpp @@ -24,7 +24,7 @@ void ConnmanTestMsg::Handshake(CNode& node, auto& connman{*this}; const CNetMsgMaker mm{0}; - peerman.InitializeNode(&node); + peerman.InitializeNode(node, node.GetLocalServices()); CSerializedNetMsg msg_version{ mm.Make(NetMsgType::VERSION, |