Skip to content

Commit 60427ee

Browse files
committed
Merge #20811: refactor: move net_processing implementation details out of header
c97f70c net_processing: move Peer definition to .cpp (Anthony Towns) e0f2e6d net_processing: move PeerManagerImpl into cpp file (Anthony Towns) a568b82 net_processing: split PeerManager into interface and implementation classes (Anthony Towns) 0df3d3f net_processing: make more of PeerManager private (Anthony Towns) 0d246a5 net, net_processing: move NetEventsInterface method docs to net.h (Anthony Towns) Pull request description: Moves the implementation details of `PeerManager` and all of `struct Peer` into net_processing.cpp. ACKs for top commit: jnewbery: ACK c97f70c Sjors: ACK c97f70c laanwj: Code review ACK c97f70c vasild: ACK c97f70c Tree-SHA512: 2e081e491d981c61bd78436a6a6c2eb41d3c2d86a1a8ef9d4d6f801b82cb64a8bf707a96db3429418d1704cffb60a657d1037a0336cbc8173fb79aef9eb72001
2 parents 8ffaf5c + c97f70c commit 60427ee

File tree

7 files changed

+283
-253
lines changed

7 files changed

+283
-253
lines changed

src/init.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,8 +1410,8 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
14101410
ChainstateManager& chainman = *Assert(node.chainman);
14111411

14121412
assert(!node.peerman);
1413-
node.peerman = std::make_unique<PeerManager>(chainparams, *node.connman, node.banman.get(),
1414-
*node.scheduler, chainman, *node.mempool, ignores_incoming_txs);
1413+
node.peerman = PeerManager::make(chainparams, *node.connman, node.banman.get(),
1414+
*node.scheduler, chainman, *node.mempool, ignores_incoming_txs);
14151415
RegisterValidationInterface(node.peerman.get());
14161416

14171417
// sanitize comments per BIP-0014, format user agent and check total size

