aboutsummaryrefslogtreecommitdiff
path: root/src/net_processing.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/net_processing.h')
-rw-r--r--src/net_processing.h118
1 files changed, 107 insertions, 11 deletions
diff --git a/src/net_processing.h b/src/net_processing.h
index 87eee566de..322fabbe11 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -32,10 +32,73 @@ static const bool DEFAULT_PEERBLOCKFILTERS = false;
/** Threshold for marking a node to be discouraged, e.g. disconnected and added to the discouragement filter. */
static const int DISCOURAGEMENT_THRESHOLD{100};
+struct CNodeStateStats {
+ int nSyncHeight = -1;
+ int nCommonHeight = -1;
+ int m_starting_height = -1;
+ std::vector<int> vHeightInFlight;
+};
+
+/**
+ * Data structure for an individual peer. This struct is not protected by
+ * cs_main since it does not contain validation-critical data.
+ *
+ * Memory is owned by shared pointers and this object is destructed when
+ * the refcount drops to zero.
+ *
+ * Mutexes inside this struct must not be held when locking m_peer_mutex.
+ *
+ * TODO: move most members from CNodeState to this structure.
+ * TODO: move remaining application-layer data members from CNode to this structure.
+ */
+struct Peer {
+ /** Same id as the CNode object for this peer */
+ const NodeId m_id{0};
+
+ /** Protects misbehavior data members */
+ Mutex m_misbehavior_mutex;
+ /** Accumulated misbehavior score for this peer */
+ int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0};
+ /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
+ bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
+
+ /** Protects block inventory data members */
+ Mutex m_block_inv_mutex;
+ /** List of blocks that we'll announce via an `inv` message.
+ * There is no final sorting before sending, as they are always sent
+ * immediately and in the order requested. */
+ std::vector<uint256> m_blocks_for_inv_relay GUARDED_BY(m_block_inv_mutex);
+ /** Unfiltered list of blocks that we'd like to announce via a `headers`
+ * message. If we can't announce via a `headers` message, we'll fall back to
+ * announcing via `inv`. */
+ std::vector<uint256> m_blocks_for_headers_relay GUARDED_BY(m_block_inv_mutex);
+ /** The final block hash that we sent in an `inv` message to this peer.
+ * When the peer requests this block, we send an `inv` message to trigger
+ * the peer to request the next sequence of block hashes.
+ * Most peers use headers-first syncing, which doesn't use this mechanism */
+ uint256 m_continuation_block GUARDED_BY(m_block_inv_mutex) {};
+
+ /** This peer's reported block height when we connected */
+ std::atomic<int> m_starting_height{-1};
+
+ /** Set of txids to reconsider once their parent transactions have been accepted **/
+ std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
+
+ /** Protects m_getdata_requests **/
+ Mutex m_getdata_requests_mutex;
+ /** Work queue of items requested by this peer **/
+ std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
+
+ explicit Peer(NodeId id) : m_id(id) {}
+};
+
+using PeerRef = std::shared_ptr<Peer>;
+
class PeerManager final : public CValidationInterface, public NetEventsInterface {
public:
PeerManager(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
- CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool);
+ CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
+ bool ignore_incoming_txs);
/**
* Overridden from CValidationInterface.
@@ -94,7 +157,24 @@ public:
*/
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message);
+ /** Get statistics from node state */
+ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats);
+
+ /** Set the best height */
+ void SetBestHeight(int height) { m_best_height = height; };
+
+ /** Whether this node ignores txs received over p2p. */
+ bool IgnoresIncomingTxs() { return m_ignore_incoming_txs; };
+
private:
+ /** Get a shared pointer to the Peer object.
+ * May return an empty shared_ptr if the Peer object can't be found. */
+ PeerRef GetPeerRef(NodeId id) const;
+
+ /** Get a shared pointer to the Peer object and remove it from m_peer_map.
+ * May return an empty shared_ptr if the Peer object can't be found. */
+ PeerRef RemovePeer(NodeId id);
+
/**
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
*
@@ -124,7 +204,9 @@ private:
void ProcessOrphanTx(std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans);
/** Process a single headers message from a peer. */
- void ProcessHeadersMessage(CNode& pfrom, const std::vector<CBlockHeader>& headers, bool via_compact_block);
+ void ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
+ const std::vector<CBlockHeader>& headers,
+ bool via_compact_block);
void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req);
@@ -134,6 +216,9 @@ private:
void AddTxAnnouncement(const CNode& node, const GenTxid& gtxid, std::chrono::microseconds current_time)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+ /** Send a version message to a peer */
+ void PushNodeVersion(CNode& pnode, int64_t nTime);
+
const CChainParams& m_chainparams;
CConnman& m_connman;
/** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
@@ -142,18 +227,29 @@ private:
CTxMemPool& m_mempool;
TxRequestTracker m_txrequest GUARDED_BY(::cs_main);
+ /** The height of the best chain */
+ std::atomic<int> m_best_height{-1};
+
int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
-};
-struct CNodeStateStats {
- int m_misbehavior_score = 0;
- int nSyncHeight = -1;
- int nCommonHeight = -1;
- std::vector<int> vHeightInFlight;
-};
+ /** Whether this node is running in blocks only mode */
+ const bool m_ignore_incoming_txs;
-/** Get statistics from node state */
-bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
+ /** Whether we've completed initial sync yet, for determining when to turn
+ * on extra block-relay-only peers. */
+ bool m_initial_sync_finished{false};
+
+ /** Protects m_peer_map. This mutex must not be locked while holding a lock
+ * on any of the mutexes inside a Peer object. */
+ mutable Mutex m_peer_mutex;
+ /**
+ * Map of all Peer objects, keyed by peer id. This map is protected
+ * by the m_peer_mutex. Once a shared pointer reference is
+ * taken, the lock may be released. Individual fields are protected by
+ * their own locks.
+ */
+ std::map<NodeId, PeerRef> m_peer_map GUARDED_BY(m_peer_mutex);
+};
/** Relay transaction to every node */
void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);