@@ -332,6 +332,104 @@ struct Peer {
332
332
333
333
using PeerRef = std::shared_ptr<Peer>;
334
334
335
+ /* *
336
+ * Maintain validation-specific state about nodes, protected by cs_main, instead
337
+ * by CNode's own locks. This simplifies asynchronous operation, where
338
+ * processing of incoming data is done after the ProcessMessage call returns,
339
+ * and we're no longer holding the node's locks.
340
+ */
341
+ struct CNodeState {
342
+ // ! The best known block we know this peer has announced.
343
+ const CBlockIndex* pindexBestKnownBlock{nullptr };
344
+ // ! The hash of the last unknown block this peer has announced.
345
+ uint256 hashLastUnknownBlock{};
346
+ // ! The last full block we both have.
347
+ const CBlockIndex* pindexLastCommonBlock{nullptr };
348
+ // ! The best header we have sent our peer.
349
+ const CBlockIndex* pindexBestHeaderSent{nullptr };
350
+ // ! Length of current-streak of unconnecting headers announcements
351
+ int nUnconnectingHeaders{0 };
352
+ // ! Whether we've started headers synchronization with this peer.
353
+ bool fSyncStarted {false };
354
+ // ! When to potentially disconnect peer for stalling headers download
355
+ std::chrono::microseconds m_headers_sync_timeout{0us};
356
+ // ! Since when we're stalling block download progress (in microseconds), or 0.
357
+ std::chrono::microseconds m_stalling_since{0us};
358
+ std::list<QueuedBlock> vBlocksInFlight;
359
+ // ! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty.
360
+ std::chrono::microseconds m_downloading_since{0us};
361
+ int nBlocksInFlight{0 };
362
+ // ! Whether we consider this a preferred download peer.
363
+ bool fPreferredDownload {false };
364
+ // ! Whether this peer wants invs or headers (when possible) for block announcements.
365
+ bool fPreferHeaders {false };
366
+ // ! Whether this peer wants invs or cmpctblocks (when possible) for block announcements.
367
+ bool fPreferHeaderAndIDs {false };
368
+ /* *
369
+ * Whether this peer will send us cmpctblocks if we request them.
370
+ * This is not used to gate request logic, as we really only care about fSupportsDesiredCmpctVersion,
371
+ * but is used as a flag to "lock in" the version of compact blocks (fWantsCmpctWitness) we send.
372
+ */
373
+ bool fProvidesHeaderAndIDs {false };
374
+ // ! Whether this peer can give us witnesses
375
+ bool fHaveWitness {false };
376
+ // ! Whether this peer wants witnesses in cmpctblocks/blocktxns
377
+ bool fWantsCmpctWitness {false };
378
+ /* *
379
+ * If we've announced NODE_WITNESS to this peer: whether the peer sends witnesses in cmpctblocks/blocktxns,
380
+ * otherwise: whether this peer sends non-witnesses in cmpctblocks/blocktxns.
381
+ */
382
+ bool fSupportsDesiredCmpctVersion {false };
383
+
384
+ /* * State used to enforce CHAIN_SYNC_TIMEOUT and EXTRA_PEER_CHECK_INTERVAL logic.
385
+ *
386
+ * Both are only in effect for outbound, non-manual, non-protected connections.
387
+ * Any peer protected (m_protect = true) is not chosen for eviction. A peer is
388
+ * marked as protected if all of these are true:
389
+ * - its connection type is IsBlockOnlyConn() == false
390
+ * - it gave us a valid connecting header
391
+ * - we haven't reached MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT yet
392
+ * - its chain tip has at least as much work as ours
393
+ *
394
+ * CHAIN_SYNC_TIMEOUT: if a peer's best known block has less work than our tip,
395
+ * set a timeout CHAIN_SYNC_TIMEOUT in the future:
396
+ * - If at timeout their best known block now has more work than our tip
397
+ * when the timeout was set, then either reset the timeout or clear it
398
+ * (after comparing against our current tip's work)
399
+ * - If at timeout their best known block still has less work than our
400
+ * tip did when the timeout was set, then send a getheaders message,
401
+ * and set a shorter timeout, HEADERS_RESPONSE_TIME seconds in future.
402
+ * If their best known block is still behind when that new timeout is
403
+ * reached, disconnect.
404
+ *
405
+ * EXTRA_PEER_CHECK_INTERVAL: after each interval, if we have too many outbound peers,
406
+ * drop the outbound one that least recently announced us a new block.
407
+ */
408
+ struct ChainSyncTimeoutState {
409
+ // ! A timeout used for checking whether our peer has sufficiently synced
410
+ std::chrono::seconds m_timeout{0s};
411
+ // ! A header with the work we require on our peer's chain
412
+ const CBlockIndex* m_work_header{nullptr };
413
+ // ! After timeout is reached, set to true after sending getheaders
414
+ bool m_sent_getheaders{false };
415
+ // ! Whether this peer is protected from disconnection due to a bad/slow chain
416
+ bool m_protect{false };
417
+ };
418
+
419
+ ChainSyncTimeoutState m_chain_sync;
420
+
421
+ // ! Time of last new block announcement
422
+ int64_t m_last_block_announcement{0 };
423
+
424
+ // ! Whether this peer is an inbound connection
425
+ const bool m_is_inbound;
426
+
427
+ // ! A rolling bloom filter of all announced tx CInvs to this peer.
428
+ CRollingBloomFilter m_recently_announced_invs = CRollingBloomFilter{INVENTORY_MAX_RECENT_RELAY, 0.000001 };
429
+
430
+ CNodeState (bool is_inbound) : m_is_inbound(is_inbound) {}
431
+ };
432
+
335
433
class PeerManagerImpl final : public PeerManager
336
434
{
337
435
public:
@@ -716,103 +814,6 @@ namespace {
716
814
} // namespace
717
815
718
816
namespace {
719
- /* *
720
- * Maintain validation-specific state about nodes, protected by cs_main, instead
721
- * by CNode's own locks. This simplifies asynchronous operation, where
722
- * processing of incoming data is done after the ProcessMessage call returns,
723
- * and we're no longer holding the node's locks.
724
- */
725
- struct CNodeState {
726
- // ! The best known block we know this peer has announced.
727
- const CBlockIndex* pindexBestKnownBlock{nullptr };
728
- // ! The hash of the last unknown block this peer has announced.
729
- uint256 hashLastUnknownBlock{};
730
- // ! The last full block we both have.
731
- const CBlockIndex* pindexLastCommonBlock{nullptr };
732
- // ! The best header we have sent our peer.
733
- const CBlockIndex* pindexBestHeaderSent{nullptr };
734
- // ! Length of current-streak of unconnecting headers announcements
735
- int nUnconnectingHeaders{0 };
736
- // ! Whether we've started headers synchronization with this peer.
737
- bool fSyncStarted {false };
738
- // ! When to potentially disconnect peer for stalling headers download
739
- std::chrono::microseconds m_headers_sync_timeout{0us};
740
- // ! Since when we're stalling block download progress (in microseconds), or 0.
741
- std::chrono::microseconds m_stalling_since{0us};
742
- std::list<QueuedBlock> vBlocksInFlight;
743
- // ! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty.
744
- std::chrono::microseconds m_downloading_since{0us};
745
- int nBlocksInFlight{0 };
746
- // ! Whether we consider this a preferred download peer.
747
- bool fPreferredDownload {false };
748
- // ! Whether this peer wants invs or headers (when possible) for block announcements.
749
- bool fPreferHeaders {false };
750
- // ! Whether this peer wants invs or cmpctblocks (when possible) for block announcements.
751
- bool fPreferHeaderAndIDs {false };
752
- /* *
753
- * Whether this peer will send us cmpctblocks if we request them.
754
- * This is not used to gate request logic, as we really only care about fSupportsDesiredCmpctVersion,
755
- * but is used as a flag to "lock in" the version of compact blocks (fWantsCmpctWitness) we send.
756
- */
757
- bool fProvidesHeaderAndIDs {false };
758
- // ! Whether this peer can give us witnesses
759
- bool fHaveWitness {false };
760
- // ! Whether this peer wants witnesses in cmpctblocks/blocktxns
761
- bool fWantsCmpctWitness {false };
762
- /* *
763
- * If we've announced NODE_WITNESS to this peer: whether the peer sends witnesses in cmpctblocks/blocktxns,
764
- * otherwise: whether this peer sends non-witnesses in cmpctblocks/blocktxns.
765
- */
766
- bool fSupportsDesiredCmpctVersion {false };
767
-
768
- /* * State used to enforce CHAIN_SYNC_TIMEOUT and EXTRA_PEER_CHECK_INTERVAL logic.
769
- *
770
- * Both are only in effect for outbound, non-manual, non-protected connections.
771
- * Any peer protected (m_protect = true) is not chosen for eviction. A peer is
772
- * marked as protected if all of these are true:
773
- * - its connection type is IsBlockOnlyConn() == false
774
- * - it gave us a valid connecting header
775
- * - we haven't reached MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT yet
776
- * - its chain tip has at least as much work as ours
777
- *
778
- * CHAIN_SYNC_TIMEOUT: if a peer's best known block has less work than our tip,
779
- * set a timeout CHAIN_SYNC_TIMEOUT in the future:
780
- * - If at timeout their best known block now has more work than our tip
781
- * when the timeout was set, then either reset the timeout or clear it
782
- * (after comparing against our current tip's work)
783
- * - If at timeout their best known block still has less work than our
784
- * tip did when the timeout was set, then send a getheaders message,
785
- * and set a shorter timeout, HEADERS_RESPONSE_TIME seconds in future.
786
- * If their best known block is still behind when that new timeout is
787
- * reached, disconnect.
788
- *
789
- * EXTRA_PEER_CHECK_INTERVAL: after each interval, if we have too many outbound peers,
790
- * drop the outbound one that least recently announced us a new block.
791
- */
792
- struct ChainSyncTimeoutState {
793
- // ! A timeout used for checking whether our peer has sufficiently synced
794
- std::chrono::seconds m_timeout{0s};
795
- // ! A header with the work we require on our peer's chain
796
- const CBlockIndex* m_work_header{nullptr };
797
- // ! After timeout is reached, set to true after sending getheaders
798
- bool m_sent_getheaders{false };
799
- // ! Whether this peer is protected from disconnection due to a bad/slow chain
800
- bool m_protect{false };
801
- };
802
-
803
- ChainSyncTimeoutState m_chain_sync;
804
-
805
- // ! Time of last new block announcement
806
- int64_t m_last_block_announcement{0 };
807
-
808
- // ! Whether this peer is an inbound connection
809
- const bool m_is_inbound;
810
-
811
- // ! A rolling bloom filter of all announced tx CInvs to this peer.
812
- CRollingBloomFilter m_recently_announced_invs = CRollingBloomFilter{INVENTORY_MAX_RECENT_RELAY, 0.000001 };
813
-
814
- CNodeState (bool is_inbound) : m_is_inbound(is_inbound) {}
815
- };
816
817
817
818
/* * Map maintaining per-node state. */
818
819
static std::map<NodeId, CNodeState> mapNodeState GUARDED_BY (cs_main);
0 commit comments