src/net.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -760,11 +760,30 @@ class CNode
760760
class NetEventsInterface
761761
{
762762
public:
763-
virtual bool ProcessMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
764-
virtual bool SendMessages(CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(pnode->cs_sendProcessing) = 0;
763+
/** Initialize a peer (setup state, queue any initial messages) */
765764
virtual void InitializeNode(CNode* pnode) = 0;
765+
766+
/** Handle removal of a peer (clear state) */
766767
virtual void FinalizeNode(const CNode& node, bool& update_connection_time) = 0;
767768

769+
/**
770+
* Process protocol messages received from a given node
771+
*
772+
* @param[in] pnode The node which we have received messages from.
773+
* @param[in] interrupt Interrupt condition for processing threads
774+
* @return True if there is more work to be done
775+
*/
776+
virtual bool ProcessMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
777+
778+
/**
779+
* Send queued protocol messages to a given node.
780+
*
781+
* @param[in] pnode The node which we are sending messages to.
782+
* @return True if there is more work to be done
783+
*/
784+
virtual bool SendMessages(CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(pnode->cs_sendProcessing) = 0;
785+
786+
768787
protected:
769788
/**
770789
* Protected destructor so that instances can only be deleted by derived classes.

src/net_processing.cpp

Lines changed: 229 additions & 35 deletions
Large diffs are not rendered by default.

src/net_processing.h

Lines changed: 19 additions & 202 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,13 @@
66
#ifndef BITCOIN_NET_PROCESSING_H
77
#define BITCOIN_NET_PROCESSING_H
88

9-
#include <consensus/params.h>
109
#include <net.h>
1110
#include <sync.h>
12-
#include <txrequest.h>
1311
#include <validationinterface.h>
1412

15-
class BlockTransactionsRequest;
16-
class BlockValidationState;
17-
class CBlockHeader;
1813
class CChainParams;
1914
class CTxMemPool;
2015
class ChainstateManager;
21-
class TxValidationState;
2216

2317
extern RecursiveMutex cs_main;
2418
extern RecursiveMutex g_cs_orphans;
@@ -39,216 +33,39 @@ struct CNodeStateStats {
3933
std::vector<int> vHeightInFlight;
4034
};
4135

42-
/**
43-
* Data structure for an individual peer. This struct is not protected by
44-
* cs_main since it does not contain validation-critical data.
45-
*
46-
* Memory is owned by shared pointers and this object is destructed when
47-
* the refcount drops to zero.
48-
*
49-
* Mutexes inside this struct must not be held when locking m_peer_mutex.
50-
*
51-
* TODO: move most members from CNodeState to this structure.
52-
* TODO: move remaining application-layer data members from CNode to this structure.
53-
*/
54-
struct Peer {
55-
/** Same id as the CNode object for this peer */
56-
const NodeId m_id{0};
57-
58-
/** Protects misbehavior data members */
59-
Mutex m_misbehavior_mutex;
60-
/** Accumulated misbehavior score for this peer */
61-
int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0};
62-
/** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
63-
bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
64-
65-
/** Protects block inventory data members */
66-
Mutex m_block_inv_mutex;
67-
/** List of blocks that we'll announce via an `inv` message.
68-
* There is no final sorting before sending, as they are always sent
69-
* immediately and in the order requested. */
70-
std::vector<uint256> m_blocks_for_inv_relay GUARDED_BY(m_block_inv_mutex);
71-
/** Unfiltered list of blocks that we'd like to announce via a `headers`
72-
* message. If we can't announce via a `headers` message, we'll fall back to
73-
* announcing via `inv`. */
74-
std::vector<uint256> m_blocks_for_headers_relay GUARDED_BY(m_block_inv_mutex);
75-
/** The final block hash that we sent in an `inv` message to this peer.
76-
* When the peer requests this block, we send an `inv` message to trigger
77-
* the peer to request the next sequence of block hashes.
78-
* Most peers use headers-first syncing, which doesn't use this mechanism */
79-
uint256 m_continuation_block GUARDED_BY(m_block_inv_mutex) {};
80-
81-
/** This peer's reported block height when we connected */
82-
std::atomic<int> m_starting_height{-1};
83-
84-
/** Set of txids to reconsider once their parent transactions have been accepted **/
85-
std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
86-
87-
/** Protects m_getdata_requests **/
88-
Mutex m_getdata_requests_mutex;
89-
/** Work queue of items requested by this peer **/
90-
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
91-
92-
explicit Peer(NodeId id) : m_id(id) {}
93-
};
94-
95-
using PeerRef = std::shared_ptr<Peer>;
96-
97-
class PeerManager final : public CValidationInterface, public NetEventsInterface {
36+
class PeerManager : public CValidationInterface, public NetEventsInterface
37+
{
9838
public:
99-
PeerManager(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
100-
CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
101-
bool ignore_incoming_txs);
39+
static std::unique_ptr<PeerManager> make(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
40+
CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
41+
bool ignore_incoming_txs);
42+
virtual ~PeerManager() { }
10243

103-
/**
104-
* Overridden from CValidationInterface.
105-
*/
106-
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override;
107-
void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex) override;
108-
/**
109-
* Overridden from CValidationInterface.
110-
*/
111-
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
112-
/**
113-
* Overridden from CValidationInterface.
114-
*/
115-
void BlockChecked(const CBlock& block, const BlockValidationState& state) override;
116-
/**
117-
* Overridden from CValidationInterface.
118-
*/
119-
void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) override;
120-
121-
/** Initialize a peer by adding it to mapNodeState and pushing a message requesting its version */
122-
void InitializeNode(CNode* pnode) override;
123-
/** Handle removal of a peer by updating various state and removing it from mapNodeState */
124-
void FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) override;
125-
/**
126-
* Process protocol messages received from a given node
127-
*
128-
* @param[in] pfrom The node which we have received messages from.
129-
* @param[in] interrupt Interrupt condition for processing threads
130-
*/
131-
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override;
132-
/**
133-
* Send queued protocol messages to be sent to a give node.
134-
*
135-
* @param[in] pto The node which we are sending messages to.
136-
* @return True if there is more work to be done
137-
*/
138-
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
44+
/** Get statistics from node state */
45+
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) = 0;
13946

140-
/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */
141-
void ConsiderEviction(CNode& pto, int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
142-
/** Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound */
143-
void CheckForStaleTipAndEvictPeers();
144-
/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */
145-
void EvictExtraOutboundPeers(int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
146-
/** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */
147-
void ReattemptInitialBroadcast(CScheduler& scheduler) const;
47+
/** Whether this node ignores txs received over p2p. */
48+
virtual bool IgnoresIncomingTxs() = 0;
14849

149-
/** Process a single message from a peer. Public for fuzz testing */
150-
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
151-
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc);
50+
/** Set the best height */
51+
virtual void SetBestHeight(int height) = 0;
15252

15353
/**
15454
* Increment peer's misbehavior score. If the new value >= DISCOURAGEMENT_THRESHOLD, mark the node
15555
* to be discouraged, meaning the peer might be disconnected and added to the discouragement filter.
15656
* Public for unit testing.
15757
*/
158-
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message);
159-
160-
/** Get statistics from node state */
161-
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats);
162-
163-
/** Set the best height */
164-
void SetBestHeight(int height) { m_best_height = height; };
165-
166-
/** Whether this node ignores txs received over p2p. */
167-
bool IgnoresIncomingTxs() { return m_ignore_incoming_txs; };
168-
169-
private:
170-
/** Get a shared pointer to the Peer object.
171-
* May return an empty shared_ptr if the Peer object can't be found. */
172-
PeerRef GetPeerRef(NodeId id) const;
173-
174-
/** Get a shared pointer to the Peer object and remove it from m_peer_map.
175-
* May return an empty shared_ptr if the Peer object can't be found. */
176-
PeerRef RemovePeer(NodeId id);
177-
178-
/**
179-
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
180-
*
181-
* @param[in] via_compact_block this bool is passed in because net_processing should
182-
* punish peers differently depending on whether the data was provided in a compact
183-
* block message or not. If the compact block had a valid header, but contained invalid
184-
* txs, the peer should not be punished. See BIP 152.
185-
*
186-
* @return Returns true if the peer was punished (probably disconnected)
187-
*/
188-
bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,
189-
bool via_compact_block, const std::string& message = "");
58+
virtual void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) = 0;
19059

19160
/**
192-
* Potentially disconnect and discourage a node based on the contents of a TxValidationState object
193-
*
194-
* @return Returns true if the peer was punished (probably disconnected)
195-
*/
196-
bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = "");
197-
198-
/** Maybe disconnect a peer and discourage future connections from its address.
199-
*
200-
* @param[in] pnode The node to check.
201-
* @return True if the peer was marked for disconnection in this function
61+
* Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound.
62+
* Public for unit testing.
20263
*/
203-
bool MaybeDiscourageAndDisconnect(CNode& pnode);
64+
virtual void CheckForStaleTipAndEvictPeers() = 0;
20465

205-
void ProcessOrphanTx(std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans);
206-
/** Process a single headers message from a peer. */
207-
void ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
208-
const std::vector<CBlockHeader>& headers,
209-
bool via_compact_block);
210-
211-
void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req);
212-
213-
/** Register with TxRequestTracker that an INV has been received from a
214-
* peer. The announcement parameters are decided in PeerManager and then
215-
* passed to TxRequestTracker. */
216-
void AddTxAnnouncement(const CNode& node, const GenTxid& gtxid, std::chrono::microseconds current_time)
217-
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
218-
219-
/** Send a version message to a peer */
220-
void PushNodeVersion(CNode& pnode, int64_t nTime);
221-
222-
const CChainParams& m_chainparams;
223-
CConnman& m_connman;
224-
/** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
225-
BanMan* const m_banman;
226-
ChainstateManager& m_chainman;
227-
CTxMemPool& m_mempool;
228-
TxRequestTracker m_txrequest GUARDED_BY(::cs_main);
229-
230-
/** The height of the best chain */
231-
std::atomic<int> m_best_height{-1};
232-
233-
int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
234-
235-
/** Whether this node is running in blocks only mode */
236-
const bool m_ignore_incoming_txs;
237-
238-
/** Whether we've completed initial sync yet, for determining when to turn
239-
* on extra block-relay-only peers. */
240-
bool m_initial_sync_finished{false};
241-
242-
/** Protects m_peer_map. This mutex must not be locked while holding a lock
243-
* on any of the mutexes inside a Peer object. */
244-
mutable Mutex m_peer_mutex;
245-
/**
246-
* Map of all Peer objects, keyed by peer id. This map is protected
247-
* by the m_peer_mutex. Once a shared pointer reference is
248-
* taken, the lock may be released. Individual fields are protected by
249-
* their own locks.
250-
*/
251-
std::map<NodeId, PeerRef> m_peer_map GUARDED_BY(m_peer_mutex);
66+
/** Process a single message from a peer. Public for fuzz testing */
67+
virtual void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
68+
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) = 0;
25269
};
25370

25471
/** Relay transaction to every node */

src/test/denialofservice_tests.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
8080
{
8181
const CChainParams& chainparams = Params();
8282
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
83-
auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler,
84-
*m_node.chainman, *m_node.mempool, false);
83+
auto peerLogic = PeerManager::make(chainparams, *connman, nullptr, *m_node.scheduler,
84+
*m_node.chainman, *m_node.mempool, false);
8585

8686
// Mock an outbound peer
8787
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -150,8 +150,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
150150
{
151151
const CChainParams& chainparams = Params();
152152
auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337);
153-
auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler,
154-
*m_node.chainman, *m_node.mempool, false);
153+
auto peerLogic = PeerManager::make(chainparams, *connman, nullptr, *m_node.scheduler,
154+
*m_node.chainman, *m_node.mempool, false);
155155

156156
constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
157157
CConnman::Options options;
@@ -224,8 +224,8 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
224224
const CChainParams& chainparams = Params();
225225
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
226226
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
227-
auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler,
228-
*m_node.chainman, *m_node.mempool, false);
227+
auto peerLogic = PeerManager::make(chainparams, *connman, banman.get(), *m_node.scheduler,
228+
*m_node.chainman, *m_node.mempool, false);
229229

230230
banman->ClearBanned();
231231
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -271,8 +271,8 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
271271
const CChainParams& chainparams = Params();
272272
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
273273
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
274-
auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler,
275-
*m_node.chainman, *m_node.mempool, false);
274+
auto peerLogic = PeerManager::make(chainparams, *connman, banman.get(), *m_node.scheduler,
275+
*m_node.chainman, *m_node.mempool, false);
276276

277277
banman->ClearBanned();
278278
int64_t nStartTime = GetTime();

src/test/util/setup_common.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,9 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
192192

193193
m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
194194
m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
195-
m_node.peerman = std::make_unique<PeerManager>(chainparams, *m_node.connman, m_node.banman.get(),
196-
*m_node.scheduler, *m_node.chainman, *m_node.mempool,
197-
false);
195+
m_node.peerman = PeerManager::make(chainparams, *m_node.connman, m_node.banman.get(),
196+
*m_node.scheduler, *m_node.chainman, *m_node.mempool,
197+
false);
198198
{
199199
CConnman::Options options;
200200
options.m_msgproc = m_node.peerman.get();

test/sanitizer_suppressions/tsan

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mutex:CConnman::ThreadOpenConnections
1313
mutex:CConnman::ThreadOpenAddedConnections
1414
mutex:CConnman::SocketHandler
1515
mutex:UpdateTip
16-
mutex:PeerManager::UpdatedBlockTip
16+
mutex:PeerManagerImpl::UpdatedBlockTip
1717
mutex:g_best_block_mutex
1818

1919
# race (TODO fix)

0 commit comments

Comments
 (0)