Bitcoin ABC 0.33.6
P2P Digital Currency
net_processing.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2016 The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include <net_processing.h>
7
8#include <addrman.h>
11#include <avalanche/processor.h>
12#include <avalanche/proof.h>
16#include <banman.h>
17#include <blockencodings.h>
18#include <blockfilter.h>
19#include <blockvalidity.h>
20#include <chain.h>
21#include <chainparams.h>
22#include <config.h>
23#include <consensus/amount.h>
25#include <hash.h>
26#include <headerssync.h>
28#include <invrequest.h>
29#include <kernel/chain.h>
31#include <merkleblock.h>
32#include <netbase.h>
33#include <netmessagemaker.h>
34#include <node/blockstorage.h>
35#include <node/miner.h>
36#include <policy/fees.h>
37#include <policy/policy.h>
38#include <policy/settings.h>
39#include <primitives/block.h>
41#include <random.h>
42#include <reverse_iterator.h>
43#include <scheduler.h>
44#include <streams.h>
45#include <timedata.h>
46#include <tinyformat.h>
47#include <txmempool.h>
48#include <txorphanage.h>
49#include <util/check.h>
50#include <util/strencodings.h>
51#include <util/trace.h>
52#include <validation.h>
53
54#include <boost/multi_index/hashed_index.hpp>
55#include <boost/multi_index/member.hpp>
56#include <boost/multi_index/ordered_index.hpp>
57#include <boost/multi_index_container.hpp>
58
59#include <algorithm>
60#include <atomic>
61#include <chrono>
62#include <functional>
63#include <future>
64#include <memory>
65#include <numeric>
66#include <typeinfo>
67#include <utility>
68
73static constexpr auto UNCONDITIONAL_RELAY_DELAY = 2min;
78static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE = 15min;
79static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1ms;
81static constexpr auto HEADERS_RESPONSE_TIME{2min};
88static constexpr auto CHAIN_SYNC_TIMEOUT{20min};
90static constexpr auto STALE_CHECK_INTERVAL{10min};
92static constexpr auto EXTRA_PEER_CHECK_INTERVAL{45s};
97static constexpr auto MINIMUM_CONNECT_TIME{30s};
99static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL;
102static constexpr int STALE_RELAY_AGE_LIMIT = 30 * 24 * 60 * 60;
105static constexpr int HISTORICAL_BLOCK_AGE = 7 * 24 * 60 * 60;
109static constexpr auto PING_INTERVAL{2min};
111static const unsigned int MAX_LOCATOR_SZ = 101;
113static const unsigned int MAX_INV_SZ = 50000;
114static_assert(MAX_PROTOCOL_MESSAGE_LENGTH > MAX_INV_SZ * sizeof(CInv),
115 "Max protocol message length must be greater than largest "
116 "possible INV message");
117
119static constexpr auto GETAVAADDR_INTERVAL{2min};
120
125static constexpr auto AVALANCHE_AVAPROOFS_TIMEOUT{2min};
126
128static constexpr size_t MAX_AVALANCHE_STALLED_TXIDS_PER_PEER{100};
129
137
147
149 const std::chrono::seconds nonpref_peer_delay;
150
155 const std::chrono::seconds overloaded_peer_delay;
156
161 const std::chrono::microseconds getdata_interval;
162
168};
169
171 100, // max_peer_request_in_flight
172 5000, // max_peer_announcements
173 std::chrono::seconds(2), // nonpref_peer_delay
174 std::chrono::seconds(2), // overloaded_peer_delay
175 std::chrono::seconds(60), // getdata_interval
176 NetPermissionFlags::Relay, // bypass_request_limits_permissions
177};
178
180 100, // max_peer_request_in_flight
181 5000, // max_peer_announcements
182 std::chrono::seconds(2), // nonpref_peer_delay
183 std::chrono::seconds(2), // overloaded_peer_delay
184 std::chrono::seconds(60), // getdata_interval
186 BypassProofRequestLimits, // bypass_request_limits_permissions
187};
188
193static const unsigned int MAX_GETDATA_SZ = 1000;
197static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
203static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT{2s};
205static constexpr auto BLOCK_STALLING_TIMEOUT_MAX{64s};
210static const int MAX_CMPCTBLOCK_DEPTH = 5;
215static const int MAX_BLOCKTXN_DEPTH = 10;
217 "MAX_BLOCKTXN_DEPTH too high");
225static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
230static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE = 1;
234static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 0.5;
239static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
241static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
245static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24h};
249static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL{30s};
251static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL{24h};
256static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL{5s};
261static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND = 7;
263static constexpr unsigned int INVENTORY_BROADCAST_MAX_PER_MB =
267static constexpr unsigned int INVENTORY_MAX_RECENT_RELAY = 3500;
276 std::chrono::seconds{1},
277 "INVENTORY_RELAY_MAX too low");
278
282static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL{10min};
286static constexpr auto MAX_FEEFILTER_CHANGE_DELAY{5min};
291static constexpr uint32_t MAX_GETCFILTERS_SIZE = 1000;
296static constexpr uint32_t MAX_GETCFHEADERS_SIZE = 2000;
301static constexpr size_t MAX_PCT_ADDR_TO_SEND = 23;
306static constexpr double MAX_ADDR_RATE_PER_SECOND{0.1};
314static constexpr uint64_t CMPCTBLOCKS_VERSION{1};
315
316// Internal stuff
317namespace {
321struct QueuedBlock {
326 const CBlockIndex *pindex;
328 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
329};
330
331struct StalledTxId {
332 TxId txid;
333 std::chrono::seconds timeAdded;
334
335 StalledTxId(TxId txid_, std::chrono::seconds timeAdded_)
336 : txid(txid_), timeAdded(timeAdded_){};
337};
338
339struct by_txid {};
340struct by_time {};
341
342using StalledTxIdSet = boost::multi_index_container<
343 StalledTxId,
344 boost::multi_index::indexed_by<
345 // sort by txid
346 boost::multi_index::hashed_unique<
347 boost::multi_index::tag<by_txid>,
348 boost::multi_index::member<StalledTxId, TxId, &StalledTxId::txid>,
350 // sort by timeAdded
351 boost::multi_index::ordered_non_unique<
352 boost::multi_index::tag<by_time>,
353 boost::multi_index::member<StalledTxId, std::chrono::seconds,
354 &StalledTxId::timeAdded>>>>;
355
369struct Peer {
371 const NodeId m_id{0};
372
388 const ServiceFlags m_our_services;
389
391 std::atomic<ServiceFlags> m_their_services{NODE_NONE};
392
394 Mutex m_misbehavior_mutex;
399 bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
400
402 Mutex m_block_inv_mutex;
408 std::vector<BlockHash> m_blocks_for_inv_relay GUARDED_BY(m_block_inv_mutex);
414 std::vector<BlockHash>
415 m_blocks_for_headers_relay GUARDED_BY(m_block_inv_mutex);
416
423 BlockHash m_continuation_block GUARDED_BY(m_block_inv_mutex){};
424
426 std::atomic<int> m_starting_height{-1};
427
429 std::atomic<uint64_t> m_ping_nonce_sent{0};
431 std::atomic<std::chrono::microseconds> m_ping_start{0us};
433 std::atomic<bool> m_ping_queued{false};
434
442 Amount::zero()};
443 std::chrono::microseconds m_next_send_feefilter
445
446 struct TxRelay {
447 mutable RecursiveMutex m_bloom_filter_mutex;
456 bool m_relay_txs GUARDED_BY(m_bloom_filter_mutex){false};
461 std::unique_ptr<CBloomFilter>
462 m_bloom_filter PT_GUARDED_BY(m_bloom_filter_mutex)
463 GUARDED_BY(m_bloom_filter_mutex){nullptr};
464
466 CRollingBloomFilter m_recently_announced_invs GUARDED_BY(
468 0.000001};
469
470 mutable RecursiveMutex m_tx_inventory_mutex;
476 CRollingBloomFilter m_tx_inventory_known_filter
477 GUARDED_BY(m_tx_inventory_mutex){50000, 0.000001};
483 std::set<TxId> m_tx_inventory_to_send GUARDED_BY(m_tx_inventory_mutex);
489 bool m_send_mempool GUARDED_BY(m_tx_inventory_mutex){false};
491 std::atomic<std::chrono::seconds> m_last_mempool_req{0s};
496 std::chrono::microseconds
497 m_next_inv_send_time GUARDED_BY(m_tx_inventory_mutex){0};
498
503 std::atomic<Amount> m_fee_filter_received{Amount::zero()};
504
508 StalledTxIdSet
509 m_avalanche_stalled_txids GUARDED_BY(m_tx_inventory_mutex);
510 };
511
512 /*
513 * Initializes a TxRelay struct for this peer. Can be called at most once
514 * for a peer.
515 */
516 TxRelay *SetTxRelay() EXCLUSIVE_LOCKS_REQUIRED(!m_tx_relay_mutex) {
517 LOCK(m_tx_relay_mutex);
518 Assume(!m_tx_relay);
519 m_tx_relay = std::make_unique<Peer::TxRelay>();
520 return m_tx_relay.get();
521 };
522
523 TxRelay *GetTxRelay() EXCLUSIVE_LOCKS_REQUIRED(!m_tx_relay_mutex) {
524 return WITH_LOCK(m_tx_relay_mutex, return m_tx_relay.get());
525 };
526 const TxRelay *GetTxRelay() const
527 EXCLUSIVE_LOCKS_REQUIRED(!m_tx_relay_mutex) {
528 return WITH_LOCK(m_tx_relay_mutex, return m_tx_relay.get());
529 };
530
531 struct ProofRelay {
532 mutable RecursiveMutex m_proof_inventory_mutex;
533 std::set<avalanche::ProofId>
534 m_proof_inventory_to_send GUARDED_BY(m_proof_inventory_mutex);
535 // Prevent sending proof invs if the peer already knows about them
536 CRollingBloomFilter m_proof_inventory_known_filter
537 GUARDED_BY(m_proof_inventory_mutex){10000, 0.000001};
541 CRollingBloomFilter m_recently_announced_proofs GUARDED_BY(
543 0.000001};
544 std::chrono::microseconds m_next_inv_send_time{0};
545
547 sharedProofs;
548 std::atomic<std::chrono::seconds> lastSharedProofsUpdate{0s};
549 std::atomic<bool> compactproofs_requested{false};
550 };
551
556 const std::unique_ptr<ProofRelay> m_proof_relay;
557
561 std::vector<CAddress>
573 std::unique_ptr<CRollingBloomFilter>
591 std::atomic_bool m_addr_relay_enabled{false};
593 bool m_getaddr_sent GUARDED_BY(NetEventsInterface::g_msgproc_mutex){false};
595 mutable Mutex m_addr_send_times_mutex;
597 std::chrono::microseconds
598 m_next_addr_send GUARDED_BY(m_addr_send_times_mutex){0};
600 std::chrono::microseconds
601 m_next_local_addr_send GUARDED_BY(m_addr_send_times_mutex){0};
606 std::atomic_bool m_wants_addrv2{false};
608 bool m_getaddr_recvd GUARDED_BY(NetEventsInterface::g_msgproc_mutex){false};
610 mutable Mutex m_addr_token_bucket_mutex;
615 double m_addr_token_bucket GUARDED_BY(m_addr_token_bucket_mutex){1.0};
617 std::chrono::microseconds
618 m_addr_token_timestamp GUARDED_BY(NetEventsInterface::g_msgproc_mutex){
619 GetTime<std::chrono::microseconds>()};
621 std::atomic<uint64_t> m_addr_rate_limited{0};
626 std::atomic<uint64_t> m_addr_processed{0};
627
632 bool m_inv_triggered_getheaders_before_sync
634
636 Mutex m_getdata_requests_mutex;
638 std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
639
641 NodeClock::time_point m_last_getheaders_timestamp
643
645 Mutex m_headers_sync_mutex;
650 std::unique_ptr<HeadersSyncState>
651 m_headers_sync PT_GUARDED_BY(m_headers_sync_mutex)
652 GUARDED_BY(m_headers_sync_mutex){};
653
655 std::atomic<bool> m_sent_sendheaders{false};
656
658 std::chrono::microseconds m_headers_sync_timeout
660
665 bool m_prefers_headers GUARDED_BY(NetEventsInterface::g_msgproc_mutex){
666 false};
667
668 explicit Peer(NodeId id, ServiceFlags our_services, bool fRelayProofs)
669 : m_id(id), m_our_services{our_services},
670 m_proof_relay(fRelayProofs ? std::make_unique<ProofRelay>()
671 : nullptr) {}
672
673private:
674 mutable Mutex m_tx_relay_mutex;
675
677 std::unique_ptr<TxRelay> m_tx_relay GUARDED_BY(m_tx_relay_mutex);
678};
679
680using PeerRef = std::shared_ptr<Peer>;
681
688struct CNodeState {
690 const CBlockIndex *pindexBestKnownBlock{nullptr};
692 BlockHash hashLastUnknownBlock{};
694 const CBlockIndex *pindexLastCommonBlock{nullptr};
696 const CBlockIndex *pindexBestHeaderSent{nullptr};
698 bool fSyncStarted{false};
701 std::chrono::microseconds m_stalling_since{0us};
702 std::list<QueuedBlock> vBlocksInFlight;
705 std::chrono::microseconds m_downloading_since{0us};
707 bool fPreferredDownload{false};
712 bool m_requested_hb_cmpctblocks{false};
714 bool m_provides_cmpctblocks{false};
715
742 struct ChainSyncTimeoutState {
745 std::chrono::seconds m_timeout{0s};
747 const CBlockIndex *m_work_header{nullptr};
749 bool m_sent_getheaders{false};
752 bool m_protect{false};
753 };
754
755 ChainSyncTimeoutState m_chain_sync;
756
758 int64_t m_last_block_announcement{0};
759
761 const bool m_is_inbound;
762
763 CNodeState(bool is_inbound) : m_is_inbound(is_inbound) {}
764};
765
766class PeerManagerImpl final : public PeerManager {
767public:
768 PeerManagerImpl(CConnman &connman, AddrMan &addrman, BanMan *banman,
769 ChainstateManager &chainman, CTxMemPool &pool,
770 avalanche::Processor *const avalanche, Options opts);
771
774 const std::shared_ptr<const CBlock> &pblock,
775 const CBlockIndex *pindexConnected) override
776 EXCLUSIVE_LOCKS_REQUIRED(!m_recent_confirmed_transactions_mutex);
777 void BlockDisconnected(const std::shared_ptr<const CBlock> &block,
778 const CBlockIndex *pindex) override
779 EXCLUSIVE_LOCKS_REQUIRED(!m_recent_confirmed_transactions_mutex);
780 void UpdatedBlockTip(const CBlockIndex *pindexNew,
781 const CBlockIndex *pindexFork,
782 bool fInitialDownload) override
783 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
784 void BlockChecked(const CBlock &block,
785 const BlockValidationState &state) override
786 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
787 void NewPoWValidBlock(const CBlockIndex *pindex,
788 const std::shared_ptr<const CBlock> &pblock) override
789 EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex);
790
792 void InitializeNode(const Config &config, CNode &node,
793 ServiceFlags our_services) override
794 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
795 void FinalizeNode(const Config &config, const CNode &node) override
796 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !cs_proofrequest,
797 !m_headers_presync_mutex);
798 bool ProcessMessages(const Config &config, CNode *pfrom,
799 std::atomic<bool> &interrupt) override
800 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex,
801 !m_recent_confirmed_transactions_mutex,
802 !m_most_recent_block_mutex, !cs_proofrequest,
803 !m_headers_presync_mutex, g_msgproc_mutex);
804 bool SendMessages(const Config &config, CNode *pto) override
805 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex,
806 !m_recent_confirmed_transactions_mutex,
807 !m_most_recent_block_mutex, !cs_proofrequest,
808 g_msgproc_mutex);
809
811 void StartScheduledTasks(CScheduler &scheduler) override;
812 void CheckForStaleTipAndEvictPeers() override;
813 std::optional<std::string>
814 FetchBlock(const Config &config, NodeId peer_id,
815 const CBlockIndex &block_index) override;
816 bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const override
817 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
818 bool IgnoresIncomingTxs() override { return m_opts.ignore_incoming_txs; }
819 void SendPings() override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
820 void RelayTransaction(const TxId &txid) override
821 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
822 void RelayProof(const avalanche::ProofId &proofid) override
823 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
824 void SetBestHeight(int height) override { m_best_height = height; };
825 void UnitTestMisbehaving(NodeId peer_id) override
826 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex) {
827 Misbehaving(*Assert(GetPeerRef(peer_id)), "");
828 }
829 void ProcessMessage(const Config &config, CNode &pfrom,
830 const std::string &msg_type, DataStream &vRecv,
831 const std::chrono::microseconds time_received,
832 const std::atomic<bool> &interruptMsgProc) override
833 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex,
834 !m_recent_confirmed_transactions_mutex,
835 !m_most_recent_block_mutex, !cs_proofrequest,
836 !m_headers_presync_mutex, g_msgproc_mutex);
838 int64_t time_in_seconds) override;
839
840private:
845 void ConsiderEviction(CNode &pto, Peer &peer,
846 std::chrono::seconds time_in_seconds)
847 EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_msgproc_mutex);
848
853 void EvictExtraOutboundPeers(std::chrono::seconds now)
855
860 void ReattemptInitialBroadcast(CScheduler &scheduler)
861 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
862
866 void UpdateAvalancheStatistics() const;
867
871 void AvalanchePeriodicNetworking(CScheduler &scheduler) const;
872
877 PeerRef GetPeerRef(NodeId id) const EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
878
883 PeerRef RemovePeer(NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
884
889 void Misbehaving(Peer &peer, const std::string &message);
890
901 void MaybePunishNodeForBlock(NodeId nodeid,
902 const BlockValidationState &state,
903 bool via_compact_block,
904 const std::string &message = "")
905 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
906
911 void MaybePunishNodeForTx(NodeId nodeid, const TxValidationState &state,
912 const std::string &message = "")
913 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
914
924 bool MaybeDiscourageAndDisconnect(CNode &pnode, Peer &peer);
925
940 void ProcessInvalidTx(NodeId nodeid, const CTransactionRef &tx,
941 const TxValidationState &result,
942 bool maybe_add_extra_compact_tx)
943 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, cs_main);
944
945 struct PackageToValidate {
946 const Package m_txns;
947 const std::vector<NodeId> m_senders;
949 explicit PackageToValidate(const CTransactionRef &parent,
950 const CTransactionRef &child,
951 NodeId parent_sender, NodeId child_sender)
952 : m_txns{parent, child}, m_senders{parent_sender, child_sender} {}
953
954 std::string ToString() const {
955 Assume(m_txns.size() == 2);
956 return strprintf(
957 "parent %s (sender=%d) + child %s (sender=%d)",
958 m_txns.front()->GetId().ToString(), m_senders.front(),
959 m_txns.back()->GetId().ToString(), m_senders.back());
960 }
961 };
962
968 void ProcessPackageResult(const PackageToValidate &package_to_validate,
969 const PackageMempoolAcceptResult &package_result)
970 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, cs_main);
971
978 std::optional<PackageToValidate> Find1P1CPackage(const CTransactionRef &ptx,
979 NodeId nodeid)
980 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, cs_main);
981
987 void ProcessValidTx(NodeId nodeid, const CTransactionRef &tx)
988 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, cs_main);
989
1005 bool ProcessOrphanTx(const Config &config, Peer &peer)
1006 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex);
1007
1018 void ProcessHeadersMessage(const Config &config, CNode &pfrom, Peer &peer,
1019 std::vector<CBlockHeader> &&headers,
1020 bool via_compact_block)
1021 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex,
1022 g_msgproc_mutex);
1023
1024 // Various helpers for headers processing, invoked by
1025 // ProcessHeadersMessage()
1030 bool CheckHeadersPoW(const std::vector<CBlockHeader> &headers,
1031 const Consensus::Params &consensusParams, Peer &peer);
1033 arith_uint256 GetAntiDoSWorkThreshold();
1040 void HandleUnconnectingHeaders(CNode &pfrom, Peer &peer,
1041 const std::vector<CBlockHeader> &headers)
1042 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1044 bool
1045 CheckHeadersAreContinuous(const std::vector<CBlockHeader> &headers) const;
1065 bool IsContinuationOfLowWorkHeadersSync(Peer &peer, CNode &pfrom,
1066 std::vector<CBlockHeader> &headers)
1067 EXCLUSIVE_LOCKS_REQUIRED(peer.m_headers_sync_mutex,
1068 !m_headers_presync_mutex, g_msgproc_mutex);
1082 bool TryLowWorkHeadersSync(Peer &peer, CNode &pfrom,
1083 const CBlockIndex *chain_start_header,
1084 std::vector<CBlockHeader> &headers)
1085 EXCLUSIVE_LOCKS_REQUIRED(!peer.m_headers_sync_mutex, !m_peer_mutex,
1086 !m_headers_presync_mutex, g_msgproc_mutex);
1087
1092 bool IsAncestorOfBestHeaderOrTip(const CBlockIndex *header)
1094
1100 bool MaybeSendGetHeaders(CNode &pfrom, const CBlockLocator &locator,
1101 Peer &peer)
1102 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1106 void HeadersDirectFetchBlocks(const Config &config, CNode &pfrom,
1107 const CBlockIndex &last_header);
1109 void UpdatePeerStateForReceivedHeaders(CNode &pfrom, Peer &peer,
1110 const CBlockIndex &last_header,
1111 bool received_new_header,
1112 bool may_have_more_headers)
1113 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1114
1115 void SendBlockTransactions(CNode &pfrom, Peer &peer, const CBlock &block,
1116 const BlockTransactionsRequest &req);
1117
1123 void AddTxAnnouncement(const CNode &node, const TxId &txid,
1124 std::chrono::microseconds current_time)
1126
1132 void
1133 AddProofAnnouncement(const CNode &node, const avalanche::ProofId &proofid,
1134 std::chrono::microseconds current_time, bool preferred)
1135 EXCLUSIVE_LOCKS_REQUIRED(cs_proofrequest);
1136
1138 void PushMessage(CNode &node, CSerializedNetMsg &&msg) const {
1139 m_connman.PushMessage(&node, std::move(msg));
1140 }
1141 template <typename... Args>
1142 void MakeAndPushMessage(CNode &node, std::string msg_type,
1143 Args &&...args) const {
1144 m_connman.PushMessage(&node, NetMsg::Make(std::move(msg_type),
1145 std::forward<Args>(args)...));
1146 }
1147
1149 void PushNodeVersion(const Config &config, CNode &pnode, const Peer &peer);
1150
1157 void MaybeSendPing(CNode &node_to, Peer &peer,
1158 std::chrono::microseconds now);
1159
1161 void MaybeSendAddr(CNode &node, Peer &peer,
1162 std::chrono::microseconds current_time)
1163 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1164
1169 void MaybeSendSendHeaders(CNode &node, Peer &peer)
1170 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1171
1173 void MaybeSendFeefilter(CNode &node, Peer &peer,
1174 std::chrono::microseconds current_time)
1175 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1176
1186 void RelayAddress(NodeId originator, const CAddress &addr, bool fReachable)
1187 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex);
1188
1190
1192 m_fee_filter_rounder GUARDED_BY(NetEventsInterface::g_msgproc_mutex);
1193
1194 const CChainParams &m_chainparams;
1195 CConnman &m_connman;
1196 AddrMan &m_addrman;
1201 BanMan *const m_banman;
1202 ChainstateManager &m_chainman;
1203 CTxMemPool &m_mempool;
1204 avalanche::Processor *const m_avalanche;
1206
1207 Mutex cs_proofrequest;
1209 m_proofrequest GUARDED_BY(cs_proofrequest);
1210
1212 std::atomic<int> m_best_height{-1};
1213
1215 std::chrono::seconds m_stale_tip_check_time GUARDED_BY(cs_main){0s};
1216
1217 const Options m_opts;
1218
1219 bool RejectIncomingTxs(const CNode &peer) const;
1220
1225 bool m_initial_sync_finished GUARDED_BY(cs_main){false};
1226
1231 mutable Mutex m_peer_mutex;
1238 std::map<NodeId, PeerRef> m_peer_map GUARDED_BY(m_peer_mutex);
1239
1241 std::map<NodeId, CNodeState> m_node_states GUARDED_BY(cs_main);
1242
1247 const CNodeState *State(NodeId pnode) const
1250 CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
1251
1252 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
1253
1255 int nSyncStarted GUARDED_BY(cs_main) = 0;
1256
1258 BlockHash
1259 m_last_block_inv_triggering_headers_sync GUARDED_BY(g_msgproc_mutex){};
1260
1267 std::map<BlockHash, std::pair<NodeId, bool>>
1268 mapBlockSource GUARDED_BY(cs_main);
1269
1271 int m_outbound_peers_with_protect_from_disconnect GUARDED_BY(cs_main) = 0;
1272
1274 int m_num_preferred_download_peers GUARDED_BY(cs_main){0};
1275
1277 std::atomic<std::chrono::seconds> m_block_stalling_timeout{
1279
1291 bool AlreadyHaveTx(const TxId &txid, bool include_reconsiderable)
1293 !m_recent_confirmed_transactions_mutex);
1294
1314 CRollingBloomFilter m_recent_rejects GUARDED_BY(::cs_main){120'000,
1315 0.000'001};
1316
1321 BlockHash hashRecentRejectsChainTip GUARDED_BY(cs_main);
1322
1348 CRollingBloomFilter m_recent_rejects_package_reconsiderable
1349 GUARDED_BY(::cs_main){120'000, 0.000'001};
1350
1356 mutable Mutex m_recent_confirmed_transactions_mutex;
1357 CRollingBloomFilter m_recent_confirmed_transactions
1358 GUARDED_BY(m_recent_confirmed_transactions_mutex){24'000, 0.000'001};
1359
1367 std::chrono::microseconds
1368 NextInvToInbounds(std::chrono::microseconds now,
1369 std::chrono::seconds average_interval)
1370 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1371
1372 // All of the following cache a recent block, and are protected by
1373 // m_most_recent_block_mutex
1374 mutable Mutex m_most_recent_block_mutex;
1375 std::shared_ptr<const CBlock>
1376 m_most_recent_block GUARDED_BY(m_most_recent_block_mutex);
1377 std::shared_ptr<const CBlockHeaderAndShortTxIDs>
1378 m_most_recent_compact_block GUARDED_BY(m_most_recent_block_mutex);
1379 BlockHash m_most_recent_block_hash GUARDED_BY(m_most_recent_block_mutex);
1380 std::unique_ptr<const std::map<TxId, CTransactionRef>>
1381 m_most_recent_block_txs GUARDED_BY(m_most_recent_block_mutex);
1382
1383 // Data about the low-work headers synchronization, aggregated from all
1384 // peers' HeadersSyncStates.
1386 Mutex m_headers_presync_mutex;
1397 using HeadersPresyncStats =
1398 std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
1400 std::map<NodeId, HeadersPresyncStats>
1401 m_headers_presync_stats GUARDED_BY(m_headers_presync_mutex){};
1403 NodeId m_headers_presync_bestpeer GUARDED_BY(m_headers_presync_mutex){-1};
1405 std::atomic_bool m_headers_presync_should_signal{false};
1406
1410 int m_highest_fast_announce GUARDED_BY(::cs_main){0};
1411
1413 bool IsBlockRequested(const BlockHash &hash)
1415
1417 bool IsBlockRequestedFromOutbound(const BlockHash &hash)
1419
1428 void RemoveBlockRequest(const BlockHash &hash,
1429 std::optional<NodeId> from_peer)
1431
1438 bool BlockRequested(const Config &config, NodeId nodeid,
1439 const CBlockIndex &block,
1440 std::list<QueuedBlock>::iterator **pit = nullptr)
1442
1443 bool TipMayBeStale() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
1444
1449 void FindNextBlocksToDownload(const Peer &peer, unsigned int count,
1450 std::vector<const CBlockIndex *> &vBlocks,
1451 NodeId &nodeStaller)
1453
1455 void TryDownloadingHistoricalBlocks(
1456 const Peer &peer, unsigned int count,
1457 std::vector<const CBlockIndex *> &vBlocks, const CBlockIndex *from_tip,
1458 const CBlockIndex *target_block) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
1459
1489 void FindNextBlocks(std::vector<const CBlockIndex *> &vBlocks,
1490 const Peer &peer, CNodeState *state,
1491 const CBlockIndex *pindexWalk, unsigned int count,
1492 int nWindowEnd, const CChain *activeChain = nullptr,
1493 NodeId *nodeStaller = nullptr)
1495
1497 typedef std::multimap<BlockHash,
1498 std::pair<NodeId, std::list<QueuedBlock>::iterator>>
1499 BlockDownloadMap;
1500 BlockDownloadMap mapBlocksInFlight GUARDED_BY(cs_main);
1501
1503 std::atomic<std::chrono::seconds> m_last_tip_update{0s};
1504
1509 CTransactionRef FindTxForGetData(const Peer &peer, const TxId &txid,
1510 const std::chrono::seconds mempool_req,
1511 const std::chrono::seconds now)
1513 EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex,
1515
1516 void ProcessGetData(const Config &config, CNode &pfrom, Peer &peer,
1517 const std::atomic<bool> &interruptMsgProc)
1518 EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex,
1519 peer.m_getdata_requests_mutex,
1522
1524 void ProcessBlock(const Config &config, CNode &node,
1525 const std::shared_ptr<const CBlock> &block,
1526 bool force_processing, bool min_pow_checked);
1527
1534 void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid)
1536
1538 std::list<NodeId> lNodesAnnouncingHeaderAndIDs GUARDED_BY(cs_main);
1539
1541 int m_peers_downloading_from GUARDED_BY(cs_main) = 0;
1542
1543 void AddToCompactExtraTransactions(const CTransactionRef &tx)
1544 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1545
1553 std::vector<CTransactionRef>
1554 vExtraTxnForCompact GUARDED_BY(g_msgproc_mutex);
1556 size_t vExtraTxnForCompactIt GUARDED_BY(g_msgproc_mutex) = 0;
1557
1561 void ProcessBlockAvailability(NodeId nodeid)
1566 void UpdateBlockAvailability(NodeId nodeid, const BlockHash &hash)
1568 bool CanDirectFetch() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
1569
1576 bool BlockRequestAllowed(const CBlockIndex *pindex)
1578 bool AlreadyHaveBlock(const BlockHash &block_hash)
1580 bool AlreadyHaveProof(const avalanche::ProofId &proofid);
1581 void ProcessGetBlockData(const Config &config, CNode &pfrom, Peer &peer,
1582 const CInv &inv)
1583 EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex);
1584
1604 bool PrepareBlockFilterRequest(CNode &node, Peer &peer,
1605 BlockFilterType filter_type,
1606 uint32_t start_height,
1607 const BlockHash &stop_hash,
1608 uint32_t max_height_diff,
1609 const CBlockIndex *&stop_index,
1610 BlockFilterIndex *&filter_index);
1611
1621 void ProcessGetCFilters(CNode &node, Peer &peer, DataStream &vRecv);
1631 void ProcessGetCFHeaders(CNode &node, Peer &peer, DataStream &vRecv);
1632
1642 void ProcessGetCFCheckPt(CNode &node, Peer &peer, DataStream &vRecv);
1643
1650 uint32_t GetAvalancheVoteForBlock(const BlockHash &hash) const
1652
1660 uint32_t GetAvalancheVoteForTx(const avalanche::Processor &avalanche,
1661 const TxId &id) const
1662 EXCLUSIVE_LOCKS_REQUIRED(!m_mempool.cs,
1663 !m_recent_confirmed_transactions_mutex);
1664
1672 bool SetupAddressRelay(const CNode &node, Peer &peer)
1673 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1674
1675 void AddAddressKnown(Peer &peer, const CAddress &addr)
1676 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1677 void PushAddress(Peer &peer, const CAddress &addr)
1678 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1679
1685 bool ReceivedAvalancheProof(CNode &node, Peer &peer,
1686 const avalanche::ProofRef &proof)
1687 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !cs_proofrequest);
1688
1689 avalanche::ProofRef FindProofForGetData(const Peer &peer,
1690 const avalanche::ProofId &proofid,
1691 const std::chrono::seconds now)
1693
1694 bool isPreferredDownloadPeer(const CNode &pfrom);
1695};
1696
1697const CNodeState *PeerManagerImpl::State(NodeId pnode) const
1699 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1700 if (it == m_node_states.end()) {
1701 return nullptr;
1702 }
1703
1704 return &it->second;
1705}
1706
1707CNodeState *PeerManagerImpl::State(NodeId pnode)
1709 return const_cast<CNodeState *>(std::as_const(*this).State(pnode));
1710}
1711
1717static bool IsAddrCompatible(const Peer &peer, const CAddress &addr) {
1718 return peer.m_wants_addrv2 || addr.IsAddrV1Compatible();
1719}
1720
1721void PeerManagerImpl::AddAddressKnown(Peer &peer, const CAddress &addr) {
1722 assert(peer.m_addr_known);
1723 peer.m_addr_known->insert(addr.GetKey());
1724}
1725
1726void PeerManagerImpl::PushAddress(Peer &peer, const CAddress &addr) {
1727 // Known checking here is only to save space from duplicates.
1728 // Before sending, we'll filter it again for known addresses that were
1729 // added after addresses were pushed.
1730 assert(peer.m_addr_known);
1731 if (addr.IsValid() && !peer.m_addr_known->contains(addr.GetKey()) &&
1732 IsAddrCompatible(peer, addr)) {
1733 if (peer.m_addrs_to_send.size() >= m_opts.max_addr_to_send) {
1734 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] =
1735 addr;
1736 } else {
1737 peer.m_addrs_to_send.push_back(addr);
1738 }
1739 }
1740}
1741
1742static void AddKnownTx(Peer &peer, const TxId &txid) {
1743 auto tx_relay = peer.GetTxRelay();
1744 if (!tx_relay) {
1745 return;
1746 }
1747
1748 LOCK(tx_relay->m_tx_inventory_mutex);
1749 tx_relay->m_tx_inventory_known_filter.insert(txid);
1750}
1751
1752static void AddKnownProof(Peer &peer, const avalanche::ProofId &proofid) {
1753 if (peer.m_proof_relay != nullptr) {
1754 LOCK(peer.m_proof_relay->m_proof_inventory_mutex);
1755 peer.m_proof_relay->m_proof_inventory_known_filter.insert(proofid);
1756 }
1757}
1758
1759bool PeerManagerImpl::isPreferredDownloadPeer(const CNode &pfrom) {
1760 LOCK(cs_main);
1761 const CNodeState *state = State(pfrom.GetId());
1762 return state && state->fPreferredDownload;
1763}
1765static bool CanServeBlocks(const Peer &peer) {
1766 return peer.m_their_services & (NODE_NETWORK | NODE_NETWORK_LIMITED);
1767}
1768
1773static bool IsLimitedPeer(const Peer &peer) {
1774 return (!(peer.m_their_services & NODE_NETWORK) &&
1775 (peer.m_their_services & NODE_NETWORK_LIMITED));
1776}
1777
1778std::chrono::microseconds
1779PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1780 std::chrono::seconds average_interval) {
1781 if (m_next_inv_to_inbounds.load() < now) {
1782 // If this function were called from multiple threads simultaneously
1783 // it would possible that both update the next send variable, and return
1784 // a different result to their caller. This is not possible in practice
1785 // as only the net processing thread invokes this function.
1786 m_next_inv_to_inbounds =
1787 now + m_rng.rand_exp_duration(average_interval);
1788 }
1789 return m_next_inv_to_inbounds;
1790}
1791
1792bool PeerManagerImpl::IsBlockRequested(const BlockHash &hash) {
1793 return mapBlocksInFlight.count(hash);
1794}
1795
1796bool PeerManagerImpl::IsBlockRequestedFromOutbound(const BlockHash &hash) {
1797 for (auto range = mapBlocksInFlight.equal_range(hash);
1798 range.first != range.second; range.first++) {
1799 auto [nodeid, block_it] = range.first->second;
1800 CNodeState &nodestate = *Assert(State(nodeid));
1801 if (!nodestate.m_is_inbound) {
1802 return true;
1803 }
1804 }
1805
1806 return false;
1807}
1808
1809void PeerManagerImpl::RemoveBlockRequest(const BlockHash &hash,
1810 std::optional<NodeId> from_peer) {
1811 auto range = mapBlocksInFlight.equal_range(hash);
1812 if (range.first == range.second) {
1813 // Block was not requested from any peer
1814 return;
1815 }
1816
1817 // We should not have requested too many of this block
1818 Assume(mapBlocksInFlight.count(hash) <= MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK);
1819
1820 while (range.first != range.second) {
1821 auto [node_id, list_it] = range.first->second;
1822
1823 if (from_peer && *from_peer != node_id) {
1824 range.first++;
1825 continue;
1826 }
1827
1828 CNodeState &state = *Assert(State(node_id));
1829
1830 if (state.vBlocksInFlight.begin() == list_it) {
1831 // First block on the queue was received, update the start download
1832 // time for the next one
1833 state.m_downloading_since =
1834 std::max(state.m_downloading_since,
1835 GetTime<std::chrono::microseconds>());
1836 }
1837 state.vBlocksInFlight.erase(list_it);
1838
1839 if (state.vBlocksInFlight.empty()) {
1840 // Last validated block on the queue for this peer was received.
1841 m_peers_downloading_from--;
1842 }
1843 state.m_stalling_since = 0us;
1844
1845 range.first = mapBlocksInFlight.erase(range.first);
1846 }
1847}
1848
1849bool PeerManagerImpl::BlockRequested(const Config &config, NodeId nodeid,
1850 const CBlockIndex &block,
1851 std::list<QueuedBlock>::iterator **pit) {
1852 const BlockHash &hash{block.GetBlockHash()};
1853
1854 CNodeState *state = State(nodeid);
1855 assert(state != nullptr);
1856
1857 Assume(mapBlocksInFlight.count(hash) <= MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK);
1858
1859 // Short-circuit most stuff in case it is from the same node
1860 for (auto range = mapBlocksInFlight.equal_range(hash);
1861 range.first != range.second; range.first++) {
1862 if (range.first->second.first == nodeid) {
1863 if (pit) {
1864 *pit = &range.first->second.second;
1865 }
1866 return false;
1867 }
1868 }
1869
1870 // Make sure it's not being fetched already from same peer.
1871 RemoveBlockRequest(hash, nodeid);
1872
1873 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(
1874 state->vBlocksInFlight.end(),
1875 {&block, std::unique_ptr<PartiallyDownloadedBlock>(
1876 pit ? new PartiallyDownloadedBlock(config, &m_mempool)
1877 : nullptr)});
1878 if (state->vBlocksInFlight.size() == 1) {
1879 // We're starting a block download (batch) from this peer.
1880 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1881 m_peers_downloading_from++;
1882 }
1883
1884 auto itInFlight = mapBlocksInFlight.insert(
1885 std::make_pair(hash, std::make_pair(nodeid, it)));
1886
1887 if (pit) {
1888 *pit = &itInFlight->second.second;
1889 }
1890
1891 return true;
1892}
1893
1894void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid) {
1896
1897 // When in -blocksonly mode, never request high-bandwidth mode from peers.
1898 // Our mempool will not contain the transactions necessary to reconstruct
1899 // the compact block.
1900 if (m_opts.ignore_incoming_txs) {
1901 return;
1902 }
1903
1904 CNodeState *nodestate = State(nodeid);
1905 if (!nodestate) {
1906 LogPrint(BCLog::NET, "node state unavailable: peer=%d\n", nodeid);
1907 return;
1908 }
1909 if (!nodestate->m_provides_cmpctblocks) {
1910 return;
1911 }
1912 int num_outbound_hb_peers = 0;
1913 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin();
1914 it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1915 if (*it == nodeid) {
1916 lNodesAnnouncingHeaderAndIDs.erase(it);
1917 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1918 return;
1919 }
1920 CNodeState *state = State(*it);
1921 if (state != nullptr && !state->m_is_inbound) {
1922 ++num_outbound_hb_peers;
1923 }
1924 }
1925 if (nodestate->m_is_inbound) {
1926 // If we're adding an inbound HB peer, make sure we're not removing
1927 // our last outbound HB peer in the process.
1928 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 &&
1929 num_outbound_hb_peers == 1) {
1930 CNodeState *remove_node =
1931 State(lNodesAnnouncingHeaderAndIDs.front());
1932 if (remove_node != nullptr && !remove_node->m_is_inbound) {
1933 // Put the HB outbound peer in the second slot, so that it
1934 // doesn't get removed.
1935 std::swap(lNodesAnnouncingHeaderAndIDs.front(),
1936 *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1937 }
1938 }
1939 }
1940 m_connman.ForNode(nodeid, [this](CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(
1941 ::cs_main) {
1943 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1944 // As per BIP152, we only get 3 of our peers to announce
1945 // blocks using compact encodings.
1946 m_connman.ForNode(
1947 lNodesAnnouncingHeaderAndIDs.front(), [this](CNode *pnodeStop) {
1948 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT,
1949 /*high_bandwidth=*/false,
1950 /*version=*/CMPCTBLOCKS_VERSION);
1951 // save BIP152 bandwidth state: we select peer to be
1952 // low-bandwidth
1953 pnodeStop->m_bip152_highbandwidth_to = false;
1954 return true;
1955 });
1956 lNodesAnnouncingHeaderAndIDs.pop_front();
1957 }
1958 MakeAndPushMessage(*pfrom, NetMsgType::SENDCMPCT,
1959 /*high_bandwidth=*/true,
1960 /*version=*/CMPCTBLOCKS_VERSION);
1961 // save BIP152 bandwidth state: we select peer to be high-bandwidth
1962 pfrom->m_bip152_highbandwidth_to = true;
1963 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId());
1964 return true;
1965 });
1966}
1967
1968bool PeerManagerImpl::TipMayBeStale() {
1970 const Consensus::Params &consensusParams = m_chainparams.GetConsensus();
1971 if (m_last_tip_update.load() == 0s) {
1972 m_last_tip_update = GetTime<std::chrono::seconds>();
1973 }
1974 return m_last_tip_update.load() <
1975 GetTime<std::chrono::seconds>() -
1976 std::chrono::seconds{consensusParams.nPowTargetSpacing *
1977 3} &&
1978 mapBlocksInFlight.empty();
1979}
1980
1981bool PeerManagerImpl::CanDirectFetch() {
1982 return m_chainman.ActiveChain().Tip()->Time() >
1983 GetAdjustedTime() -
1984 m_chainparams.GetConsensus().PowTargetSpacing() * 20;
1985}
1986
1987static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex)
1989 if (state->pindexBestKnownBlock &&
1990 pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight)) {
1991 return true;
1992 }
1993 if (state->pindexBestHeaderSent &&
1994 pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight)) {
1995 return true;
1996 }
1997 return false;
1998}
1999
2000void PeerManagerImpl::ProcessBlockAvailability(NodeId nodeid) {
2001 CNodeState *state = State(nodeid);
2002 assert(state != nullptr);
2003
2004 if (!state->hashLastUnknownBlock.IsNull()) {
2005 const CBlockIndex *pindex =
2006 m_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock);
2007 if (pindex && pindex->nChainWork > 0) {
2008 if (state->pindexBestKnownBlock == nullptr ||
2009 pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) {
2010 state->pindexBestKnownBlock = pindex;
2011 }
2012 state->hashLastUnknownBlock.SetNull();
2013 }
2014 }
2015}
2016
2017void PeerManagerImpl::UpdateBlockAvailability(NodeId nodeid,
2018 const BlockHash &hash) {
2019 CNodeState *state = State(nodeid);
2020 assert(state != nullptr);
2021
2022 ProcessBlockAvailability(nodeid);
2023
2024 const CBlockIndex *pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
2025 if (pindex && pindex->nChainWork > 0) {
2026 // An actually better block was announced.
2027 if (state->pindexBestKnownBlock == nullptr ||
2028 pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) {
2029 state->pindexBestKnownBlock = pindex;
2030 }
2031 } else {
2032 // An unknown block was announced; just assume that the latest one is
2033 // the best one.
2034 state->hashLastUnknownBlock = hash;
2035 }
2036}
2037
2038// Logic for calculating which blocks to download from a given peer, given
2039// our current tip.
2040void PeerManagerImpl::FindNextBlocksToDownload(
2041 const Peer &peer, unsigned int count,
2042 std::vector<const CBlockIndex *> &vBlocks, NodeId &nodeStaller) {
2043 if (count == 0) {
2044 return;
2045 }
2046
2047 vBlocks.reserve(vBlocks.size() + count);
2048 CNodeState *state = State(peer.m_id);
2049 assert(state != nullptr);
2050
2051 // Make sure pindexBestKnownBlock is up to date, we'll need it.
2052 ProcessBlockAvailability(peer.m_id);
2053
2054 if (state->pindexBestKnownBlock == nullptr ||
2055 state->pindexBestKnownBlock->nChainWork <
2056 m_chainman.ActiveChain().Tip()->nChainWork ||
2057 state->pindexBestKnownBlock->nChainWork <
2058 m_chainman.MinimumChainWork()) {
2059 // This peer has nothing interesting.
2060 return;
2061 }
2062
2063 // When we sync with AssumeUtxo and discover the snapshot is not in the
2064 // peer's best chain, abort: We can't reorg to this chain due to missing
2065 // undo data until the background sync has finished, so downloading blocks
2066 // from it would be futile.
2067 const CBlockIndex *snap_base{m_chainman.GetSnapshotBaseBlock()};
2068 if (snap_base && state->pindexBestKnownBlock->GetAncestor(
2069 snap_base->nHeight) != snap_base) {
2071 "Not downloading blocks from peer=%d, which doesn't have the "
2072 "snapshot block in its best chain.\n",
2073 peer.m_id);
2074 return;
2075 }
2076
2077 // Bootstrap quickly by guessing a parent of our best tip is the forking
2078 // point. Guessing wrong in either direction is not a problem. Also reset
2079 // pindexLastCommonBlock after a snapshot was loaded, so that blocks after
2080 // the snapshot will be prioritised for download.
2081 if (state->pindexLastCommonBlock == nullptr ||
2082 (snap_base &&
2083 state->pindexLastCommonBlock->nHeight < snap_base->nHeight)) {
2084 state->pindexLastCommonBlock =
2085 m_chainman
2086 .ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight,
2087 m_chainman.ActiveChain().Height())];
2088 }
2089
2090 // If the peer reorganized, our previous pindexLastCommonBlock may not be an
2091 // ancestor of its current tip anymore. Go back enough to fix that.
2092 state->pindexLastCommonBlock = LastCommonAncestor(
2093 state->pindexLastCommonBlock, state->pindexBestKnownBlock);
2094 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock) {
2095 return;
2096 }
2097
2098 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
2099 // Never fetch further than the best block we know the peer has, or more
2100 // than BLOCK_DOWNLOAD_WINDOW + 1 beyond the last linked block we have in
2101 // common with this peer. The +1 is so we can detect stalling, namely if we
2102 // would be able to download that next block if the window were 1 larger.
2103 int nWindowEnd =
2104 state->pindexLastCommonBlock->nHeight + BLOCK_DOWNLOAD_WINDOW;
2105
2106 FindNextBlocks(vBlocks, peer, state, pindexWalk, count, nWindowEnd,
2107 &m_chainman.ActiveChain(), &nodeStaller);
2108}
2109
2110void PeerManagerImpl::TryDownloadingHistoricalBlocks(
2111 const Peer &peer, unsigned int count,
2112 std::vector<const CBlockIndex *> &vBlocks, const CBlockIndex *from_tip,
2113 const CBlockIndex *target_block) {
2114 Assert(from_tip);
2115 Assert(target_block);
2116
2117 if (vBlocks.size() >= count) {
2118 return;
2119 }
2120
2121 vBlocks.reserve(count);
2122 CNodeState *state = Assert(State(peer.m_id));
2123
2124 if (state->pindexBestKnownBlock == nullptr ||
2125 state->pindexBestKnownBlock->GetAncestor(target_block->nHeight) !=
2126 target_block) {
2127 // This peer can't provide us the complete series of blocks leading up
2128 // to the assumeutxo snapshot base.
2129 //
2130 // Presumably this peer's chain has less work than our ActiveChain()'s
2131 // tip, or else we will eventually crash when we try to reorg to it. Let
2132 // other logic deal with whether we disconnect this peer.
2133 //
2134 // TODO at some point in the future, we might choose to request what
2135 // blocks this peer does have from the historical chain, despite it not
2136 // having a complete history beneath the snapshot base.
2137 return;
2138 }
2139
2140 FindNextBlocks(vBlocks, peer, state, from_tip, count,
2141 std::min<int>(from_tip->nHeight + BLOCK_DOWNLOAD_WINDOW,
2142 target_block->nHeight));
2143}
2144
2145void PeerManagerImpl::FindNextBlocks(std::vector<const CBlockIndex *> &vBlocks,
2146 const Peer &peer, CNodeState *state,
2147 const CBlockIndex *pindexWalk,
2148 unsigned int count, int nWindowEnd,
2149 const CChain *activeChain,
2150 NodeId *nodeStaller) {
2151 std::vector<const CBlockIndex *> vToFetch;
2152 int nMaxHeight =
2153 std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
2154 NodeId waitingfor = -1;
2155 while (pindexWalk->nHeight < nMaxHeight) {
2156 // Read up to 128 (or more, if more blocks than that are needed)
2157 // successors of pindexWalk (towards pindexBestKnownBlock) into
2158 // vToFetch. We fetch 128, because CBlockIndex::GetAncestor may be as
2159 // expensive as iterating over ~100 CBlockIndex* entries anyway.
2160 int nToFetch = std::min(nMaxHeight - pindexWalk->nHeight,
2161 std::max<int>(count - vBlocks.size(), 128));
2162 vToFetch.resize(nToFetch);
2163 pindexWalk = state->pindexBestKnownBlock->GetAncestor(
2164 pindexWalk->nHeight + nToFetch);
2165 vToFetch[nToFetch - 1] = pindexWalk;
2166 for (unsigned int i = nToFetch - 1; i > 0; i--) {
2167 vToFetch[i - 1] = vToFetch[i]->pprev;
2168 }
2169
2170 // Iterate over those blocks in vToFetch (in forward direction), adding
2171 // the ones that are not yet downloaded and not in flight to vBlocks. In
2172 // the meantime, update pindexLastCommonBlock as long as all ancestors
2173 // are already downloaded, or if it's already part of our chain (and
2174 // therefore don't need it even if pruned).
2175 for (const CBlockIndex *pindex : vToFetch) {
2176 if (!pindex->IsValid(BlockValidity::TREE)) {
2177 // We consider the chain that this peer is on invalid.
2178 return;
2179 }
2180 if (pindex->nStatus.hasData() ||
2181 (activeChain && activeChain->Contains(pindex))) {
2182 if (activeChain && pindex->HaveNumChainTxs()) {
2183 state->pindexLastCommonBlock = pindex;
2184 }
2185 } else if (!IsBlockRequested(pindex->GetBlockHash())) {
2186 // The block is not already downloaded, and not yet in flight.
2187 if (pindex->nHeight > nWindowEnd) {
2188 // We reached the end of the window.
2189 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
2190 // We aren't able to fetch anything, but we would be if
2191 // the download window was one larger.
2192 if (nodeStaller) {
2193 *nodeStaller = waitingfor;
2194 }
2195 }
2196 return;
2197 }
2198 vBlocks.push_back(pindex);
2199 if (vBlocks.size() == count) {
2200 return;
2201 }
2202 } else if (waitingfor == -1) {
2203 // This is the first already-in-flight block.
2204 waitingfor =
2205 mapBlocksInFlight.lower_bound(pindex->GetBlockHash())
2206 ->second.first;
2207 }
2208 }
2209 }
2210}
2211
2212} // namespace
2213
2214template <class InvId>
2216 const InvRequestTracker<InvId> &requestTracker,
2217 const DataRequestParameters &requestParams) {
2218 return !node.HasPermission(
2219 requestParams.bypass_request_limits_permissions) &&
2220 requestTracker.Count(node.GetId()) >=
2221 requestParams.max_peer_announcements;
2222}
2223
2231template <class InvId>
2232static std::chrono::microseconds
2234 const InvRequestTracker<InvId> &requestTracker,
2235 const DataRequestParameters &requestParams,
2236 std::chrono::microseconds current_time, bool preferred) {
2237 auto delay = std::chrono::microseconds{0};
2238
2239 if (!preferred) {
2240 delay += requestParams.nonpref_peer_delay;
2241 }
2242
2243 if (!node.HasPermission(requestParams.bypass_request_limits_permissions) &&
2244 requestTracker.CountInFlight(node.GetId()) >=
2245 requestParams.max_peer_request_in_flight) {
2246 delay += requestParams.overloaded_peer_delay;
2247 }
2248
2249 return current_time + delay;
2250}
2251
2252void PeerManagerImpl::PushNodeVersion(const Config &config, CNode &pnode,
2253 const Peer &peer) {
2254 uint64_t my_services{peer.m_our_services};
2255 const int64_t nTime{count_seconds(GetTime<std::chrono::seconds>())};
2256 uint64_t nonce = pnode.GetLocalNonce();
2257 const int nNodeStartingHeight{m_best_height};
2258 NodeId nodeid = pnode.GetId();
2259 CAddress addr = pnode.addr;
2260 uint64_t extraEntropy = pnode.GetLocalExtraEntropy();
2261
2262 CService addr_you =
2263 addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible()
2264 ? addr
2265 : CService();
2266 uint64_t your_services{addr.nServices};
2267
2268 const bool tx_relay{!RejectIncomingTxs(pnode)};
2269 MakeAndPushMessage(
2270 // your_services, addr_you: Together the pre-version-31402 serialization
2271 // of CAddress "addrYou" (without nTime)
2272 // my_services, CService(): Together the pre-version-31402 serialization
2273 // of CAddress "addrMe" (without nTime)
2274 pnode, NetMsgType::VERSION, PROTOCOL_VERSION, my_services, nTime,
2275 your_services, WithParams(CNetAddr::V1, addr_you), my_services,
2276 WithParams(CNetAddr::V1, CService{}), nonce, userAgent(config),
2277 nNodeStartingHeight, tx_relay, extraEntropy);
2278
2279 if (fLogIPs) {
2281 "send version message: version %d, blocks=%d, them=%s, "
2282 "txrelay=%d, peer=%d\n",
2283 PROTOCOL_VERSION, nNodeStartingHeight,
2284 addr_you.ToStringAddrPort(), tx_relay, nodeid);
2285 } else {
2287 "send version message: version %d, blocks=%d, "
2288 "txrelay=%d, peer=%d\n",
2289 PROTOCOL_VERSION, nNodeStartingHeight, tx_relay, nodeid);
2290 }
2291}
2292
2293void PeerManagerImpl::AddTxAnnouncement(
2294 const CNode &node, const TxId &txid,
2295 std::chrono::microseconds current_time) {
2296 // For m_txrequest and state
2298
2299 if (TooManyAnnouncements(node, m_txrequest, TX_REQUEST_PARAMS)) {
2300 return;
2301 }
2302
2303 const bool preferred = isPreferredDownloadPeer(node);
2304 auto reqtime = ComputeRequestTime(node, m_txrequest, TX_REQUEST_PARAMS,
2305 current_time, preferred);
2306
2307 m_txrequest.ReceivedInv(node.GetId(), txid, preferred, reqtime);
2308}
2309
2310void PeerManagerImpl::AddProofAnnouncement(
2311 const CNode &node, const avalanche::ProofId &proofid,
2312 std::chrono::microseconds current_time, bool preferred) {
2313 // For m_proofrequest
2314 AssertLockHeld(cs_proofrequest);
2315
2316 if (TooManyAnnouncements(node, m_proofrequest, PROOF_REQUEST_PARAMS)) {
2317 return;
2318 }
2319
2320 auto reqtime = ComputeRequestTime(
2321 node, m_proofrequest, PROOF_REQUEST_PARAMS, current_time, preferred);
2322
2323 m_proofrequest.ReceivedInv(node.GetId(), proofid, preferred, reqtime);
2324}
2325
2326void PeerManagerImpl::UpdateLastBlockAnnounceTime(NodeId node,
2327 int64_t time_in_seconds) {
2328 LOCK(cs_main);
2329 CNodeState *state = State(node);
2330 if (state) {
2331 state->m_last_block_announcement = time_in_seconds;
2332 }
2333}
2334
2335void PeerManagerImpl::InitializeNode(const Config &config, CNode &node,
2336 ServiceFlags our_services) {
2337 NodeId nodeid = node.GetId();
2338 {
2339 LOCK(cs_main);
2340 m_node_states.emplace_hint(m_node_states.end(),
2341 std::piecewise_construct,
2342 std::forward_as_tuple(nodeid),
2343 std::forward_as_tuple(node.IsInboundConn()));
2344 assert(m_txrequest.Count(nodeid) == 0);
2345 }
2346
2347 if (NetPermissions::HasFlag(node.m_permission_flags,
2349 our_services = static_cast<ServiceFlags>(our_services | NODE_BLOOM);
2350 }
2351
2352 PeerRef peer = std::make_shared<Peer>(nodeid, our_services, !!m_avalanche);
2353 {
2354 LOCK(m_peer_mutex);
2355 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
2356 }
2357 if (!node.IsInboundConn()) {
2358 PushNodeVersion(config, node, *peer);
2359 }
2360}
2361
2362void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler &scheduler) {
2363 std::set<TxId> unbroadcast_txids = m_mempool.GetUnbroadcastTxs();
2364
2365 for (const TxId &txid : unbroadcast_txids) {
2366 // Sanity check: all unbroadcast txns should exist in the mempool
2367 if (m_mempool.exists(txid)) {
2368 RelayTransaction(txid);
2369 } else {
2370 m_mempool.RemoveUnbroadcastTx(txid, true);
2371 }
2372 }
2373
2374 if (m_avalanche) {
2375 // Get and sanitize the list of proofids to broadcast. The RelayProof
2376 // call is done in a second loop to avoid locking cs_vNodes while
2377 // cs_peerManager is locked which would cause a potential deadlock due
2378 // to reversed lock order.
2379 auto unbroadcasted_proofids =
2380 m_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
2381 auto unbroadcasted_proofids = pm.getUnbroadcastProofs();
2382
2383 auto it = unbroadcasted_proofids.begin();
2384 while (it != unbroadcasted_proofids.end()) {
2385 // Sanity check: all unbroadcast proofs should be bound to a
2386 // peer in the peermanager
2387 if (!pm.isBoundToPeer(*it)) {
2388 pm.removeUnbroadcastProof(*it);
2389 it = unbroadcasted_proofids.erase(it);
2390 continue;
2391 }
2392
2393 ++it;
2394 }
2395
2396 return unbroadcasted_proofids;
2397 });
2398
2399 // Remaining proofids are the ones to broadcast
2400 for (const auto &proofid : unbroadcasted_proofids) {
2401 RelayProof(proofid);
2402 }
2403 }
2404
2405 // Schedule next run for 10-15 minutes in the future.
2406 // We add randomness on every cycle to avoid the possibility of P2P
2407 // fingerprinting.
2408 const auto reattemptBroadcastInterval =
2409 10min + FastRandomContext().randrange<std::chrono::milliseconds>(5min);
2410 scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); },
2411 reattemptBroadcastInterval);
2412}
2413
2414void PeerManagerImpl::UpdateAvalancheStatistics() const {
2415 m_connman.ForEachNode([](CNode *pnode) {
2417 });
2418}
2419
2420void PeerManagerImpl::AvalanchePeriodicNetworking(CScheduler &scheduler) const {
2421 const auto now = GetTime<std::chrono::seconds>();
2422 std::vector<NodeId> avanode_ids;
2423 bool fQuorumEstablished;
2424 bool fShouldRequestMoreNodes;
2425
2426 if (!m_avalanche) {
2427 // Not enabled or not ready yet, retry later
2428 goto scheduleLater;
2429 }
2430
2431 m_avalanche->sendDelayedAvahello();
2432
2433 fQuorumEstablished = m_avalanche->isQuorumEstablished();
2434 fShouldRequestMoreNodes =
2435 m_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
2436 return pm.shouldRequestMoreNodes();
2437 });
2438
2439 m_connman.ForEachNode([&](CNode *pnode) {
2440 // Build a list of the avalanche peers nodeids
2441 if (pnode->m_avalanche_enabled) {
2442 avanode_ids.push_back(pnode->GetId());
2443 }
2444
2445 PeerRef peer = GetPeerRef(pnode->GetId());
2446 if (peer == nullptr) {
2447 return;
2448 }
2449 // If a proof radix tree timed out, cleanup
2450 if (peer->m_proof_relay &&
2451 now > (peer->m_proof_relay->lastSharedProofsUpdate.load() +
2453 peer->m_proof_relay->sharedProofs = {};
2454 }
2455 });
2456
2457 if (avanode_ids.empty()) {
2458 // No node is available for messaging, retry later
2459 goto scheduleLater;
2460 }
2461
2462 Shuffle(avanode_ids.begin(), avanode_ids.end(), FastRandomContext());
2463
2464 // Request avalanche addresses from our peers
2465 for (NodeId avanodeId : avanode_ids) {
2466 const bool sentGetavaaddr =
2467 m_connman.ForNode(avanodeId, [&](CNode *pavanode) {
2468 if (!fQuorumEstablished || !pavanode->IsInboundConn()) {
2469 MakeAndPushMessage(*pavanode, NetMsgType::GETAVAADDR);
2470 PeerRef peer = GetPeerRef(avanodeId);
2471 WITH_LOCK(peer->m_addr_token_bucket_mutex,
2472 peer->m_addr_token_bucket +=
2473 m_opts.max_addr_to_send);
2474 return true;
2475 }
2476 return false;
2477 });
2478
2479 // If we have no reason to believe that we need more nodes, only request
2480 // addresses from one of our peers.
2481 if (sentGetavaaddr && fQuorumEstablished && !fShouldRequestMoreNodes) {
2482 break;
2483 }
2484 }
2485
2486 if (m_chainman.IsInitialBlockDownload()) {
2487 // Don't request proofs while in IBD. We're likely to orphan them
2488 // because we don't have the UTXOs.
2489 goto scheduleLater;
2490 }
2491
2492 // If we never had an avaproofs message yet, be kind and only request to a
2493 // subset of our peers as we expect a ton of avaproofs message in the
2494 // process.
2495 if (m_avalanche->getAvaproofsNodeCounter() == 0) {
2496 avanode_ids.resize(std::min<size_t>(avanode_ids.size(), 3));
2497 }
2498
2499 for (NodeId nodeid : avanode_ids) {
2500 // Send a getavaproofs to all of our peers
2501 m_connman.ForNode(nodeid, [&](CNode *pavanode) {
2502 PeerRef peer = GetPeerRef(nodeid);
2503 if (peer->m_proof_relay) {
2504 MakeAndPushMessage(*pavanode, NetMsgType::GETAVAPROOFS);
2505 peer->m_proof_relay->compactproofs_requested = true;
2506 }
2507 return true;
2508 });
2509 }
2510
2511scheduleLater:
2512 // Schedule next run for 2-5 minutes in the future.
2513 // We add randomness on every cycle to avoid the possibility of P2P
2514 // fingerprinting.
2515 const auto avalanchePeriodicNetworkingInterval =
2516 2min + FastRandomContext().randrange<std::chrono::milliseconds>(3min);
2517 scheduler.scheduleFromNow([&] { AvalanchePeriodicNetworking(scheduler); },
2518 avalanchePeriodicNetworkingInterval);
2519}
2520
2521void PeerManagerImpl::FinalizeNode(const Config &config, const CNode &node) {
2522 NodeId nodeid = node.GetId();
2523 {
2524 LOCK(cs_main);
2525 {
2526 // We remove the PeerRef from g_peer_map here, but we don't always
2527 // destruct the Peer. Sometimes another thread is still holding a
2528 // PeerRef, so the refcount is >= 1. Be careful not to do any
2529 // processing here that assumes Peer won't be changed before it's
2530 // destructed.
2531 PeerRef peer = RemovePeer(nodeid);
2532 assert(peer != nullptr);
2533 LOCK(m_peer_mutex);
2534 m_peer_map.erase(nodeid);
2535 }
2536 CNodeState *state = State(nodeid);
2537 assert(state != nullptr);
2538
2539 if (state->fSyncStarted) {
2540 nSyncStarted--;
2541 }
2542
2543 for (const QueuedBlock &entry : state->vBlocksInFlight) {
2544 auto range =
2545 mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
2546 while (range.first != range.second) {
2547 auto [node_id, list_it] = range.first->second;
2548 if (node_id != nodeid) {
2549 range.first++;
2550 } else {
2551 range.first = mapBlocksInFlight.erase(range.first);
2552 }
2553 }
2554 }
2555 m_mempool.withOrphanage([nodeid](TxOrphanage &orphanage) {
2556 orphanage.EraseForPeer(nodeid);
2557 });
2558 m_txrequest.DisconnectedPeer(nodeid);
2559 m_num_preferred_download_peers -= state->fPreferredDownload;
2560 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
2561 assert(m_peers_downloading_from >= 0);
2562 m_outbound_peers_with_protect_from_disconnect -=
2563 state->m_chain_sync.m_protect;
2564 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
2565
2566 m_node_states.erase(nodeid);
2567
2568 if (m_node_states.empty()) {
2569 // Do a consistency check after the last peer is removed.
2570 assert(mapBlocksInFlight.empty());
2571 assert(m_num_preferred_download_peers == 0);
2572 assert(m_peers_downloading_from == 0);
2573 assert(m_outbound_peers_with_protect_from_disconnect == 0);
2574 assert(m_txrequest.Size() == 0);
2575 assert(m_mempool.withOrphanage([](const TxOrphanage &orphanage) {
2576 return orphanage.Size();
2577 }) == 0);
2578 }
2579 }
2580
2581 if (node.fSuccessfullyConnected && !node.IsBlockOnlyConn() &&
2582 !node.IsInboundConn()) {
2583 // Only change visible addrman state for full outbound peers. We don't
2584 // call Connected() for feeler connections since they don't have
2585 // fSuccessfullyConnected set.
2586 m_addrman.Connected(node.addr);
2587 }
2588 {
2589 LOCK(m_headers_presync_mutex);
2590 m_headers_presync_stats.erase(nodeid);
2591 }
2592
2593 WITH_LOCK(cs_proofrequest, m_proofrequest.DisconnectedPeer(nodeid));
2594
2595 LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
2596}
2597
2598PeerRef PeerManagerImpl::GetPeerRef(NodeId id) const {
2599 LOCK(m_peer_mutex);
2600 auto it = m_peer_map.find(id);
2601 return it != m_peer_map.end() ? it->second : nullptr;
2602}
2603
2604PeerRef PeerManagerImpl::RemovePeer(NodeId id) {
2605 PeerRef ret;
2606 LOCK(m_peer_mutex);
2607 auto it = m_peer_map.find(id);
2608 if (it != m_peer_map.end()) {
2609 ret = std::move(it->second);
2610 m_peer_map.erase(it);
2611 }
2612 return ret;
2613}
2614
2615bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid,
2616 CNodeStateStats &stats) const {
2617 {
2618 LOCK(cs_main);
2619 const CNodeState *state = State(nodeid);
2620 if (state == nullptr) {
2621 return false;
2622 }
2623 stats.nSyncHeight = state->pindexBestKnownBlock
2624 ? state->pindexBestKnownBlock->nHeight
2625 : -1;
2626 stats.nCommonHeight = state->pindexLastCommonBlock
2627 ? state->pindexLastCommonBlock->nHeight
2628 : -1;
2629 for (const QueuedBlock &queue : state->vBlocksInFlight) {
2630 if (queue.pindex) {
2631 stats.vHeightInFlight.push_back(queue.pindex->nHeight);
2632 }
2633 }
2634 }
2635
2636 PeerRef peer = GetPeerRef(nodeid);
2637 if (peer == nullptr) {
2638 return false;
2639 }
2640 stats.their_services = peer->m_their_services;
2641 stats.m_starting_height = peer->m_starting_height;
2642 // It is common for nodes with good ping times to suddenly become lagged,
2643 // due to a new block arriving or other large transfer.
2644 // Merely reporting pingtime might fool the caller into thinking the node
2645 // was still responsive, since pingtime does not update until the ping is
2646 // complete, which might take a while. So, if a ping is taking an unusually
2647 // long time in flight, the caller can immediately detect that this is
2648 // happening.
2649 auto ping_wait{0us};
2650 if ((0 != peer->m_ping_nonce_sent) &&
2651 (0 != peer->m_ping_start.load().count())) {
2652 ping_wait =
2653 GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
2654 }
2655
2656 if (auto tx_relay = peer->GetTxRelay()) {
2657 stats.m_relay_txs = WITH_LOCK(tx_relay->m_bloom_filter_mutex,
2658 return tx_relay->m_relay_txs);
2659 stats.m_fee_filter_received = tx_relay->m_fee_filter_received.load();
2660 } else {
2661 stats.m_relay_txs = false;
2663 }
2664
2665 stats.m_ping_wait = ping_wait;
2666 stats.m_addr_processed = peer->m_addr_processed.load();
2667 stats.m_addr_rate_limited = peer->m_addr_rate_limited.load();
2668 stats.m_addr_relay_enabled = peer->m_addr_relay_enabled.load();
2669 {
2670 LOCK(peer->m_headers_sync_mutex);
2671 if (peer->m_headers_sync) {
2672 stats.presync_height = peer->m_headers_sync->GetPresyncHeight();
2673 }
2674 }
2675
2676 return true;
2677}
2678
2679void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef &tx) {
2680 if (m_opts.max_extra_txs <= 0) {
2681 return;
2682 }
2683
2684 if (!vExtraTxnForCompact.size()) {
2685 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
2686 }
2687
2688 vExtraTxnForCompact[vExtraTxnForCompactIt] = tx;
2689 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
2690}
2691
2692void PeerManagerImpl::Misbehaving(Peer &peer, const std::string &message) {
2693 LOCK(peer.m_misbehavior_mutex);
2694
2695 const std::string message_prefixed =
2696 message.empty() ? "" : (": " + message);
2697 peer.m_should_discourage = true;
2698 LogPrint(BCLog::NET, "Misbehaving: peer=%d%s\n", peer.m_id,
2699 message_prefixed);
2700}
2701
2702void PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid,
2703 const BlockValidationState &state,
2704 bool via_compact_block,
2705 const std::string &message) {
2706 PeerRef peer{GetPeerRef(nodeid)};
2707 switch (state.GetResult()) {
2709 break;
2711 // We didn't try to process the block because the header chain may
2712 // have too little work.
2713 break;
2714 // The node is providing invalid data:
2717 if (!via_compact_block) {
2718 if (peer) {
2719 Misbehaving(*peer, message);
2720 }
2721 return;
2722 }
2723 break;
2725 LOCK(cs_main);
2726 CNodeState *node_state = State(nodeid);
2727 if (node_state == nullptr) {
2728 break;
2729 }
2730
2731 // Ban outbound (but not inbound) peers if on an invalid chain.
2732 // Exempt HB compact block peers. Manual connections are always
2733 // protected from discouragement.
2734 if (!via_compact_block && !node_state->m_is_inbound) {
2735 if (peer) {
2736 Misbehaving(*peer, message);
2737 }
2738 return;
2739 }
2740 break;
2741 }
2745 if (peer) {
2746 Misbehaving(*peer, message);
2747 }
2748 return;
2749 // Conflicting (but not necessarily invalid) data or different policy:
2751 if (peer) {
2752 Misbehaving(*peer, message);
2753 }
2754 return;
2756 break;
2757 }
2758 if (message != "") {
2759 LogPrint(BCLog::NET, "peer=%d: %s\n", nodeid, message);
2760 }
2761}
2762
2763void PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid,
2764 const TxValidationState &state,
2765 const std::string &message) {
2766 PeerRef peer{GetPeerRef(nodeid)};
2767 switch (state.GetResult()) {
2769 break;
2770 // The node is providing invalid data:
2772 if (peer) {
2773 Misbehaving(*peer, message);
2774 }
2775 return;
2776 // Conflicting (but not necessarily invalid) data or different policy:
2789 break;
2790 }
2791 if (message != "") {
2792 LogPrint(BCLog::NET, "peer=%d: %s\n", nodeid, message);
2793 }
2794}
2795
2796bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex *pindex) {
2798 if (m_chainman.ActiveChain().Contains(pindex)) {
2799 return true;
2800 }
2801 return pindex->IsValid(BlockValidity::SCRIPTS) &&
2802 (m_chainman.m_best_header != nullptr) &&
2803 (m_chainman.m_best_header->GetBlockTime() - pindex->GetBlockTime() <
2806 *m_chainman.m_best_header, *pindex, *m_chainman.m_best_header,
2807 m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT);
2808}
2809
2810std::optional<std::string>
2811PeerManagerImpl::FetchBlock(const Config &config, NodeId peer_id,
2812 const CBlockIndex &block_index) {
2813 if (m_chainman.m_blockman.LoadingBlocks()) {
2814 return "Loading blocks ...";
2815 }
2816
2817 LOCK(cs_main);
2818
2819 // Ensure this peer exists and hasn't been disconnected
2820 CNodeState *state = State(peer_id);
2821 if (state == nullptr) {
2822 return "Peer does not exist";
2823 }
2824
2825 // Forget about all prior requests
2826 RemoveBlockRequest(block_index.GetBlockHash(), std::nullopt);
2827
2828 // Mark block as in-flight
2829 if (!BlockRequested(config, peer_id, block_index)) {
2830 return "Already requested from this peer";
2831 }
2832
2833 // Construct message to request the block
2834 const BlockHash &hash{block_index.GetBlockHash()};
2835 const std::vector<CInv> invs{CInv(MSG_BLOCK, hash)};
2836
2837 // Send block request message to the peer
2838 if (!m_connman.ForNode(peer_id, [this, &invs](CNode *node) {
2839 this->MakeAndPushMessage(*node, NetMsgType::GETDATA, invs);
2840 return true;
2841 })) {
2842 return "Node not fully connected";
2843 }
2844
2845 LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n", hash.ToString(),
2846 peer_id);
2847 return std::nullopt;
2848}
2849
2850std::unique_ptr<PeerManager>
2851PeerManager::make(CConnman &connman, AddrMan &addrman, BanMan *banman,
2852 ChainstateManager &chainman, CTxMemPool &pool,
2853 avalanche::Processor *const avalanche, Options opts) {
2854 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman,
2855 pool, avalanche, opts);
2856}
2857
2858PeerManagerImpl::PeerManagerImpl(CConnman &connman, AddrMan &addrman,
2859 BanMan *banman, ChainstateManager &chainman,
2860 CTxMemPool &pool,
2862 Options opts)
2863 : m_rng{opts.deterministic_rng},
2864 m_fee_filter_rounder{CFeeRate{DEFAULT_MIN_RELAY_TX_FEE_PER_KB}, m_rng},
2865 m_chainparams(chainman.GetParams()), m_connman(connman),
2866 m_addrman(addrman), m_banman(banman), m_chainman(chainman),
2867 m_mempool(pool), m_avalanche(avalanche), m_opts{opts} {}
2868
2869void PeerManagerImpl::StartScheduledTasks(CScheduler &scheduler) {
2870 // Stale tip checking and peer eviction are on two different timers, but we
2871 // don't want them to get out of sync due to drift in the scheduler, so we
2872 // combine them in one function and schedule at the quicker (peer-eviction)
2873 // timer.
2874 static_assert(
2876 "peer eviction timer should be less than stale tip check timer");
2877 scheduler.scheduleEvery(
2878 [this]() {
2879 this->CheckForStaleTipAndEvictPeers();
2880 return true;
2881 },
2882 std::chrono::seconds{EXTRA_PEER_CHECK_INTERVAL});
2883
2884 // schedule next run for 10-15 minutes in the future
2885 const auto reattemptBroadcastInterval =
2886 10min + FastRandomContext().randrange<std::chrono::milliseconds>(5min);
2887 scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); },
2888 reattemptBroadcastInterval);
2889
2890 // Update the avalanche statistics on a schedule
2891 scheduler.scheduleEvery(
2892 [this]() {
2893 UpdateAvalancheStatistics();
2894 return true;
2895 },
2897
2898 // schedule next run for 2-5 minutes in the future
2899 const auto avalanchePeriodicNetworkingInterval =
2900 2min + FastRandomContext().randrange<std::chrono::milliseconds>(3min);
2901 scheduler.scheduleFromNow([&] { AvalanchePeriodicNetworking(scheduler); },
2902 avalanchePeriodicNetworkingInterval);
2903}
2904
2911void PeerManagerImpl::BlockConnected(
2912 ChainstateRole role, const std::shared_ptr<const CBlock> &pblock,
2913 const CBlockIndex *pindex) {
2914 // Update this for all chainstate roles so that we don't mistakenly see
2915 // peers helping us do background IBD as having a stale tip.
2916 m_last_tip_update = GetTime<std::chrono::seconds>();
2917
2918 // In case the dynamic timeout was doubled once or more, reduce it slowly
2919 // back to its default value
2920 auto stalling_timeout = m_block_stalling_timeout.load();
2921 Assume(stalling_timeout >= BLOCK_STALLING_TIMEOUT_DEFAULT);
2922 if (stalling_timeout != BLOCK_STALLING_TIMEOUT_DEFAULT) {
2923 const auto new_timeout =
2924 std::max(std::chrono::duration_cast<std::chrono::seconds>(
2925 stalling_timeout * 0.85),
2927 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout,
2928 new_timeout)) {
2929 LogPrint(BCLog::NET, "Decreased stalling timeout to %d seconds\n",
2930 count_seconds(new_timeout));
2931 }
2932 }
2933
2934 // The following tasks can be skipped since we don't maintain a mempool for
2935 // the ibd/background chainstate.
2936 if (role == ChainstateRole::BACKGROUND) {
2937 return;
2938 }
2939 m_mempool.withOrphanage([&pblock](TxOrphanage &orphanage) {
2940 orphanage.EraseForBlock(*pblock);
2941 });
2942 m_mempool.withConflicting([&pblock](TxConflicting &conflicting) {
2943 conflicting.EraseForBlock(*pblock);
2944 });
2945
2946 {
2947 LOCK(m_recent_confirmed_transactions_mutex);
2948 for (const CTransactionRef &ptx : pblock->vtx) {
2949 m_recent_confirmed_transactions.insert(ptx->GetId());
2950 }
2951 }
2952 {
2953 LOCK(cs_main);
2954 for (const auto &ptx : pblock->vtx) {
2955 m_txrequest.ForgetInvId(ptx->GetId());
2956 }
2957 }
2958}
2959
2960void PeerManagerImpl::BlockDisconnected(
2961 const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex) {
2962 // To avoid relay problems with transactions that were previously
2963 // confirmed, clear our filter of recently confirmed transactions whenever
2964 // there's a reorg.
2965 // This means that in a 1-block reorg (where 1 block is disconnected and
2966 // then another block reconnected), our filter will drop to having only one
2967 // block's worth of transactions in it, but that should be fine, since
2968 // presumably the most common case of relaying a confirmed transaction
2969 // should be just after a new block containing it is found.
2970 LOCK(m_recent_confirmed_transactions_mutex);
2971 m_recent_confirmed_transactions.reset();
2972}
2973
2978void PeerManagerImpl::NewPoWValidBlock(
2979 const CBlockIndex *pindex, const std::shared_ptr<const CBlock> &pblock) {
2980 std::shared_ptr<const CBlockHeaderAndShortTxIDs> pcmpctblock =
2981 std::make_shared<const CBlockHeaderAndShortTxIDs>(
2982 *pblock, FastRandomContext().rand64());
2983
2984 LOCK(cs_main);
2985
2986 if (pindex->nHeight <= m_highest_fast_announce) {
2987 return;
2988 }
2989 m_highest_fast_announce = pindex->nHeight;
2990
2991 BlockHash hashBlock(pblock->GetHash());
2992 const std::shared_future<CSerializedNetMsg> lazy_ser{
2993 std::async(std::launch::deferred, [&] {
2994 return NetMsg::Make(NetMsgType::CMPCTBLOCK, *pcmpctblock);
2995 })};
2996
2997 {
2998 auto most_recent_block_txs =
2999 std::make_unique<std::map<TxId, CTransactionRef>>();
3000 for (const auto &tx : pblock->vtx) {
3001 most_recent_block_txs->emplace(tx->GetId(), tx);
3002 }
3003
3004 LOCK(m_most_recent_block_mutex);
3005 m_most_recent_block_hash = hashBlock;
3006 m_most_recent_block = pblock;
3007 m_most_recent_compact_block = pcmpctblock;
3008 m_most_recent_block_txs = std::move(most_recent_block_txs);
3009 }
3010
3011 m_connman.ForEachNode(
3012 [this, pindex, &lazy_ser, &hashBlock](CNode *pnode)
3015
3017 pnode->fDisconnect) {
3018 return;
3019 }
3020 ProcessBlockAvailability(pnode->GetId());
3021 CNodeState &state = *State(pnode->GetId());
3022 // If the peer has, or we announced to them the previous block
3023 // already, but we don't think they have this one, go ahead and
3024 // announce it.
3025 if (state.m_requested_hb_cmpctblocks &&
3026 !PeerHasHeader(&state, pindex) &&
3027 PeerHasHeader(&state, pindex->pprev)) {
3029 "%s sending header-and-ids %s to peer=%d\n",
3030 "PeerManager::NewPoWValidBlock",
3031 hashBlock.ToString(), pnode->GetId());
3032
3033 const CSerializedNetMsg &ser_cmpctblock{lazy_ser.get()};
3034 PushMessage(*pnode, ser_cmpctblock.Copy());
3035 state.pindexBestHeaderSent = pindex;
3036 }
3037 });
3038}
3039
3044void PeerManagerImpl::UpdatedBlockTip(const CBlockIndex *pindexNew,
3045 const CBlockIndex *pindexFork,
3046 bool fInitialDownload) {
3047 SetBestHeight(pindexNew->nHeight);
3048 SetServiceFlagsIBDCache(!fInitialDownload);
3049
3050 // Don't relay inventory during initial block download.
3051 if (fInitialDownload) {
3052 return;
3053 }
3054
3055 // Find the hashes of all blocks that weren't previously in the best chain.
3056 std::vector<BlockHash> vHashes;
3057 const CBlockIndex *pindexToAnnounce = pindexNew;
3058 while (pindexToAnnounce != pindexFork) {
3059 vHashes.push_back(pindexToAnnounce->GetBlockHash());
3060 pindexToAnnounce = pindexToAnnounce->pprev;
3061 if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
3062 // Limit announcements in case of a huge reorganization. Rely on the
3063 // peer's synchronization mechanism in that case.
3064 break;
3065 }
3066 }
3067
3068 {
3069 LOCK(m_peer_mutex);
3070 for (auto &it : m_peer_map) {
3071 Peer &peer = *it.second;
3072 LOCK(peer.m_block_inv_mutex);
3073 for (const BlockHash &hash : reverse_iterate(vHashes)) {
3074 peer.m_blocks_for_headers_relay.push_back(hash);
3075 }
3076 }
3077 }
3078
3079 m_connman.WakeMessageHandler();
3080}
3081
3086void PeerManagerImpl::BlockChecked(const CBlock &block,
3087 const BlockValidationState &state) {
3088 LOCK(cs_main);
3089
3090 const BlockHash hash = block.GetHash();
3091 std::map<BlockHash, std::pair<NodeId, bool>>::iterator it =
3092 mapBlockSource.find(hash);
3093
3094 // If the block failed validation, we know where it came from and we're
3095 // still connected to that peer, maybe punish.
3096 if (state.IsInvalid() && it != mapBlockSource.end() &&
3097 State(it->second.first)) {
3098 MaybePunishNodeForBlock(/*nodeid=*/it->second.first, state,
3099 /*via_compact_block=*/!it->second.second);
3100 }
3101 // Check that:
3102 // 1. The block is valid
3103 // 2. We're not in initial block download
3104 // 3. This is currently the best block we're aware of. We haven't updated
3105 // the tip yet so we have no way to check this directly here. Instead we
3106 // just check that there are currently no other blocks in flight.
3107 else if (state.IsValid() && !m_chainman.IsInitialBlockDownload() &&
3108 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
3109 if (it != mapBlockSource.end()) {
3110 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
3111 }
3112 }
3113
3114 if (it != mapBlockSource.end()) {
3115 mapBlockSource.erase(it);
3116 }
3117}
3118
3120//
3121// Messages
3122//
3123
3124bool PeerManagerImpl::AlreadyHaveTx(const TxId &txid,
3125 bool include_reconsiderable) {
3126 if (m_chainman.ActiveChain().Tip()->GetBlockHash() !=
3127 hashRecentRejectsChainTip) {
3128 // If the chain tip has changed previously rejected transactions
3129 // might be now valid, e.g. due to a nLockTime'd tx becoming
3130 // valid, or a double-spend. Reset the rejects filter and give
3131 // those txs a second chance.
3132 hashRecentRejectsChainTip =
3133 m_chainman.ActiveChain().Tip()->GetBlockHash();
3134 m_recent_rejects.reset();
3135 m_recent_rejects_package_reconsiderable.reset();
3136 }
3137
3138 if (m_mempool.withOrphanage([&txid](const TxOrphanage &orphanage) {
3139 return orphanage.HaveTx(txid);
3140 })) {
3141 return true;
3142 }
3143
3144 if (m_mempool.withConflicting([&txid](const TxConflicting &conflicting) {
3145 return conflicting.HaveTx(txid);
3146 })) {
3147 return true;
3148 }
3149
3150 if (include_reconsiderable &&
3151 m_recent_rejects_package_reconsiderable.contains(txid)) {
3152 return true;
3153 }
3154
3155 {
3156 LOCK(m_recent_confirmed_transactions_mutex);
3157 if (m_recent_confirmed_transactions.contains(txid)) {
3158 return true;
3159 }
3160 }
3161
3162 return m_recent_rejects.contains(txid) || m_mempool.exists(txid);
3163}
3164
3165bool PeerManagerImpl::AlreadyHaveBlock(const BlockHash &block_hash) {
3166 return m_chainman.m_blockman.LookupBlockIndex(block_hash) != nullptr;
3167}
3168
3169bool PeerManagerImpl::AlreadyHaveProof(const avalanche::ProofId &proofid) {
3170 if (!Assume(m_avalanche)) {
3171 return false;
3172 }
3173
3174 auto localProof = m_avalanche->getLocalProof();
3175 if (localProof && localProof->getId() == proofid) {
3176 return true;
3177 }
3178
3179 return m_avalanche->withPeerManager([&proofid](avalanche::PeerManager &pm) {
3180 return pm.exists(proofid) || pm.isInvalid(proofid);
3181 });
3182}
3183
3184void PeerManagerImpl::SendPings() {
3185 LOCK(m_peer_mutex);
3186 for (auto &it : m_peer_map) {
3187 it.second->m_ping_queued = true;
3188 }
3189}
3190
3191void PeerManagerImpl::RelayTransaction(const TxId &txid) {
3192 LOCK(m_peer_mutex);
3193 for (auto &it : m_peer_map) {
3194 Peer &peer = *it.second;
3195 auto tx_relay = peer.GetTxRelay();
3196 if (!tx_relay) {
3197 continue;
3198 }
3199 LOCK(tx_relay->m_tx_inventory_mutex);
3200 // Only queue transactions for announcement once the version handshake
3201 // is completed. The time of arrival for these transactions is
3202 // otherwise at risk of leaking to a spy, if the spy is able to
3203 // distinguish transactions received during the handshake from the rest
3204 // in the announcement.
3205 if (tx_relay->m_next_inv_send_time == 0s) {
3206 continue;
3207 }
3208
3209 if (!tx_relay->m_tx_inventory_known_filter.contains(txid) ||
3210 tx_relay->m_avalanche_stalled_txids.count(txid) > 0) {
3211 tx_relay->m_tx_inventory_to_send.insert(txid);
3212 }
3213 }
3214}
3215
3216void PeerManagerImpl::RelayProof(const avalanche::ProofId &proofid) {
3217 LOCK(m_peer_mutex);
3218 for (auto &it : m_peer_map) {
3219 Peer &peer = *it.second;
3220
3221 if (!peer.m_proof_relay) {
3222 continue;
3223 }
3224 LOCK(peer.m_proof_relay->m_proof_inventory_mutex);
3225 if (!peer.m_proof_relay->m_proof_inventory_known_filter.contains(
3226 proofid)) {
3227 peer.m_proof_relay->m_proof_inventory_to_send.insert(proofid);
3228 }
3229 }
3230}
3231
3232void PeerManagerImpl::RelayAddress(NodeId originator, const CAddress &addr,
3233 bool fReachable) {
3234 // We choose the same nodes within a given 24h window (if the list of
3235 // connected nodes does not change) and we don't relay to nodes that already
3236 // know an address. So within 24h we will likely relay a given address once.
3237 // This is to prevent a peer from unjustly giving their address better
3238 // propagation by sending it to us repeatedly.
3239
3240 if (!fReachable && !addr.IsRelayable()) {
3241 return;
3242 }
3243
3244 // Relay to a limited number of other nodes
3245 // Use deterministic randomness to send to the same nodes for 24 hours
3246 // at a time so the m_addr_knowns of the chosen nodes prevent repeats
3247 const uint64_t hash_addr{CServiceHash(0, 0)(addr)};
3248 const auto current_time{GetTime<std::chrono::seconds>()};
3249 // Adding address hash makes exact rotation time different per address,
3250 // while preserving periodicity.
3251 const uint64_t time_addr{
3252 (static_cast<uint64_t>(count_seconds(current_time)) + hash_addr) /
3254
3255 const CSipHasher hasher{
3257 .Write(hash_addr)
3258 .Write(time_addr)};
3259
3260 // Relay reachable addresses to 2 peers. Unreachable addresses are relayed
3261 // randomly to 1 or 2 peers.
3262 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
3263 std::array<std::pair<uint64_t, Peer *>, 2> best{
3264 {{0, nullptr}, {0, nullptr}}};
3265 assert(nRelayNodes <= best.size());
3266
3267 LOCK(m_peer_mutex);
3268
3269 for (auto &[id, peer] : m_peer_map) {
3270 if (peer->m_addr_relay_enabled && id != originator &&
3271 IsAddrCompatible(*peer, addr)) {
3272 uint64_t hashKey = CSipHasher(hasher).Write(id).Finalize();
3273 for (unsigned int i = 0; i < nRelayNodes; i++) {
3274 if (hashKey > best[i].first) {
3275 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1,
3276 best.begin() + i + 1);
3277 best[i] = std::make_pair(hashKey, peer.get());
3278 break;
3279 }
3280 }
3281 }
3282 };
3283
3284 for (unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
3285 PushAddress(*best[i].second, addr);
3286 }
3287}
3288
3289void PeerManagerImpl::ProcessGetBlockData(const Config &config, CNode &pfrom,
3290 Peer &peer, const CInv &inv) {
3291 const BlockHash hash(inv.hash);
3292
3293 std::shared_ptr<const CBlock> a_recent_block;
3294 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
3295 {
3296 LOCK(m_most_recent_block_mutex);
3297 a_recent_block = m_most_recent_block;
3298 a_recent_compact_block = m_most_recent_compact_block;
3299 }
3300
3301 bool need_activate_chain = false;
3302 {
3303 LOCK(cs_main);
3304 const CBlockIndex *pindex =
3305 m_chainman.m_blockman.LookupBlockIndex(hash);
3306 if (pindex) {
3307 if (pindex->HaveNumChainTxs() &&
3308 !pindex->IsValid(BlockValidity::SCRIPTS) &&
3309 pindex->IsValid(BlockValidity::TREE)) {
3310 // If we have the block and all of its parents, but have not yet
3311 // validated it, we might be in the middle of connecting it (ie
3312 // in the unlock of cs_main before ActivateBestChain but after
3313 // AcceptBlock). In this case, we need to run ActivateBestChain
3314 // prior to checking the relay conditions below.
3315 need_activate_chain = true;
3316 }
3317 }
3318 } // release cs_main before calling ActivateBestChain
3319 if (need_activate_chain) {
3321 if (!m_chainman.ActiveChainstate().ActivateBestChain(
3322 state, a_recent_block, m_avalanche)) {
3323 LogPrint(BCLog::NET, "failed to activate chain (%s)\n",
3324 state.ToString());
3325 }
3326 }
3327
3328 const CBlockIndex *pindex{nullptr};
3329 const CBlockIndex *tip{nullptr};
3330 bool can_direct_fetch{false};
3331 FlatFilePos block_pos{};
3332 {
3333 LOCK(cs_main);
3334 pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
3335 if (!pindex) {
3336 return;
3337 }
3338 if (!BlockRequestAllowed(pindex)) {
3340 "%s: ignoring request from peer=%i for old "
3341 "block that isn't in the main chain\n",
3342 __func__, pfrom.GetId());
3343 return;
3344 }
3345 // Disconnect node in case we have reached the outbound limit for
3346 // serving historical blocks.
3347 if (m_connman.OutboundTargetReached(true) &&
3348 (((m_chainman.m_best_header != nullptr) &&
3349 (m_chainman.m_best_header->GetBlockTime() -
3350 pindex->GetBlockTime() >
3352 inv.IsMsgFilteredBlk()) &&
3353 // nodes with the download permission may exceed target
3355 LogPrint(
3356 BCLog::NET,
3357 "historical block serving limit reached, disconnect peer=%d\n",
3358 pfrom.GetId());
3359 pfrom.fDisconnect = true;
3360 return;
3361 }
3362 tip = m_chainman.ActiveChain().Tip();
3363 // Avoid leaking prune-height by never sending blocks below the
3364 // NODE_NETWORK_LIMITED threshold.
3365 // Add two blocks buffer extension for possible races
3367 ((((peer.m_our_services & NODE_NETWORK_LIMITED) ==
3369 ((peer.m_our_services & NODE_NETWORK) != NODE_NETWORK) &&
3370 (tip->nHeight - pindex->nHeight >
3371 (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2)))) {
3373 "Ignore block request below NODE_NETWORK_LIMITED "
3374 "threshold, disconnect peer=%d\n",
3375 pfrom.GetId());
3376
3377 // disconnect node and prevent it from stalling (would otherwise
3378 // wait for the missing block)
3379 pfrom.fDisconnect = true;
3380 return;
3381 }
3382 // Pruned nodes may have deleted the block, so check whether it's
3383 // available before trying to send.
3384 if (!pindex->nStatus.hasData()) {
3385 return;
3386 }
3387 can_direct_fetch = CanDirectFetch();
3388 block_pos = pindex->GetBlockPos();
3389 }
3390
3391 std::shared_ptr<const CBlock> pblock;
3392 auto handle_block_read_error = [&]() {
3393 if (WITH_LOCK(m_chainman.GetMutex(),
3394 return m_chainman.m_blockman.IsBlockPruned(*pindex))) {
3396 "Block was pruned before it could be read, disconnect "
3397 "peer=%s\n",
3398 pfrom.GetId());
3399 } else {
3400 LogError("Cannot load block from disk, disconnect peer=%d\n",
3401 pfrom.GetId());
3402 }
3403 pfrom.fDisconnect = true;
3404 };
3405
3406 if (a_recent_block && a_recent_block->GetHash() == pindex->GetBlockHash()) {
3407 pblock = a_recent_block;
3408 } else if (!inv.IsMsgCmpctBlk()) {
3409 // Fast-path: in this case it is possible to serve the block directly
3410 // from disk, as the network format matches the format on disk
3411 std::vector<uint8_t> block_data;
3412 if (!m_chainman.m_blockman.ReadRawBlock(block_data, block_pos)) {
3413 handle_block_read_error();
3414 return;
3415 }
3416 MakeAndPushMessage(pfrom, NetMsgType::BLOCK, Span{block_data});
3417 // Don't set pblock as we've sent the block
3418 } else {
3419 // Send block from disk
3420 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
3421 if (!m_chainman.m_blockman.ReadBlock(*pblockRead, block_pos)) {
3422 handle_block_read_error();
3423 return;
3424 }
3425 pblock = pblockRead;
3426 }
3427 if (pblock) {
3428 if (inv.IsMsgBlk()) {
3429 MakeAndPushMessage(pfrom, NetMsgType::BLOCK, *pblock);
3430 } else if (inv.IsMsgFilteredBlk()) {
3431 bool sendMerkleBlock = false;
3432 CMerkleBlock merkleBlock;
3433 if (auto tx_relay = peer.GetTxRelay()) {
3434 LOCK(tx_relay->m_bloom_filter_mutex);
3435 if (tx_relay->m_bloom_filter) {
3436 sendMerkleBlock = true;
3437 merkleBlock =
3438 CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
3439 }
3440 }
3441 if (sendMerkleBlock) {
3442 MakeAndPushMessage(pfrom, NetMsgType::MERKLEBLOCK, merkleBlock);
3443 // CMerkleBlock just contains hashes, so also push any
3444 // transactions in the block the client did not see. This avoids
3445 // hurting performance by pointlessly requiring a round-trip.
3446 // Note that there is currently no way for a node to request any
3447 // single transactions we didn't send here - they must either
3448 // disconnect and retry or request the full block. Thus, the
3449 // protocol spec specified allows for us to provide duplicate
3450 // txn here, however we MUST always provide at least what the
3451 // remote peer needs.
3452 typedef std::pair<size_t, uint256> PairType;
3453 for (PairType &pair : merkleBlock.vMatchedTxn) {
3454 MakeAndPushMessage(pfrom, NetMsgType::TX,
3455 *pblock->vtx[pair.first]);
3456 }
3457 }
3458 // else
3459 // no response
3460 } else if (inv.IsMsgCmpctBlk()) {
3461 // If a peer is asking for old blocks, we're almost guaranteed they
3462 // won't have a useful mempool to match against a compact block, and
3463 // we don't feel like constructing the object for them, so instead
3464 // we respond with the full, non-compact block.
3465 if (can_direct_fetch &&
3466 pindex->nHeight >= tip->nHeight - MAX_CMPCTBLOCK_DEPTH) {
3467 if (a_recent_compact_block &&
3468 a_recent_compact_block->header.GetHash() ==
3469 pindex->GetBlockHash()) {
3470 MakeAndPushMessage(pfrom, NetMsgType::CMPCTBLOCK,
3471 *a_recent_compact_block);
3472 } else {
3473 CBlockHeaderAndShortTxIDs cmpctblock(
3474 *pblock, FastRandomContext().rand64());
3475 MakeAndPushMessage(pfrom, NetMsgType::CMPCTBLOCK,
3476 cmpctblock);
3477 }
3478 } else {
3479 MakeAndPushMessage(pfrom, NetMsgType::BLOCK, *pblock);
3480 }
3481 }
3482 }
3483
3484 {
3485 LOCK(peer.m_block_inv_mutex);
3486 // Trigger the peer node to send a getblocks request for the next
3487 // batch of inventory.
3488 if (hash == peer.m_continuation_block) {
3489 // Send immediately. This must send even if redundant, and
3490 // we want it right after the last block so they don't wait for
3491 // other stuff first.
3492 std::vector<CInv> vInv;
3493 vInv.push_back(CInv(MSG_BLOCK, tip->GetBlockHash()));
3494 MakeAndPushMessage(pfrom, NetMsgType::INV, vInv);
3495 peer.m_continuation_block = BlockHash();
3496 }
3497 }
3498}
3499
3501PeerManagerImpl::FindTxForGetData(const Peer &peer, const TxId &txid,
3502 const std::chrono::seconds mempool_req,
3503 const std::chrono::seconds now) {
3504 auto txinfo = m_mempool.info(txid);
3505 if (txinfo.tx) {
3506 // If a TX could have been INVed in reply to a MEMPOOL request,
3507 // or is older than UNCONDITIONAL_RELAY_DELAY, permit the request
3508 // unconditionally.
3509 if ((mempool_req.count() && txinfo.m_time <= mempool_req) ||
3510 txinfo.m_time <= now - UNCONDITIONAL_RELAY_DELAY) {
3511 return std::move(txinfo.tx);
3512 }
3513 }
3514
3515 {
3516 LOCK(cs_main);
3517
3518 // Otherwise, the transaction might have been announced recently.
3519 bool recent =
3520 Assume(peer.GetTxRelay())->m_recently_announced_invs.contains(txid);
3521 if (recent && txinfo.tx) {
3522 return std::move(txinfo.tx);
3523 }
3524
3525 // Or it might be from the most recent block
3526 {
3527 LOCK(m_most_recent_block_mutex);
3528 if (m_most_recent_block_txs != nullptr) {
3529 auto it = m_most_recent_block_txs->find(txid);
3530 if (it != m_most_recent_block_txs->end()) {
3531 return it->second;
3532 }
3533 }
3534 }
3535 }
3536
3537 return {};
3538}
3539
3543PeerManagerImpl::FindProofForGetData(const Peer &peer,
3544 const avalanche::ProofId &proofid,
3545 const std::chrono::seconds now) {
3546 avalanche::ProofRef proof;
3547
3548 bool send_unconditionally =
3549 m_avalanche->withPeerManager([&](const avalanche::PeerManager &pm) {
3550 return pm.forPeer(proofid, [&](const avalanche::Peer &peer) {
3551 proof = peer.proof;
3552
3553 // If we know that proof for long enough, allow for requesting
3554 // it.
3555 return peer.registration_time <=
3557 });
3558 });
3559
3560 if (!proof) {
3561 // Always send our local proof if it gets requested, assuming it's
3562 // valid. This will make it easier to bind with peers upon startup where
3563 // the status of our proof is unknown pending for a block. Note that it
3564 // still needs to have been announced first (presumably via an avahello
3565 // message).
3566 proof = m_avalanche->getLocalProof();
3567 }
3568
3569 // We don't have this proof
3570 if (!proof) {
3571 return avalanche::ProofRef();
3572 }
3573
3574 if (send_unconditionally) {
3575 return proof;
3576 }
3577
3578 // Otherwise, the proofs must have been announced recently.
3579 if (peer.m_proof_relay->m_recently_announced_proofs.contains(proofid)) {
3580 return proof;
3581 }
3582
3583 return avalanche::ProofRef();
3584}
3585
3586void PeerManagerImpl::ProcessGetData(
3587 const Config &config, CNode &pfrom, Peer &peer,
3588 const std::atomic<bool> &interruptMsgProc) {
3590
3591 auto tx_relay = peer.GetTxRelay();
3592
3593 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
3594 std::vector<CInv> vNotFound;
3595
3596 const auto now{GetTime<std::chrono::seconds>()};
3597 // Get last mempool request time
3598 const auto mempool_req = tx_relay != nullptr
3599 ? tx_relay->m_last_mempool_req.load()
3600 : std::chrono::seconds::min();
3601
3602 // Process as many TX or AVA_PROOF items from the front of the getdata
3603 // queue as possible, since they're common and it's efficient to batch
3604 // process them.
3605 while (it != peer.m_getdata_requests.end() &&
3606 (it->IsMsgProof() || it->IsMsgTx())) {
3607 if (interruptMsgProc) {
3608 return;
3609 }
3610 // The send buffer provides backpressure. If there's no space in
3611 // the buffer, pause processing until the next call.
3612 if (pfrom.fPauseSend) {
3613 break;
3614 }
3615
3616 const CInv &inv = *it++;
3617
3618 if (inv.IsMsgProof()) {
3619 if (!m_avalanche) {
3620 vNotFound.push_back(inv);
3621 continue;
3622 }
3623 const avalanche::ProofId proofid(inv.hash);
3624 auto proof = FindProofForGetData(peer, proofid, now);
3625 if (proof) {
3626 MakeAndPushMessage(pfrom, NetMsgType::AVAPROOF, *proof);
3627 m_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
3628 pm.removeUnbroadcastProof(proofid);
3629 });
3630 } else {
3631 vNotFound.push_back(inv);
3632 }
3633
3634 continue;
3635 }
3636
3637 if (inv.IsMsgTx()) {
3638 if (tx_relay == nullptr) {
3639 // Ignore GETDATA requests for transactions from
3640 // block-relay-only peers and peers that asked us not to
3641 // announce transactions.
3642 continue;
3643 }
3644
3645 const TxId txid(inv.hash);
3646 CTransactionRef tx = FindTxForGetData(peer, txid, mempool_req, now);
3647 if (tx) {
3648 MakeAndPushMessage(pfrom, NetMsgType::TX, *tx);
3649 m_mempool.RemoveUnbroadcastTx(txid);
3650 // As we're going to send tx, make sure its unconfirmed parents
3651 // are made requestable.
3652 std::vector<TxId> parent_ids_to_add;
3653 {
3654 LOCK(m_mempool.cs);
3655 auto txiter = m_mempool.GetIter(tx->GetId());
3656 if (txiter) {
3657 auto &pentry = *txiter;
3658 const CTxMemPoolEntry::Parents &parents =
3659 (*pentry)->GetMemPoolParentsConst();
3660 parent_ids_to_add.reserve(parents.size());
3661 for (const auto &parent : parents) {
3662 if (parent.get()->GetTime() >
3664 parent_ids_to_add.push_back(
3665 parent.get()->GetTx().GetId());
3666 }
3667 }
3668 }
3669 }
3670 for (const TxId &parent_txid : parent_ids_to_add) {
3671 // Relaying a transaction with a recent but unconfirmed
3672 // parent.
3673 if (WITH_LOCK(tx_relay->m_tx_inventory_mutex,
3674 return !tx_relay->m_tx_inventory_known_filter
3675 .contains(parent_txid))) {
3676 tx_relay->m_recently_announced_invs.insert(parent_txid);
3677 }
3678 }
3679 } else {
3680 vNotFound.push_back(inv);
3681 }
3682
3683 continue;
3684 }
3685
3686 // It's neither a proof nor a transaction
3687 break;
3688 }
3689
3690 // Only process one BLOCK item per call, since they're uncommon and can be
3691 // expensive to process.
3692 if (it != peer.m_getdata_requests.end() && !pfrom.fPauseSend) {
3693 const CInv &inv = *it++;
3694 if (inv.IsGenBlkMsg()) {
3695 ProcessGetBlockData(config, pfrom, peer, inv);
3696 }
3697 // else: If the first item on the queue is an unknown type, we erase it
3698 // and continue processing the queue on the next call.
3699 }
3700
3701 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
3702
3703 if (!vNotFound.empty()) {
3704 // Let the peer know that we didn't find what it asked for, so it
3705 // doesn't have to wait around forever. SPV clients care about this
3706 // message: it's needed when they are recursively walking the
3707 // dependencies of relevant unconfirmed transactions. SPV clients want
3708 // to do that because they want to know about (and store and rebroadcast
3709 // and risk analyze) the dependencies of transactions relevant to them,
3710 // without having to download the entire memory pool. Also, other nodes
3711 // can use these messages to automatically request a transaction from
3712 // some other peer that annnounced it, and stop waiting for us to
3713 // respond. In normal operation, we often send NOTFOUND messages for
3714 // parents of transactions that we relay; if a peer is missing a parent,
3715 // they may assume we have them and request the parents from us.
3716 MakeAndPushMessage(pfrom, NetMsgType::NOTFOUND, vNotFound);
3717 }
3718}
3719
3720void PeerManagerImpl::SendBlockTransactions(
3721 CNode &pfrom, Peer &peer, const CBlock &block,
3722 const BlockTransactionsRequest &req) {
3723 BlockTransactions resp(req);
3724 for (size_t i = 0; i < req.indices.size(); i++) {
3725 if (req.indices[i] >= block.vtx.size()) {
3726 Misbehaving(peer, "getblocktxn with out-of-bounds tx indices");
3727 return;
3728 }
3729 resp.txn[i] = block.vtx[req.indices[i]];
3730 }
3731 LOCK(cs_main);
3732 MakeAndPushMessage(pfrom, NetMsgType::BLOCKTXN, resp);
3733}
3734
3735bool PeerManagerImpl::CheckHeadersPoW(const std::vector<CBlockHeader> &headers,
3736 const Consensus::Params &consensusParams,
3737 Peer &peer) {
3738 // Do these headers have proof-of-work matching what's claimed?
3739 if (!HasValidProofOfWork(headers, consensusParams)) {
3740 Misbehaving(peer, "header with invalid proof of work");
3741 return false;
3742 }
3743
3744 // Are these headers connected to each other?
3745 if (!CheckHeadersAreContinuous(headers)) {
3746 Misbehaving(peer, "non-continuous headers sequence");
3747 return false;
3748 }
3749 return true;
3750}
3751
3752arith_uint256 PeerManagerImpl::GetAntiDoSWorkThreshold() {
3753 arith_uint256 near_chaintip_work = 0;
3754 LOCK(cs_main);
3755 if (m_chainman.ActiveChain().Tip() != nullptr) {
3756 const CBlockIndex *tip = m_chainman.ActiveChain().Tip();
3757 // Use a 144 block buffer, so that we'll accept headers that fork from
3758 // near our tip.
3759 near_chaintip_work =
3760 tip->nChainWork -
3761 std::min<arith_uint256>(144 * GetBlockProof(*tip), tip->nChainWork);
3762 }
3763 return std::max(near_chaintip_work, m_chainman.MinimumChainWork());
3764}
3765
3772void PeerManagerImpl::HandleUnconnectingHeaders(
3773 CNode &pfrom, Peer &peer, const std::vector<CBlockHeader> &headers) {
3774 // Try to fill in the missing headers.
3775 const CBlockIndex *best_header{
3776 WITH_LOCK(cs_main, return m_chainman.m_best_header)};
3777 if (MaybeSendGetHeaders(pfrom, GetLocator(best_header), peer)) {
3778 LogPrint(
3779 BCLog::NET,
3780 "received header %s: missing prev block %s, sending getheaders "
3781 "(%d) to end (peer=%d)\n",
3782 headers[0].GetHash().ToString(),
3783 headers[0].hashPrevBlock.ToString(), best_header->nHeight,
3784 pfrom.GetId());
3785 }
3786
3787 // Set hashLastUnknownBlock for this peer, so that if we
3788 // eventually get the headers - even from a different peer -
3789 // we can use this peer to download.
3791 UpdateBlockAvailability(pfrom.GetId(), headers.back().GetHash()));
3792}
3793
3794bool PeerManagerImpl::CheckHeadersAreContinuous(
3795 const std::vector<CBlockHeader> &headers) const {
3796 BlockHash hashLastBlock;
3797 for (const CBlockHeader &header : headers) {
3798 if (!hashLastBlock.IsNull() && header.hashPrevBlock != hashLastBlock) {
3799 return false;
3800 }
3801 hashLastBlock = header.GetHash();
3802 }
3803 return true;
3804}
3805
3806bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(
3807 Peer &peer, CNode &pfrom, std::vector<CBlockHeader> &headers) {
3808 if (peer.m_headers_sync) {
3809 auto result = peer.m_headers_sync->ProcessNextHeaders(
3810 headers, headers.size() == MAX_HEADERS_RESULTS);
3811 // If it is a valid continuation, we should treat the existing
3812 // getheaders request as responded to.
3813 if (result.success) {
3814 peer.m_last_getheaders_timestamp = {};
3815 }
3816 if (result.request_more) {
3817 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
3818 // If we were instructed to ask for a locator, it should not be
3819 // empty.
3820 Assume(!locator.vHave.empty());
3821 // We can only be instructed to request more if processing was
3822 // successful.
3823 Assume(result.success);
3824 if (!locator.vHave.empty()) {
3825 // It should be impossible for the getheaders request to fail,
3826 // because we just cleared the last getheaders timestamp.
3827 bool sent_getheaders =
3828 MaybeSendGetHeaders(pfrom, locator, peer);
3829 Assume(sent_getheaders);
3830 LogPrint(BCLog::NET, "more getheaders (from %s) to peer=%d\n",
3831 locator.vHave.front().ToString(), pfrom.GetId());
3832 }
3833 }
3834
3835 if (peer.m_headers_sync->GetState() == HeadersSyncState::State::FINAL) {
3836 peer.m_headers_sync.reset(nullptr);
3837
3838 // Delete this peer's entry in m_headers_presync_stats.
3839 // If this is m_headers_presync_bestpeer, it will be replaced later
3840 // by the next peer that triggers the else{} branch below.
3841 LOCK(m_headers_presync_mutex);
3842 m_headers_presync_stats.erase(pfrom.GetId());
3843 } else {
3844 // Build statistics for this peer's sync.
3845 HeadersPresyncStats stats;
3846 stats.first = peer.m_headers_sync->GetPresyncWork();
3847 if (peer.m_headers_sync->GetState() ==
3849 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
3850 peer.m_headers_sync->GetPresyncTime()};
3851 }
3852
3853 // Update statistics in stats.
3854 LOCK(m_headers_presync_mutex);
3855 m_headers_presync_stats[pfrom.GetId()] = stats;
3856 auto best_it =
3857 m_headers_presync_stats.find(m_headers_presync_bestpeer);
3858 bool best_updated = false;
3859 if (best_it == m_headers_presync_stats.end()) {
3860 // If the cached best peer is outdated, iterate over all
3861 // remaining ones (including newly updated one) to find the best
3862 // one.
3863 NodeId peer_best{-1};
3864 const HeadersPresyncStats *stat_best{nullptr};
3865 for (const auto &[_peer, _stat] : m_headers_presync_stats) {
3866 if (!stat_best || _stat > *stat_best) {
3867 peer_best = _peer;
3868 stat_best = &_stat;
3869 }
3870 }
3871 m_headers_presync_bestpeer = peer_best;
3872 best_updated = (peer_best == pfrom.GetId());
3873 } else if (best_it->first == pfrom.GetId() ||
3874 stats > best_it->second) {
3875 // pfrom was and remains the best peer, or pfrom just became
3876 // best.
3877 m_headers_presync_bestpeer = pfrom.GetId();
3878 best_updated = true;
3879 }
3880 if (best_updated && stats.second.has_value()) {
3881 // If the best peer updated, and it is in its first phase,
3882 // signal.
3883 m_headers_presync_should_signal = true;
3884 }
3885 }
3886
3887 if (result.success) {
3888 // We only overwrite the headers passed in if processing was
3889 // successful.
3890 headers.swap(result.pow_validated_headers);
3891 }
3892
3893 return result.success;
3894 }
3895 // Either we didn't have a sync in progress, or something went wrong
3896 // processing these headers, or we are returning headers to the caller to
3897 // process.
3898 return false;
3899}
3900
3901bool PeerManagerImpl::TryLowWorkHeadersSync(
3902 Peer &peer, CNode &pfrom, const CBlockIndex *chain_start_header,
3903 std::vector<CBlockHeader> &headers) {
3904 // Calculate the total work on this chain.
3905 arith_uint256 total_work =
3906 chain_start_header->nChainWork + CalculateHeadersWork(headers);
3907
3908 // Our dynamic anti-DoS threshold (minimum work required on a headers chain
3909 // before we'll store it)
3910 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
3911
3912 // Avoid DoS via low-difficulty-headers by only processing if the headers
3913 // are part of a chain with sufficient work.
3914 if (total_work < minimum_chain_work) {
3915 // Only try to sync with this peer if their headers message was full;
3916 // otherwise they don't have more headers after this so no point in
3917 // trying to sync their too-little-work chain.
3918 if (headers.size() == MAX_HEADERS_RESULTS) {
3919 // Note: we could advance to the last header in this set that is
3920 // known to us, rather than starting at the first header (which we
3921 // may already have); however this is unlikely to matter much since
3922 // ProcessHeadersMessage() already handles the case where all
3923 // headers in a received message are already known and are
3924 // ancestors of m_best_header or chainActive.Tip(), by skipping
3925 // this logic in that case. So even if the first header in this set
3926 // of headers is known, some header in this set must be new, so
3927 // advancing to the first unknown header would be a small effect.
3928 LOCK(peer.m_headers_sync_mutex);
3929 peer.m_headers_sync.reset(
3930 new HeadersSyncState(peer.m_id, m_chainparams.GetConsensus(),
3931 chain_start_header, minimum_chain_work));
3932
3933 // Now a HeadersSyncState object for tracking this synchronization
3934 // is created, process the headers using it as normal. Failures are
3935 // handled inside of IsContinuationOfLowWorkHeadersSync.
3936 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3937 } else {
3939 "Ignoring low-work chain (height=%u) from peer=%d\n",
3940 chain_start_header->nHeight + headers.size(),
3941 pfrom.GetId());
3942 }
3943 // The peer has not yet given us a chain that meets our work threshold,
3944 // so we want to prevent further processing of the headers in any case.
3945 headers = {};
3946 return true;
3947 }
3948
3949 return false;
3950}
3951
3952bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(const CBlockIndex *header) {
3953 return header != nullptr &&
3954 ((m_chainman.m_best_header != nullptr &&
3955 header ==
3956 m_chainman.m_best_header->GetAncestor(header->nHeight)) ||
3957 m_chainman.ActiveChain().Contains(header));
3958}
3959
3960bool PeerManagerImpl::MaybeSendGetHeaders(CNode &pfrom,
3961 const CBlockLocator &locator,
3962 Peer &peer) {
3963 const auto current_time = NodeClock::now();
3964
3965 // Only allow a new getheaders message to go out if we don't have a recent
3966 // one already in-flight
3967 if (current_time - peer.m_last_getheaders_timestamp >
3969 MakeAndPushMessage(pfrom, NetMsgType::GETHEADERS, locator, uint256());
3970 peer.m_last_getheaders_timestamp = current_time;
3971 return true;
3972 }
3973 return false;
3974}
3975
3982void PeerManagerImpl::HeadersDirectFetchBlocks(const Config &config,
3983 CNode &pfrom,
3984 const CBlockIndex &last_header) {
3985 LOCK(cs_main);
3986 CNodeState *nodestate = State(pfrom.GetId());
3987
3988 if (CanDirectFetch() && last_header.IsValid(BlockValidity::TREE) &&
3989 m_chainman.ActiveChain().Tip()->nChainWork <= last_header.nChainWork) {
3990 std::vector<const CBlockIndex *> vToFetch;
3991 const CBlockIndex *pindexWalk{&last_header};
3992 // Calculate all the blocks we'd need to switch to last_header, up to
3993 // a limit.
3994 while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) &&
3995 vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
3996 if (!pindexWalk->nStatus.hasData() &&
3997 !IsBlockRequested(pindexWalk->GetBlockHash())) {
3998 // We don't have this block, and it's not yet in flight.
3999 vToFetch.push_back(pindexWalk);
4000 }
4001 pindexWalk = pindexWalk->pprev;
4002 }
4003 // If pindexWalk still isn't on our main chain, we're looking at a
4004 // very large reorg at a time we think we're close to caught up to
4005 // the main chain -- this shouldn't really happen. Bail out on the
4006 // direct fetch and rely on parallel download instead.
4007 if (!m_chainman.ActiveChain().Contains(pindexWalk)) {
4008 LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
4009 last_header.GetBlockHash().ToString(),
4010 last_header.nHeight);
4011 } else {
4012 std::vector<CInv> vGetData;
4013 // Download as much as possible, from earliest to latest.
4014 for (const CBlockIndex *pindex : reverse_iterate(vToFetch)) {
4015 if (nodestate->vBlocksInFlight.size() >=
4017 // Can't download any more from this peer
4018 break;
4019 }
4020 vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
4021 BlockRequested(config, pfrom.GetId(), *pindex);
4022 LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
4023 pindex->GetBlockHash().ToString(), pfrom.GetId());
4024 }
4025 if (vGetData.size() > 1) {
4027 "Downloading blocks toward %s (%d) via headers "
4028 "direct fetch\n",
4029 last_header.GetBlockHash().ToString(),
4030 last_header.nHeight);
4031 }
4032 if (vGetData.size() > 0) {
4033 if (!m_opts.ignore_incoming_txs &&
4034 nodestate->m_provides_cmpctblocks && vGetData.size() == 1 &&
4035 mapBlocksInFlight.size() == 1 &&
4036 last_header.pprev->IsValid(BlockValidity::CHAIN)) {
4037 // In any case, we want to download using a compact
4038 // block, not a regular one.
4039 vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash);
4040 }
4041 MakeAndPushMessage(pfrom, NetMsgType::GETDATA, vGetData);
4042 }
4043 }
4044 }
4045}
4046
4052void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
4053 CNode &pfrom, Peer &peer, const CBlockIndex &last_header,
4054 bool received_new_header, bool may_have_more_headers) {
4055 LOCK(cs_main);
4056
4057 CNodeState *nodestate = State(pfrom.GetId());
4058
4059 UpdateBlockAvailability(pfrom.GetId(), last_header.GetBlockHash());
4060
4061 // From here, pindexBestKnownBlock should be guaranteed to be non-null,
4062 // because it is set in UpdateBlockAvailability. Some nullptr checks are
4063 // still present, however, as belt-and-suspenders.
4064
4065 if (received_new_header &&
4066 last_header.nChainWork > m_chainman.ActiveChain().Tip()->nChainWork) {
4067 nodestate->m_last_block_announcement = GetTime();
4068 }
4069
4070 // If we're in IBD, we want outbound peers that will serve us a useful
4071 // chain. Disconnect peers that are on chains with insufficient work.
4072 if (m_chainman.IsInitialBlockDownload() && !may_have_more_headers) {
4073 // When nCount < MAX_HEADERS_RESULTS, we know we have no more
4074 // headers to fetch from this peer.
4075 if (nodestate->pindexBestKnownBlock &&
4076 nodestate->pindexBestKnownBlock->nChainWork <
4077 m_chainman.MinimumChainWork()) {
4078 // This peer has too little work on their headers chain to help
4079 // us sync -- disconnect if it is an outbound disconnection
4080 // candidate.
4081 // Note: We compare their tip to the minimum chain work (rather than
4082 // m_chainman.ActiveChain().Tip()) because we won't start block
4083 // download until we have a headers chain that has at least
4084 // the minimum chain work, even if a peer has a chain past our tip,
4085 // as an anti-DoS measure.
4086 if (pfrom.IsOutboundOrBlockRelayConn()) {
4087 LogPrintf("Disconnecting outbound peer %d -- headers "
4088 "chain has insufficient work\n",
4089 pfrom.GetId());
4090 pfrom.fDisconnect = true;
4091 }
4092 }
4093 }
4094
4095 // If this is an outbound full-relay peer, check to see if we should
4096 // protect it from the bad/lagging chain logic.
4097 // Note that outbound block-relay peers are excluded from this
4098 // protection, and thus always subject to eviction under the bad/lagging
4099 // chain logic.
4100 // See ChainSyncTimeoutState.
4101 if (!pfrom.fDisconnect && pfrom.IsFullOutboundConn() &&
4102 nodestate->pindexBestKnownBlock != nullptr) {
4103 if (m_outbound_peers_with_protect_from_disconnect <
4105 nodestate->pindexBestKnownBlock->nChainWork >=
4106 m_chainman.ActiveChain().Tip()->nChainWork &&
4107 !nodestate->m_chain_sync.m_protect) {
4108 LogPrint(BCLog::NET, "Protecting outbound peer=%d from eviction\n",
4109 pfrom.GetId());
4110 nodestate->m_chain_sync.m_protect = true;
4111 ++m_outbound_peers_with_protect_from_disconnect;
4112 }
4113 }
4114}
4115
4116void PeerManagerImpl::ProcessHeadersMessage(const Config &config, CNode &pfrom,
4117 Peer &peer,
4118 std::vector<CBlockHeader> &&headers,
4119 bool via_compact_block) {
4120 size_t nCount = headers.size();
4121
4122 if (nCount == 0) {
4123 // Nothing interesting. Stop asking this peers for more headers.
4124 // If we were in the middle of headers sync, receiving an empty headers
4125 // message suggests that the peer suddenly has nothing to give us
4126 // (perhaps it reorged to our chain). Clear download state for this
4127 // peer.
4128 LOCK(peer.m_headers_sync_mutex);
4129 if (peer.m_headers_sync) {
4130 peer.m_headers_sync.reset(nullptr);
4131 LOCK(m_headers_presync_mutex);
4132 m_headers_presync_stats.erase(pfrom.GetId());
4133 }
4134 // A headers message with no headers cannot be an announcement, so
4135 // assume it is a response to our last getheaders request, if there is
4136 // one.
4137 peer.m_last_getheaders_timestamp = {};
4138 return;
4139 }
4140
4141 // Before we do any processing, make sure these pass basic sanity checks.
4142 // We'll rely on headers having valid proof-of-work further down, as an
4143 // anti-DoS criteria (note: this check is required before passing any
4144 // headers into HeadersSyncState).
4145 if (!CheckHeadersPoW(headers, m_chainparams.GetConsensus(), peer)) {
4146 // Misbehaving() calls are handled within CheckHeadersPoW(), so we can
4147 // just return. (Note that even if a header is announced via compact
4148 // block, the header itself should be valid, so this type of error can
4149 // always be punished.)
4150 return;
4151 }
4152
4153 const CBlockIndex *pindexLast = nullptr;
4154
4155 // We'll set already_validated_work to true if these headers are
4156 // successfully processed as part of a low-work headers sync in progress
4157 // (either in PRESYNC or REDOWNLOAD phase).
4158 // If true, this will mean that any headers returned to us (ie during
4159 // REDOWNLOAD) can be validated without further anti-DoS checks.
4160 bool already_validated_work = false;
4161
4162 // If we're in the middle of headers sync, let it do its magic.
4163 bool have_headers_sync = false;
4164 {
4165 LOCK(peer.m_headers_sync_mutex);
4166
4167 already_validated_work =
4168 IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
4169
4170 // The headers we passed in may have been:
4171 // - untouched, perhaps if no headers-sync was in progress, or some
4172 // failure occurred
4173 // - erased, such as if the headers were successfully processed and no
4174 // additional headers processing needs to take place (such as if we
4175 // are still in PRESYNC)
4176 // - replaced with headers that are now ready for validation, such as
4177 // during the REDOWNLOAD phase of a low-work headers sync.
4178 // So just check whether we still have headers that we need to process,
4179 // or not.
4180 if (headers.empty()) {
4181 return;
4182 }
4183
4184 have_headers_sync = !!peer.m_headers_sync;
4185 }
4186
4187 // Do these headers connect to something in our block index?
4188 const CBlockIndex *chain_start_header{
4190 headers[0].hashPrevBlock))};
4191 bool headers_connect_blockindex{chain_start_header != nullptr};
4192
4193 if (!headers_connect_blockindex) {
4194 // This could be a BIP 130 block announcement, use
4195 // special logic for handling headers that don't connect, as this
4196 // could be benign.
4197 HandleUnconnectingHeaders(pfrom, peer, headers);
4198 return;
4199 }
4200
4201 // If headers connect, assume that this is in response to any outstanding
4202 // getheaders request we may have sent, and clear out the time of our last
4203 // request. Non-connecting headers cannot be a response to a getheaders
4204 // request.
4205 peer.m_last_getheaders_timestamp = {};
4206
4207 // If the headers we received are already in memory and an ancestor of
4208 // m_best_header or our tip, skip anti-DoS checks. These headers will not
4209 // use any more memory (and we are not leaking information that could be
4210 // used to fingerprint us).
4211 const CBlockIndex *last_received_header{nullptr};
4212 {
4213 LOCK(cs_main);
4214 last_received_header =
4215 m_chainman.m_blockman.LookupBlockIndex(headers.back().GetHash());
4216 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
4217 already_validated_work = true;
4218 }
4219 }
4220
4221 // If our peer has NetPermissionFlags::NoBan privileges, then bypass our
4222 // anti-DoS logic (this saves bandwidth when we connect to a trusted peer
4223 // on startup).
4225 already_validated_work = true;
4226 }
4227
4228 // At this point, the headers connect to something in our block index.
4229 // Do anti-DoS checks to determine if we should process or store for later
4230 // processing.
4231 if (!already_validated_work &&
4232 TryLowWorkHeadersSync(peer, pfrom, chain_start_header, headers)) {
4233 // If we successfully started a low-work headers sync, then there
4234 // should be no headers to process any further.
4235 Assume(headers.empty());
4236 return;
4237 }
4238
4239 // At this point, we have a set of headers with sufficient work on them
4240 // which can be processed.
4241
4242 // If we don't have the last header, then this peer will have given us
4243 // something new (if these headers are valid).
4244 bool received_new_header{last_received_header == nullptr};
4245
4246 // Now process all the headers.
4248 if (!m_chainman.ProcessNewBlockHeaders(headers, /*min_pow_checked=*/true,
4249 state, &pindexLast)) {
4250 if (state.IsInvalid()) {
4251 MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block,
4252 "invalid header received");
4253 return;
4254 }
4255 }
4256 assert(pindexLast);
4257
4258 // Consider fetching more headers if we are not using our headers-sync
4259 // mechanism.
4260 if (nCount == MAX_HEADERS_RESULTS && !have_headers_sync) {
4261 // Headers message had its maximum size; the peer may have more headers.
4262 if (MaybeSendGetHeaders(pfrom, GetLocator(pindexLast), peer)) {
4263 LogPrint(
4264 BCLog::NET,
4265 "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
4266 pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
4267 }
4268 }
4269
4270 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast,
4271 received_new_header,
4272 nCount == MAX_HEADERS_RESULTS);
4273
4274 // Consider immediately downloading blocks.
4275 HeadersDirectFetchBlocks(config, pfrom, *pindexLast);
4276}
4277
4278void PeerManagerImpl::ProcessInvalidTx(NodeId nodeid,
4279 const CTransactionRef &ptx,
4280 const TxValidationState &state,
4281 bool maybe_add_extra_compact_tx) {
4282 AssertLockNotHeld(m_peer_mutex);
4283 AssertLockHeld(g_msgproc_mutex);
4285
4286 const TxId &txid = ptx->GetId();
4287
4288 LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n",
4289 txid.ToString(), nodeid, state.ToString());
4290
4292 return;
4293 }
4294
4295 if (m_avalanche &&
4296 m_avalanche->isPreconsensusActivated(m_chainman.ActiveTip()) &&
4298 return;
4299 }
4300
4302 // If the result is TX_PACKAGE_RECONSIDERABLE, add it to
4303 // m_recent_rejects_package_reconsiderable because we should not
4304 // download or submit this transaction by itself again, but may submit
4305 // it as part of a package later.
4306 m_recent_rejects_package_reconsiderable.insert(txid);
4307 } else {
4308 m_recent_rejects.insert(txid);
4309 }
4310 m_txrequest.ForgetInvId(txid);
4311
4312 if (maybe_add_extra_compact_tx && RecursiveDynamicUsage(*ptx) < 100000) {
4313 AddToCompactExtraTransactions(ptx);
4314 }
4315
4316 MaybePunishNodeForTx(nodeid, state);
4317
4318 // If the tx failed in ProcessOrphanTx, it should be removed from the
4319 // orphanage unless the tx was still missing inputs. If the tx was not in
4320 // the orphanage, EraseTx does nothing and returns 0.
4321 if (m_mempool.withOrphanage([&txid](TxOrphanage &orphanage) {
4322 return orphanage.EraseTx(txid);
4323 }) > 0) {
4324 LogPrint(BCLog::TXPACKAGES, " removed orphan tx %s\n",
4325 txid.ToString());
4326 }
4327}
4328
4329void PeerManagerImpl::ProcessValidTx(NodeId nodeid, const CTransactionRef &tx) {
4330 AssertLockNotHeld(m_peer_mutex);
4331 AssertLockHeld(g_msgproc_mutex);
4333
4334 // As this version of the transaction was acceptable, we can forget about
4335 // any requests for it. No-op if the tx is not in txrequest.
4336 m_txrequest.ForgetInvId(tx->GetId());
4337
4338 m_mempool.withOrphanage([&tx](TxOrphanage &orphanage) {
4339 orphanage.AddChildrenToWorkSet(*tx);
4340 // If it came from the orphanage, remove it. No-op if the tx is not in
4341 // txorphanage.
4342 orphanage.EraseTx(tx->GetId());
4343 });
4344
4345 LogPrint(
4347 "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n",
4348 nodeid, tx->GetId().ToString(), m_mempool.size(),
4349 m_mempool.DynamicMemoryUsage() / 1000);
4350
4351 RelayTransaction(tx->GetId());
4352}
4353
4354void PeerManagerImpl::ProcessPackageResult(
4355 const PackageToValidate &package_to_validate,
4356 const PackageMempoolAcceptResult &package_result) {
4357 AssertLockNotHeld(m_peer_mutex);
4358 AssertLockHeld(g_msgproc_mutex);
4360
4361 const auto &package = package_to_validate.m_txns;
4362 const auto &senders = package_to_validate.m_senders;
4363
4364 if (package_result.m_state.IsInvalid()) {
4365 m_recent_rejects_package_reconsiderable.insert(GetPackageHash(package));
4366 }
4367 // We currently only expect to process 1-parent-1-child packages. Remove if
4368 // this changes.
4369 if (!Assume(package.size() == 2)) {
4370 return;
4371 }
4372
4373 // Iterate backwards to erase in-package descendants from the orphanage
4374 // before they become relevant in AddChildrenToWorkSet.
4375 auto package_iter = package.rbegin();
4376 auto senders_iter = senders.rbegin();
4377 while (package_iter != package.rend()) {
4378 const auto &tx = *package_iter;
4379 const NodeId nodeid = *senders_iter;
4380 const auto it_result{package_result.m_tx_results.find(tx->GetId())};
4381
4382 // It is not guaranteed that a result exists for every transaction.
4383 if (it_result != package_result.m_tx_results.end()) {
4384 const auto &tx_result = it_result->second;
4385 switch (tx_result.m_result_type) {
4387 ProcessValidTx(nodeid, tx);
4388 break;
4389 }
4391 // Don't add to vExtraTxnForCompact, as these transactions
4392 // should have already been added there when added to the
4393 // orphanage or rejected for TX_PACKAGE_RECONSIDERABLE.
4394 // This should be updated if package submission is ever used
4395 // for transactions that haven't already been validated
4396 // before.
4397 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
4398 /*maybe_add_extra_compact_tx=*/false);
4399 break;
4400 }
4402 // AlreadyHaveTx() should be catching transactions that are
4403 // already in mempool.
4404 Assume(false);
4405 break;
4406 }
4407 }
4408 }
4409 package_iter++;
4410 senders_iter++;
4411 }
4412}
4413
4414std::optional<PeerManagerImpl::PackageToValidate>
4415PeerManagerImpl::Find1P1CPackage(const CTransactionRef &ptx, NodeId nodeid) {
4416 AssertLockNotHeld(m_peer_mutex);
4417 AssertLockHeld(g_msgproc_mutex);
4419
4420 const auto &parent_txid{ptx->GetId()};
4421
4422 Assume(m_recent_rejects_package_reconsiderable.contains(parent_txid));
4423
4424 // Prefer children from this peer. This helps prevent censorship attempts in
4425 // which an attacker sends lots of fake children for the parent, and we
4426 // (unluckily) keep selecting the fake children instead of the real one
4427 // provided by the honest peer.
4428 const auto cpfp_candidates_same_peer{
4429 m_mempool.withOrphanage([&ptx, nodeid](const TxOrphanage &orphanage) {
4430 return orphanage.GetChildrenFromSamePeer(ptx, nodeid);
4431 })};
4432
4433 // These children should be sorted from newest to oldest.
4434 for (const auto &child : cpfp_candidates_same_peer) {
4435 Package maybe_cpfp_package{ptx, child};
4436 if (!m_recent_rejects_package_reconsiderable.contains(
4437 GetPackageHash(maybe_cpfp_package))) {
4438 return PeerManagerImpl::PackageToValidate{ptx, child, nodeid,
4439 nodeid};
4440 }
4441 }
4442
4443 // If no suitable candidate from the same peer is found, also try children
4444 // that were provided by a different peer. This is useful because sometimes
4445 // multiple peers announce both transactions to us, and we happen to
4446 // download them from different peers (we wouldn't have known that these 2
4447 // transactions are related). We still want to find 1p1c packages then.
4448 //
4449 // If we start tracking all announcers of orphans, we can restrict this
4450 // logic to parent + child pairs in which both were provided by the same
4451 // peer, i.e. delete this step.
4452 const auto cpfp_candidates_different_peer{
4453 m_mempool.withOrphanage([&ptx, nodeid](const TxOrphanage &orphanage) {
4454 return orphanage.GetChildrenFromDifferentPeer(ptx, nodeid);
4455 })};
4456
4457 // Find the first 1p1c that hasn't already been rejected. We randomize the
4458 // order to not create a bias that attackers can use to delay package
4459 // acceptance.
4460 //
4461 // Create a random permutation of the indices.
4462 std::vector<size_t> tx_indices(cpfp_candidates_different_peer.size());
4463 std::iota(tx_indices.begin(), tx_indices.end(), 0);
4464 Shuffle(tx_indices.begin(), tx_indices.end(), m_rng);
4465
4466 for (const auto index : tx_indices) {
4467 // If we already tried a package and failed for any reason, the combined
4468 // hash was cached in m_recent_rejects_package_reconsiderable.
4469 const auto [child_tx, child_sender] =
4470 cpfp_candidates_different_peer.at(index);
4471 Package maybe_cpfp_package{ptx, child_tx};
4472 if (!m_recent_rejects_package_reconsiderable.contains(
4473 GetPackageHash(maybe_cpfp_package))) {
4474 return PeerManagerImpl::PackageToValidate{ptx, child_tx, nodeid,
4475 child_sender};
4476 }
4477 }
4478 return std::nullopt;
4479}
4480
4481bool PeerManagerImpl::ProcessOrphanTx(const Config &config, Peer &peer) {
4482 AssertLockHeld(g_msgproc_mutex);
4483 LOCK(cs_main);
4484
4485 while (CTransactionRef porphanTx =
4486 m_mempool.withOrphanage([&peer](TxOrphanage &orphanage) {
4487 return orphanage.GetTxToReconsider(peer.m_id);
4488 })) {
4489 const MempoolAcceptResult result =
4490 m_chainman.ProcessTransaction(porphanTx);
4491 const TxValidationState &state = result.m_state;
4492 const TxId &orphanTxId = porphanTx->GetId();
4493
4495 LogPrint(BCLog::TXPACKAGES, " accepted orphan tx %s\n",
4496 orphanTxId.ToString());
4497 ProcessValidTx(peer.m_id, porphanTx);
4498 return true;
4499 }
4500
4503 " invalid orphan tx %s from peer=%d. %s\n",
4504 orphanTxId.ToString(), peer.m_id, state.ToString());
4505
4506 if (Assume(state.IsInvalid() &&
4508 state.GetResult() !=
4510 ProcessInvalidTx(peer.m_id, porphanTx, state,
4511 /*maybe_add_extra_compact_tx=*/false);
4512 }
4513
4514 return true;
4515 }
4516 }
4517
4518 return false;
4519}
4520
4521bool PeerManagerImpl::PrepareBlockFilterRequest(
4522 CNode &node, Peer &peer, BlockFilterType filter_type, uint32_t start_height,
4523 const BlockHash &stop_hash, uint32_t max_height_diff,
4524 const CBlockIndex *&stop_index, BlockFilterIndex *&filter_index) {
4525 const bool supported_filter_type =
4526 (filter_type == BlockFilterType::BASIC &&
4527 (peer.m_our_services & NODE_COMPACT_FILTERS));
4528 if (!supported_filter_type) {
4530 "peer %d requested unsupported block filter type: %d\n",
4531 node.GetId(), static_cast<uint8_t>(filter_type));
4532 node.fDisconnect = true;
4533 return false;
4534 }
4535
4536 {
4537 LOCK(cs_main);
4538 stop_index = m_chainman.m_blockman.LookupBlockIndex(stop_hash);
4539
4540 // Check that the stop block exists and the peer would be allowed to
4541 // fetch it.
4542 if (!stop_index || !BlockRequestAllowed(stop_index)) {
4543 LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n",
4544 node.GetId(), stop_hash.ToString());
4545 node.fDisconnect = true;
4546 return false;
4547 }
4548 }
4549
4550 uint32_t stop_height = stop_index->nHeight;
4551 if (start_height > stop_height) {
4552 LogPrint(
4553 BCLog::NET,
4554 "peer %d sent invalid getcfilters/getcfheaders with " /* Continued
4555 */
4556 "start height %d and stop height %d\n",
4557 node.GetId(), start_height, stop_height);
4558 node.fDisconnect = true;
4559 return false;
4560 }
4561 if (stop_height - start_height >= max_height_diff) {
4563 "peer %d requested too many cfilters/cfheaders: %d / %d\n",
4564 node.GetId(), stop_height - start_height + 1, max_height_diff);
4565 node.fDisconnect = true;
4566 return false;
4567 }
4568
4569 filter_index = GetBlockFilterIndex(filter_type);
4570 if (!filter_index) {
4571 LogPrint(BCLog::NET, "Filter index for supported type %s not found\n",
4572 BlockFilterTypeName(filter_type));
4573 return false;
4574 }
4575
4576 return true;
4577}
4578
4579void PeerManagerImpl::ProcessGetCFilters(CNode &node, Peer &peer,
4580 DataStream &vRecv) {
4581 uint8_t filter_type_ser;
4582 uint32_t start_height;
4583 BlockHash stop_hash;
4584
4585 vRecv >> filter_type_ser >> start_height >> stop_hash;
4586
4587 const BlockFilterType filter_type =
4588 static_cast<BlockFilterType>(filter_type_ser);
4589
4590 const CBlockIndex *stop_index;
4591 BlockFilterIndex *filter_index;
4592 if (!PrepareBlockFilterRequest(node, peer, filter_type, start_height,
4593 stop_hash, MAX_GETCFILTERS_SIZE, stop_index,
4594 filter_index)) {
4595 return;
4596 }
4597
4598 std::vector<BlockFilter> filters;
4599 if (!filter_index->LookupFilterRange(start_height, stop_index, filters)) {
4601 "Failed to find block filter in index: filter_type=%s, "
4602 "start_height=%d, stop_hash=%s\n",
4603 BlockFilterTypeName(filter_type), start_height,
4604 stop_hash.ToString());
4605 return;
4606 }
4607
4608 for (const auto &filter : filters) {
4609 MakeAndPushMessage(node, NetMsgType::CFILTER, filter);
4610 }
4611}
4612
4613void PeerManagerImpl::ProcessGetCFHeaders(CNode &node, Peer &peer,
4614 DataStream &vRecv) {
4615 uint8_t filter_type_ser;
4616 uint32_t start_height;
4617 BlockHash stop_hash;
4618
4619 vRecv >> filter_type_ser >> start_height >> stop_hash;
4620
4621 const BlockFilterType filter_type =
4622 static_cast<BlockFilterType>(filter_type_ser);
4623
4624 const CBlockIndex *stop_index;
4625 BlockFilterIndex *filter_index;
4626 if (!PrepareBlockFilterRequest(node, peer, filter_type, start_height,
4627 stop_hash, MAX_GETCFHEADERS_SIZE, stop_index,
4628 filter_index)) {
4629 return;
4630 }
4631
4632 uint256 prev_header;
4633 if (start_height > 0) {
4634 const CBlockIndex *const prev_block =
4635 stop_index->GetAncestor(static_cast<int>(start_height - 1));
4636 if (!filter_index->LookupFilterHeader(prev_block, prev_header)) {
4638 "Failed to find block filter header in index: "
4639 "filter_type=%s, block_hash=%s\n",
4640 BlockFilterTypeName(filter_type),
4641 prev_block->GetBlockHash().ToString());
4642 return;
4643 }
4644 }
4645
4646 std::vector<uint256> filter_hashes;
4647 if (!filter_index->LookupFilterHashRange(start_height, stop_index,
4648 filter_hashes)) {
4650 "Failed to find block filter hashes in index: filter_type=%s, "
4651 "start_height=%d, stop_hash=%s\n",
4652 BlockFilterTypeName(filter_type), start_height,
4653 stop_hash.ToString());
4654 return;
4655 }
4656
4657 MakeAndPushMessage(node, NetMsgType::CFHEADERS, filter_type_ser,
4658 stop_index->GetBlockHash(), prev_header, filter_hashes);
4659}
4660
4661void PeerManagerImpl::ProcessGetCFCheckPt(CNode &node, Peer &peer,
4662 DataStream &vRecv) {
4663 uint8_t filter_type_ser;
4664 BlockHash stop_hash;
4665
4666 vRecv >> filter_type_ser >> stop_hash;
4667
4668 const BlockFilterType filter_type =
4669 static_cast<BlockFilterType>(filter_type_ser);
4670
4671 const CBlockIndex *stop_index;
4672 BlockFilterIndex *filter_index;
4673 if (!PrepareBlockFilterRequest(
4674 node, peer, filter_type, /*start_height=*/0, stop_hash,
4675 /*max_height_diff=*/std::numeric_limits<uint32_t>::max(),
4676 stop_index, filter_index)) {
4677 return;
4678 }
4679
4680 std::vector<uint256> headers(stop_index->nHeight / CFCHECKPT_INTERVAL);
4681
4682 // Populate headers.
4683 const CBlockIndex *block_index = stop_index;
4684 for (int i = headers.size() - 1; i >= 0; i--) {
4685 int height = (i + 1) * CFCHECKPT_INTERVAL;
4686 block_index = block_index->GetAncestor(height);
4687
4688 if (!filter_index->LookupFilterHeader(block_index, headers[i])) {
4690 "Failed to find block filter header in index: "
4691 "filter_type=%s, block_hash=%s\n",
4692 BlockFilterTypeName(filter_type),
4693 block_index->GetBlockHash().ToString());
4694 return;
4695 }
4696 }
4697
4698 MakeAndPushMessage(node, NetMsgType::CFCHECKPT, filter_type_ser,
4699 stop_index->GetBlockHash(), headers);
4700}
4701
4702bool IsAvalancheMessageType(const std::string &msg_type) {
4703 return msg_type == NetMsgType::AVAHELLO ||
4704 msg_type == NetMsgType::AVAPOLL ||
4705 msg_type == NetMsgType::AVARESPONSE ||
4706 msg_type == NetMsgType::AVAPROOF ||
4707 msg_type == NetMsgType::GETAVAADDR ||
4708 msg_type == NetMsgType::GETAVAPROOFS ||
4709 msg_type == NetMsgType::AVAPROOFS ||
4710 msg_type == NetMsgType::AVAPROOFSREQ;
4711}
4712
4713uint32_t
4714PeerManagerImpl::GetAvalancheVoteForBlock(const BlockHash &hash) const {
4716
4717 const CBlockIndex *pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
4718
4719 // Unknown block.
4720 if (!pindex) {
4721 return -1;
4722 }
4723
4724 // Invalid block
4725 if (pindex->nStatus.isInvalid()) {
4726 return 1;
4727 }
4728
4729 // Parked block
4730 if (pindex->nStatus.isOnParkedChain()) {
4731 return 2;
4732 }
4733
4734 const CBlockIndex *pindexTip = m_chainman.ActiveChain().Tip();
4735 const CBlockIndex *pindexFork = LastCommonAncestor(pindex, pindexTip);
4736
4737 // Active block.
4738 if (pindex == pindexFork) {
4739 return 0;
4740 }
4741
4742 // Fork block.
4743 if (pindexFork != pindexTip) {
4744 return 3;
4745 }
4746
4747 // Missing block data.
4748 if (!pindex->nStatus.hasData()) {
4749 return -2;
4750 }
4751
4752 // This block is built on top of the tip, we have the data, it
4753 // is pending connection or rejection.
4754 return -3;
4755};
4756
4757uint32_t
4758PeerManagerImpl::GetAvalancheVoteForTx(const avalanche::Processor &avalanche,
4759 const TxId &id) const {
4760 // Recently confirmed
4761 if (WITH_LOCK(m_recent_confirmed_transactions_mutex,
4762 return m_recent_confirmed_transactions.contains(id))) {
4763 return 0;
4764 }
4765
4766 CTransactionRef mempool_tx;
4767 {
4768 LOCK(::cs_main);
4769
4770 // Invalid tx. m_recent_rejects needs cs_main
4771 if (m_recent_rejects.contains(id)) {
4772 return 1;
4773 }
4774
4775 LOCK(m_mempool.cs);
4776
4777 // Finalized
4778 if (m_mempool.isAvalancheFinalizedPreConsensus(id)) {
4779 return 0;
4780 }
4781
4782 // Accepted in mempool
4783 if (auto iter = m_mempool.GetIter(id)) {
4784 mempool_tx = (**iter)->GetSharedTx();
4785 } else {
4786 // Conflicting tx
4787 if (m_mempool.withConflicting(
4788 [&id](const TxConflicting &conflicting) {
4789 return conflicting.HaveTx(id);
4790 })) {
4791 return 2;
4792 }
4793
4794 // Orphan tx
4795 if (m_mempool.withOrphanage([&id](const TxOrphanage &orphanage) {
4796 return orphanage.HaveTx(id);
4797 })) {
4798 return -2;
4799 }
4800 }
4801 } // release cs_main and mempool.cs locks
4802
4803 // isPolled() access the vote records, and should be accessed with cs_main
4804 // released.
4805 // If the tx is in the mempool...
4806 if (mempool_tx) {
4807 // ... and in the polled list
4808 if (avalanche.isPolled(mempool_tx)) {
4809 return 0;
4810 }
4811
4812 // ... but not in the polled list
4813 return -3;
4814 }
4815
4816 // Unknown tx
4817 return -1;
4818};
4819
4827 const avalanche::ProofId &id) {
4828 return avalanche.withPeerManager([&id](avalanche::PeerManager &pm) {
4829 // Rejected proof
4830 if (pm.isInvalid(id)) {
4831 return 1;
4832 }
4833
4834 // The proof is actively bound to a peer
4835 if (pm.isBoundToPeer(id)) {
4836 return 0;
4837 }
4838
4839 // Unknown proof
4840 if (!pm.exists(id)) {
4841 return -1;
4842 }
4843
4844 // Immature proof
4845 if (pm.isImmature(id)) {
4846 return 2;
4847 }
4848
4849 // Not immature, but in conflict with an actively bound proof
4850 if (pm.isInConflictingPool(id)) {
4851 return 3;
4852 }
4853
4854 // The proof is known, not rejected, not immature, not a conflict, but
4855 // for some reason unbound. This should not happen if the above pools
4856 // are managed correctly, but added for robustness.
4857 return -2;
4858 });
4859};
4860
4861void PeerManagerImpl::ProcessBlock(const Config &config, CNode &node,
4862 const std::shared_ptr<const CBlock> &block,
4863 bool force_processing,
4864 bool min_pow_checked) {
4865 bool new_block{false};
4866 m_chainman.ProcessNewBlock(block, force_processing, min_pow_checked,
4867 &new_block, m_avalanche);
4868 if (new_block) {
4869 node.m_last_block_time = GetTime<std::chrono::seconds>();
4870 // In case this block came from a different peer than we requested
4871 // from, we can erase the block request now anyway (as we just stored
4872 // this block to disk).
4873 LOCK(cs_main);
4874 RemoveBlockRequest(block->GetHash(), std::nullopt);
4875 } else {
4876 LOCK(cs_main);
4877 mapBlockSource.erase(block->GetHash());
4878 }
4879}
4880
4881void PeerManagerImpl::ProcessMessage(
4882 const Config &config, CNode &pfrom, const std::string &msg_type,
4883 DataStream &vRecv, const std::chrono::microseconds time_received,
4884 const std::atomic<bool> &interruptMsgProc) {
4885 AssertLockHeld(g_msgproc_mutex);
4886
4887 LogPrint(BCLog::NETDEBUG, "received: %s (%u bytes) peer=%d\n",
4888 SanitizeString(msg_type), vRecv.size(), pfrom.GetId());
4889
4890 PeerRef peer = GetPeerRef(pfrom.GetId());
4891 if (peer == nullptr) {
4892 return;
4893 }
4894
4895 if (!m_avalanche && IsAvalancheMessageType(msg_type)) {
4897 "Avalanche is not initialized, ignoring %s message\n",
4898 msg_type);
4899 return;
4900 }
4901
4902 if (msg_type == NetMsgType::VERSION) {
4903 // Each connection can only send one version message
4904 if (pfrom.nVersion != 0) {
4905 LogPrint(BCLog::NET, "redundant version message from peer=%d\n",
4906 pfrom.GetId());
4907 return;
4908 }
4909
4910 int64_t nTime;
4911 CService addrMe;
4912 uint64_t nNonce = 1;
4913 ServiceFlags nServices;
4914 int nVersion;
4915 std::string cleanSubVer;
4916 int starting_height = -1;
4917 bool fRelay = true;
4918 uint64_t nExtraEntropy = 1;
4919
4920 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
4921 if (nTime < 0) {
4922 nTime = 0;
4923 }
4924 // Ignore the addrMe service bits sent by the peer
4925 vRecv.ignore(8);
4926 vRecv >> WithParams(CNetAddr::V1, addrMe);
4927 if (!pfrom.IsInboundConn()) {
4928 m_addrman.SetServices(pfrom.addr, nServices);
4929 }
4930 if (pfrom.ExpectServicesFromConn() &&
4931 !HasAllDesirableServiceFlags(nServices)) {
4933 "peer=%d does not offer the expected services "
4934 "(%08x offered, %08x expected); disconnecting\n",
4935 pfrom.GetId(), nServices,
4936 GetDesirableServiceFlags(nServices));
4937 pfrom.fDisconnect = true;
4938 return;
4939 }
4940
4941 if (pfrom.IsAvalancheOutboundConnection() &&
4942 !(nServices & NODE_AVALANCHE)) {
4943 LogPrint(
4945 "peer=%d does not offer the avalanche service; disconnecting\n",
4946 pfrom.GetId());
4947 pfrom.fDisconnect = true;
4948 return;
4949 }
4950
4951 if (nVersion < MIN_PEER_PROTO_VERSION) {
4952 // disconnect from peers older than this proto version
4954 "peer=%d using obsolete version %i; disconnecting\n",
4955 pfrom.GetId(), nVersion);
4956 pfrom.fDisconnect = true;
4957 return;
4958 }
4959
4960 if (!vRecv.empty()) {
4961 // The version message includes information about the sending node
4962 // which we don't use:
4963 // - 8 bytes (service bits)
4964 // - 16 bytes (ipv6 address)
4965 // - 2 bytes (port)
4966 vRecv.ignore(26);
4967 vRecv >> nNonce;
4968 }
4969 if (!vRecv.empty()) {
4970 std::string strSubVer;
4971 vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH);
4972 cleanSubVer = SanitizeString(strSubVer);
4973 }
4974 if (!vRecv.empty()) {
4975 vRecv >> starting_height;
4976 }
4977 if (!vRecv.empty()) {
4978 vRecv >> fRelay;
4979 }
4980 if (!vRecv.empty()) {
4981 vRecv >> nExtraEntropy;
4982 }
4983 // Disconnect if we connected to ourself
4984 if (pfrom.IsInboundConn() && !m_connman.CheckIncomingNonce(nNonce)) {
4985 LogPrintf("connected to self at %s, disconnecting\n",
4986 pfrom.addr.ToStringAddrPort());
4987 pfrom.fDisconnect = true;
4988 return;
4989 }
4990
4991 if (pfrom.IsInboundConn() && addrMe.IsRoutable()) {
4992 SeenLocal(addrMe);
4993 }
4994
4995 // Inbound peers send us their version message when they connect.
4996 // We send our version message in response.
4997 if (pfrom.IsInboundConn()) {
4998 PushNodeVersion(config, pfrom, *peer);
4999 }
5000
5001 // Change version
5002 const int greatest_common_version =
5003 std::min(nVersion, PROTOCOL_VERSION);
5004 pfrom.SetCommonVersion(greatest_common_version);
5005 pfrom.nVersion = nVersion;
5006
5007 MakeAndPushMessage(pfrom, NetMsgType::VERACK);
5008
5009 // Signal ADDRv2 support (BIP155).
5010 MakeAndPushMessage(pfrom, NetMsgType::SENDADDRV2);
5011
5013 HasAllDesirableServiceFlags(nServices);
5014 peer->m_their_services = nServices;
5015 pfrom.SetAddrLocal(addrMe);
5016 {
5017 LOCK(pfrom.m_subver_mutex);
5018 pfrom.cleanSubVer = cleanSubVer;
5019 }
5020 peer->m_starting_height = starting_height;
5021
5022 // Only initialize the m_tx_relay data structure if:
5023 // - this isn't an outbound block-relay-only connection; and
5024 // - this isn't an outbound feeler connection, and
5025 // - fRelay=true or we're offering NODE_BLOOM to this peer
5026 // (NODE_BLOOM means that the peer may turn on tx relay later)
5027 if (!pfrom.IsBlockOnlyConn() && !pfrom.IsFeelerConn() &&
5028 (fRelay || (peer->m_our_services & NODE_BLOOM))) {
5029 auto *const tx_relay = peer->SetTxRelay();
5030 {
5031 LOCK(tx_relay->m_bloom_filter_mutex);
5032 // set to true after we get the first filter* message
5033 tx_relay->m_relay_txs = fRelay;
5034 }
5035 if (fRelay) {
5036 pfrom.m_relays_txs = true;
5037 }
5038 }
5039
5040 pfrom.nRemoteHostNonce = nNonce;
5041 pfrom.nRemoteExtraEntropy = nExtraEntropy;
5042
5043 // Potentially mark this peer as a preferred download peer.
5044 {
5045 LOCK(cs_main);
5046 CNodeState *state = State(pfrom.GetId());
5047 state->fPreferredDownload =
5048 (!pfrom.IsInboundConn() ||
5050 !pfrom.IsAddrFetchConn() && CanServeBlocks(*peer);
5051 m_num_preferred_download_peers += state->fPreferredDownload;
5052 }
5053
5054 // Attempt to initialize address relay for outbound peers and use result
5055 // to decide whether to send GETADDR, so that we don't send it to
5056 // inbound or outbound block-relay-only peers.
5057 bool send_getaddr{false};
5058 if (!pfrom.IsInboundConn()) {
5059 send_getaddr = SetupAddressRelay(pfrom, *peer);
5060 }
5061 if (send_getaddr) {
5062 // Do a one-time address fetch to help populate/update our addrman.
5063 // If we're starting up for the first time, our addrman may be
5064 // pretty empty, so this mechanism is important to help us connect
5065 // to the network.
5066 // We skip this for block-relay-only peers. We want to avoid
5067 // potentially leaking addr information and we do not want to
5068 // indicate to the peer that we will participate in addr relay.
5069 MakeAndPushMessage(pfrom, NetMsgType::GETADDR);
5070 peer->m_getaddr_sent = true;
5071 // When requesting a getaddr, accept an additional MAX_ADDR_TO_SEND
5072 // addresses in response (bypassing the
5073 // MAX_ADDR_PROCESSING_TOKEN_BUCKET limit).
5074 WITH_LOCK(peer->m_addr_token_bucket_mutex,
5075 peer->m_addr_token_bucket += m_opts.max_addr_to_send);
5076 }
5077
5078 if (!pfrom.IsInboundConn()) {
5079 // For non-inbound connections, we update the addrman to record
5080 // connection success so that addrman will have an up-to-date
5081 // notion of which peers are online and available.
5082 //
5083 // While we strive to not leak information about block-relay-only
5084 // connections via the addrman, not moving an address to the tried
5085 // table is also potentially detrimental because new-table entries
5086 // are subject to eviction in the event of addrman collisions. We
5087 // mitigate the information-leak by never calling
5088 // AddrMan::Connected() on block-relay-only peers; see
5089 // FinalizeNode().
5090 //
5091 // This moves an address from New to Tried table in Addrman,
5092 // resolves tried-table collisions, etc.
5093 m_addrman.Good(pfrom.addr);
5094 }
5095
5096 std::string remoteAddr;
5097 if (fLogIPs) {
5098 remoteAddr = ", peeraddr=" + pfrom.addr.ToStringAddrPort();
5099 }
5100
5102 "receive version message: [%s] %s: version %d, blocks=%d, "
5103 "us=%s, txrelay=%d, peer=%d%s\n",
5104 pfrom.addr.ToStringAddrPort(), cleanSubVer, pfrom.nVersion,
5105 peer->m_starting_height, addrMe.ToStringAddrPort(), fRelay,
5106 pfrom.GetId(), remoteAddr);
5107
5108 int64_t currentTime = GetTime();
5109 int64_t nTimeOffset = nTime - currentTime;
5110 pfrom.nTimeOffset = nTimeOffset;
5111 if (nTime < int64_t(m_chainparams.GenesisBlock().nTime)) {
5112 // Ignore time offsets that are improbable (before the Genesis
5113 // block) and may underflow our adjusted time.
5114 Misbehaving(*peer, "Ignoring invalid timestamp in version message");
5115 } else if (!pfrom.IsInboundConn()) {
5116 // Don't use timedata samples from inbound peers to make it
5117 // harder for others to tamper with our adjusted time.
5118 AddTimeData(pfrom.addr, nTimeOffset);
5119 }
5120
5121 // Feeler connections exist only to verify if address is online.
5122 if (pfrom.IsFeelerConn()) {
5124 "feeler connection completed peer=%d; disconnecting\n",
5125 pfrom.GetId());
5126 pfrom.fDisconnect = true;
5127 }
5128 return;
5129 }
5130
5131 if (pfrom.nVersion == 0) {
5132 // Must have a version message before anything else
5133 Misbehaving(*peer, "non-version message before version handshake");
5134 return;
5135 }
5136
5137 if (msg_type == NetMsgType::VERACK) {
5138 if (pfrom.fSuccessfullyConnected) {
5140 "ignoring redundant verack message from peer=%d\n",
5141 pfrom.GetId());
5142 return;
5143 }
5144
5145 if (!pfrom.IsInboundConn()) {
5146 LogPrintf("New outbound peer connected: version: %d, blocks=%d, "
5147 "peer=%d%s (%s)\n",
5148 pfrom.nVersion.load(), peer->m_starting_height,
5149 pfrom.GetId(),
5150 (fLogIPs ? strprintf(", peeraddr=%s",
5151 pfrom.addr.ToStringAddrPort())
5152 : ""),
5153 pfrom.ConnectionTypeAsString());
5154 }
5155
5157 // Tell our peer we are willing to provide version 1
5158 // cmpctblocks. However, we do not request new block announcements
5159 // using cmpctblock messages. We send this to non-NODE NETWORK peers
5160 // as well, because they may wish to request compact blocks from us.
5161 MakeAndPushMessage(pfrom, NetMsgType::SENDCMPCT,
5162 /*high_bandwidth=*/false,
5163 /*version=*/CMPCTBLOCKS_VERSION);
5164 }
5165
5166 if (m_avalanche) {
5167 if (m_avalanche->sendHello(&pfrom)) {
5168 auto localProof = m_avalanche->getLocalProof();
5169
5170 if (localProof) {
5171 AddKnownProof(*peer, localProof->getId());
5172 // Add our proof id to the list or the recently announced
5173 // proof INVs to this peer. This is used for filtering which
5174 // INV can be requested for download.
5175 peer->m_proof_relay->m_recently_announced_proofs.insert(
5176 localProof->getId());
5177 }
5178 }
5179 }
5180
5181 if (auto tx_relay = peer->GetTxRelay()) {
5182 // `TxRelay::m_tx_inventory_to_send` must be empty before the
5183 // version handshake is completed as
5184 // `TxRelay::m_next_inv_send_time` is first initialised in
5185 // `SendMessages` after the verack is received. Any transactions
5186 // received during the version handshake would otherwise
5187 // immediately be advertised without random delay, potentially
5188 // leaking the time of arrival to a spy.
5189 Assume(WITH_LOCK(tx_relay->m_tx_inventory_mutex,
5190 return tx_relay->m_tx_inventory_to_send.empty() &&
5191 tx_relay->m_next_inv_send_time == 0s));
5192 }
5193
5194 pfrom.fSuccessfullyConnected = true;
5195 return;
5196 }
5197
5198 if (!pfrom.fSuccessfullyConnected) {
5199 // Must have a verack message before anything else
5200 Misbehaving(*peer, "non-verack message before version handshake");
5201 return;
5202 }
5203
5204 if (msg_type == NetMsgType::ADDR || msg_type == NetMsgType::ADDRV2) {
5205 const auto ser_params{
5206 msg_type == NetMsgType::ADDRV2
5207 ?
5208 // Set V2 param so that the CNetAddr and CAddress unserialize
5209 // methods know that an address in v2 format is coming.
5212 };
5213
5214 std::vector<CAddress> vAddr;
5215
5216 vRecv >> WithParams(ser_params, vAddr);
5217
5218 if (!SetupAddressRelay(pfrom, *peer)) {
5219 LogPrint(BCLog::NET, "ignoring %s message from %s peer=%d\n",
5220 msg_type, pfrom.ConnectionTypeAsString(), pfrom.GetId());
5221 return;
5222 }
5223
5224 if (vAddr.size() > m_opts.max_addr_to_send) {
5225 Misbehaving(*peer, strprintf("%s message size = %u", msg_type,
5226 vAddr.size()));
5227 return;
5228 }
5229
5230 // Store the new addresses
5231 std::vector<CAddress> vAddrOk;
5232 const auto current_a_time{Now<NodeSeconds>()};
5233
5234 // Update/increment addr rate limiting bucket.
5235 const auto current_time = GetTime<std::chrono::microseconds>();
5236 {
5237 LOCK(peer->m_addr_token_bucket_mutex);
5238 if (peer->m_addr_token_bucket < MAX_ADDR_PROCESSING_TOKEN_BUCKET) {
5239 // Don't increment bucket if it's already full
5240 const auto time_diff =
5241 std::max(current_time - peer->m_addr_token_timestamp, 0us);
5242 const double increment =
5244 peer->m_addr_token_bucket =
5245 std::min<double>(peer->m_addr_token_bucket + increment,
5247 }
5248 }
5249 peer->m_addr_token_timestamp = current_time;
5250
5251 const bool rate_limited =
5253 uint64_t num_proc = 0;
5254 uint64_t num_rate_limit = 0;
5255 Shuffle(vAddr.begin(), vAddr.end(), m_rng);
5256 for (CAddress &addr : vAddr) {
5257 if (interruptMsgProc) {
5258 return;
5259 }
5260
5261 {
5262 LOCK(peer->m_addr_token_bucket_mutex);
5263 // Apply rate limiting.
5264 if (peer->m_addr_token_bucket < 1.0) {
5265 if (rate_limited) {
5266 ++num_rate_limit;
5267 continue;
5268 }
5269 } else {
5270 peer->m_addr_token_bucket -= 1.0;
5271 }
5272 }
5273
5274 // We only bother storing full nodes, though this may include things
5275 // which we would not make an outbound connection to, in part
5276 // because we may make feeler connections to them.
5277 if (!MayHaveUsefulAddressDB(addr.nServices) &&
5279 continue;
5280 }
5281
5282 if (addr.nTime <= NodeSeconds{100000000s} ||
5283 addr.nTime > current_a_time + 10min) {
5284 addr.nTime = current_a_time - 5 * 24h;
5285 }
5286 AddAddressKnown(*peer, addr);
5287 if (m_banman &&
5288 (m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr))) {
5289 // Do not process banned/discouraged addresses beyond
5290 // remembering we received them
5291 continue;
5292 }
5293 ++num_proc;
5294 bool fReachable = IsReachable(addr);
5295 if (addr.nTime > current_a_time - 10min && !peer->m_getaddr_sent &&
5296 vAddr.size() <= 10 && addr.IsRoutable()) {
5297 // Relay to a limited number of other nodes
5298 RelayAddress(pfrom.GetId(), addr, fReachable);
5299 }
5300 // Do not store addresses outside our network
5301 if (fReachable) {
5302 vAddrOk.push_back(addr);
5303 }
5304 }
5305 peer->m_addr_processed += num_proc;
5306 peer->m_addr_rate_limited += num_rate_limit;
5308 "Received addr: %u addresses (%u processed, %u rate-limited) "
5309 "from peer=%d\n",
5310 vAddr.size(), num_proc, num_rate_limit, pfrom.GetId());
5311
5312 m_addrman.Add(vAddrOk, pfrom.addr, 2h);
5313 if (vAddr.size() < 1000) {
5314 peer->m_getaddr_sent = false;
5315 }
5316
5317 // AddrFetch: Require multiple addresses to avoid disconnecting on
5318 // self-announcements
5319 if (pfrom.IsAddrFetchConn() && vAddr.size() > 1) {
5321 "addrfetch connection completed peer=%d; disconnecting\n",
5322 pfrom.GetId());
5323 pfrom.fDisconnect = true;
5324 }
5325 return;
5326 }
5327
5328 if (msg_type == NetMsgType::SENDADDRV2) {
5329 peer->m_wants_addrv2 = true;
5330 return;
5331 }
5332
5333 if (msg_type == NetMsgType::SENDHEADERS) {
5334 peer->m_prefers_headers = true;
5335 return;
5336 }
5337
5338 if (msg_type == NetMsgType::SENDCMPCT) {
5339 bool sendcmpct_hb{false};
5340 uint64_t sendcmpct_version{0};
5341 vRecv >> sendcmpct_hb >> sendcmpct_version;
5342
5343 if (sendcmpct_version != CMPCTBLOCKS_VERSION) {
5344 return;
5345 }
5346
5347 LOCK(cs_main);
5348 CNodeState *nodestate = State(pfrom.GetId());
5349 nodestate->m_provides_cmpctblocks = true;
5350 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
5351 // save whether peer selects us as BIP152 high-bandwidth peer
5352 // (receiving sendcmpct(1) signals high-bandwidth,
5353 // sendcmpct(0) low-bandwidth)
5354 pfrom.m_bip152_highbandwidth_from = sendcmpct_hb;
5355 return;
5356 }
5357
5358 if (msg_type == NetMsgType::INV) {
5359 std::vector<CInv> vInv;
5360 vRecv >> vInv;
5361 if (vInv.size() > MAX_INV_SZ) {
5362 Misbehaving(*peer, strprintf("inv message size = %u", vInv.size()));
5363 return;
5364 }
5365
5366 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
5367
5368 const auto current_time{GetTime<std::chrono::microseconds>()};
5369 std::optional<BlockHash> best_block;
5370
5371 auto logInv = [&](const CInv &inv, bool fAlreadyHave) {
5372 LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(),
5373 fAlreadyHave ? "have" : "new", pfrom.GetId());
5374 };
5375
5376 for (CInv &inv : vInv) {
5377 if (interruptMsgProc) {
5378 return;
5379 }
5380
5381 if (inv.IsMsgStakeContender()) {
5382 // Ignore invs with stake contenders. This type is only used for
5383 // polling.
5384 continue;
5385 }
5386
5387 if (inv.IsMsgBlk()) {
5388 LOCK(cs_main);
5389 const bool fAlreadyHave = AlreadyHaveBlock(BlockHash(inv.hash));
5390 logInv(inv, fAlreadyHave);
5391
5392 BlockHash hash{inv.hash};
5393 UpdateBlockAvailability(pfrom.GetId(), hash);
5394 if (!fAlreadyHave && !m_chainman.m_blockman.LoadingBlocks() &&
5395 !IsBlockRequested(hash)) {
5396 // Headers-first is the primary method of announcement on
5397 // the network. If a node fell back to sending blocks by
5398 // inv, it may be for a re-org, or because we haven't
5399 // completed initial headers sync. The final block hash
5400 // provided should be the highest, so send a getheaders and
5401 // then fetch the blocks we need to catch up.
5402 best_block = std::move(hash);
5403 }
5404
5405 continue;
5406 }
5407
5408 if (inv.IsMsgProof()) {
5409 if (!m_avalanche) {
5410 continue;
5411 }
5412 const avalanche::ProofId proofid(inv.hash);
5413 const bool fAlreadyHave = AlreadyHaveProof(proofid);
5414 logInv(inv, fAlreadyHave);
5415 AddKnownProof(*peer, proofid);
5416
5417 if (!fAlreadyHave && m_avalanche &&
5418 !m_chainman.IsInitialBlockDownload()) {
5419 const bool preferred = isPreferredDownloadPeer(pfrom);
5420
5421 LOCK(cs_proofrequest);
5422 AddProofAnnouncement(pfrom, proofid, current_time,
5423 preferred);
5424 }
5425 continue;
5426 }
5427
5428 if (inv.IsMsgTx()) {
5429 LOCK(cs_main);
5430 const TxId txid(inv.hash);
5431 const bool fAlreadyHave =
5432 AlreadyHaveTx(txid, /*include_reconsiderable=*/true);
5433 logInv(inv, fAlreadyHave);
5434
5435 AddKnownTx(*peer, txid);
5436 if (reject_tx_invs) {
5438 "transaction (%s) inv sent in violation of "
5439 "protocol, disconnecting peer=%d\n",
5440 txid.ToString(), pfrom.GetId());
5441 pfrom.fDisconnect = true;
5442 return;
5443 } else if (!fAlreadyHave &&
5444 !m_chainman.IsInitialBlockDownload()) {
5445 AddTxAnnouncement(pfrom, txid, current_time);
5446 }
5447
5448 continue;
5449 }
5450
5452 "Unknown inv type \"%s\" received from peer=%d\n",
5453 inv.ToString(), pfrom.GetId());
5454 }
5455
5456 if (best_block) {
5457 // If we haven't started initial headers-sync with this peer, then
5458 // consider sending a getheaders now. On initial startup, there's a
5459 // reliability vs bandwidth tradeoff, where we are only trying to do
5460 // initial headers sync with one peer at a time, with a long
5461 // timeout (at which point, if the sync hasn't completed, we will
5462 // disconnect the peer and then choose another). In the meantime,
5463 // as new blocks are found, we are willing to add one new peer per
5464 // block to sync with as well, to sync quicker in the case where
5465 // our initial peer is unresponsive (but less bandwidth than we'd
5466 // use if we turned on sync with all peers).
5467 LOCK(::cs_main);
5468 CNodeState &state{*Assert(State(pfrom.GetId()))};
5469 if (state.fSyncStarted ||
5470 (!peer->m_inv_triggered_getheaders_before_sync &&
5471 *best_block != m_last_block_inv_triggering_headers_sync)) {
5472 if (MaybeSendGetHeaders(
5473 pfrom, GetLocator(m_chainman.m_best_header), *peer)) {
5474 LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n",
5475 m_chainman.m_best_header->nHeight,
5476 best_block->ToString(), pfrom.GetId());
5477 }
5478 if (!state.fSyncStarted) {
5479 peer->m_inv_triggered_getheaders_before_sync = true;
5480 // Update the last block hash that triggered a new headers
5481 // sync, so that we don't turn on headers sync with more
5482 // than 1 new peer every new block.
5483 m_last_block_inv_triggering_headers_sync = *best_block;
5484 }
5485 }
5486 }
5487
5488 return;
5489 }
5490
5491 if (msg_type == NetMsgType::GETDATA) {
5492 std::vector<CInv> vInv;
5493 vRecv >> vInv;
5494 if (vInv.size() > MAX_INV_SZ) {
5495 Misbehaving(*peer,
5496 strprintf("getdata message size = %u", vInv.size()));
5497 return;
5498 }
5499
5500 LogPrint(BCLog::NET, "received getdata (%u invsz) peer=%d\n",
5501 vInv.size(), pfrom.GetId());
5502
5503 if (vInv.size() > 0) {
5504 LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n",
5505 vInv[0].ToString(), pfrom.GetId());
5506 }
5507
5508 {
5509 LOCK(peer->m_getdata_requests_mutex);
5510 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(),
5511 vInv.begin(), vInv.end());
5512 ProcessGetData(config, pfrom, *peer, interruptMsgProc);
5513 }
5514
5515 return;
5516 }
5517
5518 if (msg_type == NetMsgType::GETBLOCKS) {
5519 CBlockLocator locator;
5520 uint256 hashStop;
5521 vRecv >> locator >> hashStop;
5522
5523 if (locator.vHave.size() > MAX_LOCATOR_SZ) {
5525 "getblocks locator size %lld > %d, disconnect peer=%d\n",
5526 locator.vHave.size(), MAX_LOCATOR_SZ, pfrom.GetId());
5527 pfrom.fDisconnect = true;
5528 return;
5529 }
5530
5531 // We might have announced the currently-being-connected tip using a
5532 // compact block, which resulted in the peer sending a getblocks
5533 // request, which we would otherwise respond to without the new block.
5534 // To avoid this situation we simply verify that we are on our best
5535 // known chain now. This is super overkill, but we handle it better
5536 // for getheaders requests, and there are no known nodes which support
5537 // compact blocks but still use getblocks to request blocks.
5538 {
5539 std::shared_ptr<const CBlock> a_recent_block;
5540 {
5541 LOCK(m_most_recent_block_mutex);
5542 a_recent_block = m_most_recent_block;
5543 }
5545 if (!m_chainman.ActiveChainstate().ActivateBestChain(
5546 state, a_recent_block, m_avalanche)) {
5547 LogPrint(BCLog::NET, "failed to activate chain (%s)\n",
5548 state.ToString());
5549 }
5550 }
5551
5552 LOCK(cs_main);
5553
5554 // Find the last block the caller has in the main chain
5555 const CBlockIndex *pindex =
5556 m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
5557
5558 // Send the rest of the chain
5559 if (pindex) {
5560 pindex = m_chainman.ActiveChain().Next(pindex);
5561 }
5562 int nLimit = 500;
5563 LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n",
5564 (pindex ? pindex->nHeight : -1),
5565 hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit,
5566 pfrom.GetId());
5567 for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex)) {
5568 if (pindex->GetBlockHash() == hashStop) {
5569 LogPrint(BCLog::NET, " getblocks stopping at %d %s\n",
5570 pindex->nHeight, pindex->GetBlockHash().ToString());
5571 break;
5572 }
5573 // If pruning, don't inv blocks unless we have on disk and are
5574 // likely to still have for some reasonable time window (1 hour)
5575 // that block relay might require.
5576 const int nPrunedBlocksLikelyToHave =
5578 3600 / m_chainparams.GetConsensus().nPowTargetSpacing;
5579 if (m_chainman.m_blockman.IsPruneMode() &&
5580 (!pindex->nStatus.hasData() ||
5581 pindex->nHeight <= m_chainman.ActiveChain().Tip()->nHeight -
5582 nPrunedBlocksLikelyToHave)) {
5583 LogPrint(
5584 BCLog::NET,
5585 " getblocks stopping, pruned or too old block at %d %s\n",
5586 pindex->nHeight, pindex->GetBlockHash().ToString());
5587 break;
5588 }
5589 WITH_LOCK(
5590 peer->m_block_inv_mutex,
5591 peer->m_blocks_for_inv_relay.push_back(pindex->GetBlockHash()));
5592 if (--nLimit <= 0) {
5593 // When this block is requested, we'll send an inv that'll
5594 // trigger the peer to getblocks the next batch of inventory.
5595 LogPrint(BCLog::NET, " getblocks stopping at limit %d %s\n",
5596 pindex->nHeight, pindex->GetBlockHash().ToString());
5597 WITH_LOCK(peer->m_block_inv_mutex, {
5598 peer->m_continuation_block = pindex->GetBlockHash();
5599 });
5600 break;
5601 }
5602 }
5603 return;
5604 }
5605
5606 if (msg_type == NetMsgType::GETBLOCKTXN) {
5608 vRecv >> req;
5609
5610 std::shared_ptr<const CBlock> recent_block;
5611 {
5612 LOCK(m_most_recent_block_mutex);
5613 if (m_most_recent_block_hash == req.blockhash) {
5614 recent_block = m_most_recent_block;
5615 }
5616 // Unlock m_most_recent_block_mutex to avoid cs_main lock inversion
5617 }
5618 if (recent_block) {
5619 SendBlockTransactions(pfrom, *peer, *recent_block, req);
5620 return;
5621 }
5622
5623 FlatFilePos block_pos{};
5624 {
5625 LOCK(cs_main);
5626
5627 const CBlockIndex *pindex =
5628 m_chainman.m_blockman.LookupBlockIndex(req.blockhash);
5629 if (!pindex || !pindex->nStatus.hasData()) {
5630 LogPrint(
5631 BCLog::NET,
5632 "Peer %d sent us a getblocktxn for a block we don't have\n",
5633 pfrom.GetId());
5634 return;
5635 }
5636
5637 if (pindex->nHeight >=
5638 m_chainman.ActiveChain().Height() - MAX_BLOCKTXN_DEPTH) {
5639 block_pos = pindex->GetBlockPos();
5640 }
5641 }
5642
5643 if (!block_pos.IsNull()) {
5644 CBlock block;
5645 const bool ret{m_chainman.m_blockman.ReadBlock(block, block_pos)};
5646 // If height is above MAX_BLOCKTXN_DEPTH then this block cannot get
5647 // pruned after we release cs_main above, so this read should never
5648 // fail.
5649 assert(ret);
5650
5651 SendBlockTransactions(pfrom, *peer, block, req);
5652 return;
5653 }
5654
5655 // If an older block is requested (should never happen in practice,
5656 // but can happen in tests) send a block response instead of a
5657 // blocktxn response. Sending a full block response instead of a
5658 // small blocktxn response is preferable in the case where a peer
5659 // might maliciously send lots of getblocktxn requests to trigger
5660 // expensive disk reads, because it will require the peer to
5661 // actually receive all the data read from disk over the network.
5663 "Peer %d sent us a getblocktxn for a block > %i deep\n",
5664 pfrom.GetId(), MAX_BLOCKTXN_DEPTH);
5665 CInv inv;
5666 inv.type = MSG_BLOCK;
5667 inv.hash = req.blockhash;
5668 WITH_LOCK(peer->m_getdata_requests_mutex,
5669 peer->m_getdata_requests.push_back(inv));
5670 // The message processing loop will go around again (without pausing)
5671 // and we'll respond then (without cs_main)
5672 return;
5673 }
5674
5675 if (msg_type == NetMsgType::GETHEADERS) {
5676 CBlockLocator locator;
5677 BlockHash hashStop;
5678 vRecv >> locator >> hashStop;
5679
5680 if (locator.vHave.size() > MAX_LOCATOR_SZ) {
5682 "getheaders locator size %lld > %d, disconnect peer=%d\n",
5683 locator.vHave.size(), MAX_LOCATOR_SZ, pfrom.GetId());
5684 pfrom.fDisconnect = true;
5685 return;
5686 }
5687
5688 if (m_chainman.m_blockman.LoadingBlocks()) {
5689 LogPrint(
5690 BCLog::NET,
5691 "Ignoring getheaders from peer=%d while importing/reindexing\n",
5692 pfrom.GetId());
5693 return;
5694 }
5695
5696 LOCK(cs_main);
5697
5698 // Note that if we were to be on a chain that forks from the
5699 // checkpointed chain, then serving those headers to a peer that has
5700 // seen the checkpointed chain would cause that peer to disconnect us.
5701 // Requiring that our chainwork exceed the minimum chainwork is a
5702 // protection against being fed a bogus chain when we started up for
5703 // the first time and getting partitioned off the honest network for
5704 // serving that chain to others.
5705 if (m_chainman.ActiveTip() == nullptr ||
5706 (m_chainman.ActiveTip()->nChainWork <
5707 m_chainman.MinimumChainWork() &&
5710 "Ignoring getheaders from peer=%d because active chain "
5711 "has too little work; sending empty response\n",
5712 pfrom.GetId());
5713 // Just respond with an empty headers message, to tell the peer to
5714 // go away but not treat us as unresponsive.
5715 MakeAndPushMessage(pfrom, NetMsgType::HEADERS,
5716 std::vector<CBlock>());
5717 return;
5718 }
5719
5720 CNodeState *nodestate = State(pfrom.GetId());
5721 const CBlockIndex *pindex = nullptr;
5722 if (locator.IsNull()) {
5723 // If locator is null, return the hashStop block
5724 pindex = m_chainman.m_blockman.LookupBlockIndex(hashStop);
5725 if (!pindex) {
5726 return;
5727 }
5728
5729 if (!BlockRequestAllowed(pindex)) {
5731 "%s: ignoring request from peer=%i for old block "
5732 "header that isn't in the main chain\n",
5733 __func__, pfrom.GetId());
5734 return;
5735 }
5736 } else {
5737 // Find the last block the caller has in the main chain
5738 pindex =
5739 m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
5740 if (pindex) {
5741 pindex = m_chainman.ActiveChain().Next(pindex);
5742 }
5743 }
5744
5745 // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx
5746 // count at the end
5747 std::vector<CBlock> vHeaders;
5748 int nLimit = MAX_HEADERS_RESULTS;
5749 LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n",
5750 (pindex ? pindex->nHeight : -1),
5751 hashStop.IsNull() ? "end" : hashStop.ToString(),
5752 pfrom.GetId());
5753 for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex)) {
5754 vHeaders.push_back(pindex->GetBlockHeader());
5755 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop) {
5756 break;
5757 }
5758 }
5759 // pindex can be nullptr either if we sent
5760 // m_chainman.ActiveChain().Tip() OR if our peer has
5761 // m_chainman.ActiveChain().Tip() (and thus we are sending an empty
5762 // headers message). In both cases it's safe to update
5763 // pindexBestHeaderSent to be our tip.
5764 //
5765 // It is important that we simply reset the BestHeaderSent value here,
5766 // and not max(BestHeaderSent, newHeaderSent). We might have announced
5767 // the currently-being-connected tip using a compact block, which
5768 // resulted in the peer sending a headers request, which we respond to
5769 // without the new block. By resetting the BestHeaderSent, we ensure we
5770 // will re-announce the new block via headers (or compact blocks again)
5771 // in the SendMessages logic.
5772 nodestate->pindexBestHeaderSent =
5773 pindex ? pindex : m_chainman.ActiveChain().Tip();
5774 MakeAndPushMessage(pfrom, NetMsgType::HEADERS, vHeaders);
5775 return;
5776 }
5777
5778 if (msg_type == NetMsgType::TX) {
5779 if (RejectIncomingTxs(pfrom)) {
5781 "transaction sent in violation of protocol peer=%d\n",
5782 pfrom.GetId());
5783 pfrom.fDisconnect = true;
5784 return;
5785 }
5786
5787 // Stop processing the transaction early if we are still in IBD since we
5788 // don't have enough information to validate it yet. Sending unsolicited
5789 // transactions is not considered a protocol violation, so don't punish
5790 // the peer.
5791 if (m_chainman.IsInitialBlockDownload()) {
5792 return;
5793 }
5794
5795 CTransactionRef ptx;
5796 vRecv >> ptx;
5797 const CTransaction &tx = *ptx;
5798 const TxId &txid = tx.GetId();
5799 AddKnownTx(*peer, txid);
5800
5801 {
5802 LOCK(cs_main);
5803
5804 m_txrequest.ReceivedResponse(pfrom.GetId(), txid);
5805
5806 if (AlreadyHaveTx(txid, /*include_reconsiderable=*/true)) {
5808 // Always relay transactions received from peers with
5809 // forcerelay permission, even if they were already in the
5810 // mempool, allowing the node to function as a gateway for
5811 // nodes hidden behind it.
5812 if (!m_mempool.exists(tx.GetId())) {
5813 LogPrintf(
5814 "Not relaying non-mempool transaction %s from "
5815 "forcerelay peer=%d\n",
5816 tx.GetId().ToString(), pfrom.GetId());
5817 } else {
5818 LogPrintf("Force relaying tx %s from peer=%d\n",
5819 tx.GetId().ToString(), pfrom.GetId());
5820 RelayTransaction(tx.GetId());
5821 }
5822 }
5823
5824 if (m_recent_rejects_package_reconsiderable.contains(txid)) {
5825 // When a transaction is already in
5826 // m_recent_rejects_package_reconsiderable, we shouldn't
5827 // submit it by itself again. However, look for a matching
5828 // child in the orphanage, as it is possible that they
5829 // succeed as a package.
5830 LogPrint(
5832 "found tx %s in reconsiderable rejects, looking for "
5833 "child in orphanage\n",
5834 txid.ToString());
5835 if (auto package_to_validate{
5836 Find1P1CPackage(ptx, pfrom.GetId())}) {
5837 const auto package_result{ProcessNewPackage(
5838 m_chainman.ActiveChainstate(), m_mempool,
5839 package_to_validate->m_txns,
5840 /*test_accept=*/false)};
5842 "package evaluation for %s: %s (%s)\n",
5843 package_to_validate->ToString(),
5844 package_result.m_state.IsValid()
5845 ? "package accepted"
5846 : "package rejected",
5847 package_result.m_state.ToString());
5848 ProcessPackageResult(package_to_validate.value(),
5849 package_result);
5850 }
5851 }
5852 // If a tx is detected by m_recent_rejects it is ignored.
5853 // Because we haven't submitted the tx to our mempool, we won't
5854 // have computed a DoS score for it or determined exactly why we
5855 // consider it invalid.
5856 //
5857 // This means we won't penalize any peer subsequently relaying a
5858 // DoSy tx (even if we penalized the first peer who gave it to
5859 // us) because we have to account for m_recent_rejects showing
5860 // false positives. In other words, we shouldn't penalize a peer
5861 // if we aren't *sure* they submitted a DoSy tx.
5862 //
5863 // Note that m_recent_rejects doesn't just record DoSy or
5864 // invalid transactions, but any tx not accepted by the mempool,
5865 // which may be due to node policy (vs. consensus). So we can't
5866 // blanket penalize a peer simply for relaying a tx that our
5867 // m_recent_rejects has caught, regardless of false positives.
5868 return;
5869 }
5870
5871 const MempoolAcceptResult result =
5872 m_chainman.ProcessTransaction(ptx);
5873 const TxValidationState &state = result.m_state;
5874
5875 if (result.m_result_type ==
5877 ProcessValidTx(pfrom.GetId(), ptx);
5878 pfrom.m_last_tx_time = GetTime<std::chrono::seconds>();
5879 } else if (state.GetResult() ==
5881 // It may be the case that the orphans parents have all been
5882 // rejected.
5883 bool fRejectedParents = false;
5884
5885 // Deduplicate parent txids, so that we don't have to loop over
5886 // the same parent txid more than once down below.
5887 std::vector<TxId> unique_parents;
5888 unique_parents.reserve(tx.vin.size());
5889 for (const CTxIn &txin : tx.vin) {
5890 // We start with all parents, and then remove duplicates
5891 // below.
5892 unique_parents.push_back(txin.prevout.GetTxId());
5893 }
5894 std::sort(unique_parents.begin(), unique_parents.end());
5895 unique_parents.erase(
5896 std::unique(unique_parents.begin(), unique_parents.end()),
5897 unique_parents.end());
5898
5899 // Distinguish between parents in m_recent_rejects and
5900 // m_recent_rejects_package_reconsiderable. We can tolerate
5901 // having up to 1 parent in
5902 // m_recent_rejects_package_reconsiderable since we submit 1p1c
5903 // packages. However, fail immediately if any are in
5904 // m_recent_rejects.
5905 std::optional<TxId> rejected_parent_reconsiderable;
5906 for (const TxId &parent_txid : unique_parents) {
5907 if (m_recent_rejects.contains(parent_txid)) {
5908 fRejectedParents = true;
5909 break;
5910 }
5911
5912 if (m_recent_rejects_package_reconsiderable.contains(
5913 parent_txid) &&
5914 !m_mempool.exists(parent_txid)) {
5915 // More than 1 parent in
5916 // m_recent_rejects_package_reconsiderable:
5917 // 1p1c will not be sufficient to accept this package,
5918 // so just give up here.
5919 if (rejected_parent_reconsiderable.has_value()) {
5920 fRejectedParents = true;
5921 break;
5922 }
5923 rejected_parent_reconsiderable = parent_txid;
5924 }
5925 }
5926 if (!fRejectedParents) {
5927 const auto current_time{
5928 GetTime<std::chrono::microseconds>()};
5929
5930 for (const TxId &parent_txid : unique_parents) {
5931 // FIXME: MSG_TX should use a TxHash, not a TxId.
5932 AddKnownTx(*peer, parent_txid);
5933 // Exclude m_recent_rejects_package_reconsiderable: the
5934 // missing parent may have been previously rejected for
5935 // being too low feerate. This orphan might CPFP it.
5936 if (!AlreadyHaveTx(parent_txid,
5937 /*include_reconsiderable=*/false)) {
5938 AddTxAnnouncement(pfrom, parent_txid, current_time);
5939 }
5940 }
5941
5942 // NO_THREAD_SAFETY_ANALYSIS because we can't annotate for
5943 // g_msgproc_mutex
5944 if (unsigned int nEvicted =
5945 m_mempool.withOrphanage(
5946 [&](TxOrphanage &orphanage)
5948 if (orphanage.AddTx(ptx,
5949 pfrom.GetId())) {
5950 AddToCompactExtraTransactions(ptx);
5951 }
5952 return orphanage.LimitTxs(
5953 m_opts.max_orphan_txs, m_rng);
5954 }) > 0) {
5956 "orphanage overflow, removed %u tx\n",
5957 nEvicted);
5958 }
5959
5960 // Once added to the orphan pool, a tx is considered
5961 // AlreadyHave, and we shouldn't request it anymore.
5962 m_txrequest.ForgetInvId(tx.GetId());
5963
5964 } else {
5966 "not keeping orphan with rejected parents %s\n",
5967 tx.GetId().ToString());
5968 // We will continue to reject this tx since it has rejected
5969 // parents so avoid re-requesting it from other peers.
5970 m_recent_rejects.insert(tx.GetId());
5971 m_txrequest.ForgetInvId(tx.GetId());
5972 }
5973 }
5974 if (state.IsInvalid()) {
5975 ProcessInvalidTx(pfrom.GetId(), ptx, state,
5976 /*maybe_add_extra_compact_tx=*/true);
5977 }
5978 // When a transaction fails for TX_PACKAGE_RECONSIDERABLE, look for
5979 // a matching child in the orphanage, as it is possible that they
5980 // succeed as a package.
5981 if (state.GetResult() ==
5983 LogPrint(
5985 "tx %s failed but reconsiderable, looking for child in "
5986 "orphanage\n",
5987 txid.ToString());
5988 if (auto package_to_validate{
5989 Find1P1CPackage(ptx, pfrom.GetId())}) {
5990 const auto package_result{ProcessNewPackage(
5991 m_chainman.ActiveChainstate(), m_mempool,
5992 package_to_validate->m_txns, /*test_accept=*/false)};
5994 "package evaluation for %s: %s (%s)\n",
5995 package_to_validate->ToString(),
5996 package_result.m_state.IsValid()
5997 ? "package accepted"
5998 : "package rejected",
5999 package_result.m_state.ToString());
6000 ProcessPackageResult(package_to_validate.value(),
6001 package_result);
6002 }
6003 }
6004
6005 if (state.GetResult() ==
6007 // Once added to the conflicting pool, a tx is considered
6008 // AlreadyHave, and we shouldn't request it anymore.
6009 m_txrequest.ForgetInvId(tx.GetId());
6010
6011 unsigned int nEvicted{0};
6012 // NO_THREAD_SAFETY_ANALYSIS because of g_msgproc_mutex required
6013 // in the lambda for m_rng
6014 m_mempool.withConflicting(
6015 [&](TxConflicting &conflicting) NO_THREAD_SAFETY_ANALYSIS {
6016 conflicting.AddTx(ptx, pfrom.GetId());
6017 nEvicted = conflicting.LimitTxs(
6018 m_opts.max_conflicting_txs, m_rng);
6019 });
6020
6021 if (nEvicted > 0) {
6023 "conflicting pool overflow, removed %u tx\n",
6024 nEvicted);
6025 }
6026 }
6027 } // Release cs_main
6028
6029 return;
6030 }
6031
6032 if (msg_type == NetMsgType::CMPCTBLOCK) {
6033 // Ignore cmpctblock received while importing
6034 if (m_chainman.m_blockman.LoadingBlocks()) {
6036 "Unexpected cmpctblock message received from peer %d\n",
6037 pfrom.GetId());
6038 return;
6039 }
6040
6041 CBlockHeaderAndShortTxIDs cmpctblock;
6042 try {
6043 vRecv >> cmpctblock;
6044 } catch (std::ios_base::failure &e) {
6045 // This block has non contiguous or overflowing indexes
6046 Misbehaving(*peer, "cmpctblock-bad-indexes");
6047 return;
6048 }
6049
6050 bool received_new_header = false;
6051 const auto blockhash = cmpctblock.header.GetHash();
6052
6053 {
6054 LOCK(cs_main);
6055
6056 const CBlockIndex *prev_block =
6057 m_chainman.m_blockman.LookupBlockIndex(
6058 cmpctblock.header.hashPrevBlock);
6059 if (!prev_block) {
6060 // Doesn't connect (or is genesis), instead of DoSing in
6061 // AcceptBlockHeader, request deeper headers
6062 if (!m_chainman.IsInitialBlockDownload()) {
6063 MaybeSendGetHeaders(
6064 pfrom, GetLocator(m_chainman.m_best_header), *peer);
6065 }
6066 return;
6067 }
6068 if (prev_block->nChainWork +
6069 CalculateHeadersWork({cmpctblock.header}) <
6070 GetAntiDoSWorkThreshold()) {
6071 // If we get a low-work header in a compact block, we can ignore
6072 // it.
6074 "Ignoring low-work compact block from peer %d\n",
6075 pfrom.GetId());
6076 return;
6077 }
6078
6079 if (!m_chainman.m_blockman.LookupBlockIndex(blockhash)) {
6080 received_new_header = true;
6081 }
6082 }
6083
6084 const CBlockIndex *pindex = nullptr;
6086 if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header},
6087 /*min_pow_checked=*/true, state,
6088 &pindex)) {
6089 if (state.IsInvalid()) {
6090 MaybePunishNodeForBlock(pfrom.GetId(), state,
6091 /*via_compact_block*/ true,
6092 "invalid header via cmpctblock");
6093 return;
6094 }
6095 }
6096
6097 if (received_new_header) {
6098 LogInfo("Saw new cmpctblock header hash=%s peer=%d\n",
6099 blockhash.ToString(), pfrom.GetId());
6100 }
6101
6102 // When we succeed in decoding a block's txids from a cmpctblock
6103 // message we typically jump to the BLOCKTXN handling code, with a
6104 // dummy (empty) BLOCKTXN message, to re-use the logic there in
6105 // completing processing of the putative block (without cs_main).
6106 bool fProcessBLOCKTXN = false;
6107 DataStream blockTxnMsg{};
6108
6109 // If we end up treating this as a plain headers message, call that as
6110 // well
6111 // without cs_main.
6112 bool fRevertToHeaderProcessing = false;
6113
6114 // Keep a CBlock for "optimistic" compactblock reconstructions (see
6115 // below)
6116 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
6117 bool fBlockReconstructed = false;
6118
6119 {
6120 LOCK(cs_main);
6121 // If AcceptBlockHeader returned true, it set pindex
6122 assert(pindex);
6123 UpdateBlockAvailability(pfrom.GetId(), pindex->GetBlockHash());
6124
6125 CNodeState *nodestate = State(pfrom.GetId());
6126
6127 // If this was a new header with more work than our tip, update the
6128 // peer's last block announcement time
6129 if (received_new_header &&
6130 pindex->nChainWork >
6131 m_chainman.ActiveChain().Tip()->nChainWork) {
6132 nodestate->m_last_block_announcement = GetTime();
6133 }
6134
6135 if (pindex->nStatus.hasData()) {
6136 // Nothing to do here
6137 return;
6138 }
6139
6140 auto range_flight =
6141 mapBlocksInFlight.equal_range(pindex->GetBlockHash());
6142 size_t already_in_flight =
6143 std::distance(range_flight.first, range_flight.second);
6144 bool requested_block_from_this_peer{false};
6145
6146 // Multimap ensures ordering of outstanding requests. It's either
6147 // empty or first in line.
6148 bool first_in_flight =
6149 already_in_flight == 0 ||
6150 (range_flight.first->second.first == pfrom.GetId());
6151
6152 while (range_flight.first != range_flight.second) {
6153 if (range_flight.first->second.first == pfrom.GetId()) {
6154 requested_block_from_this_peer = true;
6155 break;
6156 }
6157 range_flight.first++;
6158 }
6159
6160 if (pindex->nChainWork <=
6161 m_chainman.ActiveChain()
6162 .Tip()
6163 ->nChainWork || // We know something better
6164 pindex->nTx != 0) {
6165 // We had this block at some point, but pruned it
6166 if (requested_block_from_this_peer) {
6167 // We requested this block for some reason, but our mempool
6168 // will probably be useless so we just grab the block via
6169 // normal getdata.
6170 std::vector<CInv> vInv(1);
6171 vInv[0] = CInv(MSG_BLOCK, blockhash);
6172 MakeAndPushMessage(pfrom, NetMsgType::GETDATA, vInv);
6173 }
6174 return;
6175 }
6176
6177 // If we're not close to tip yet, give up and let parallel block
6178 // fetch work its magic.
6179 if (!already_in_flight && !CanDirectFetch()) {
6180 return;
6181 }
6182
6183 // We want to be a bit conservative just to be extra careful about
6184 // DoS possibilities in compact block processing...
6185 if (pindex->nHeight <= m_chainman.ActiveChain().Height() + 2) {
6186 if ((already_in_flight < MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK &&
6187 nodestate->vBlocksInFlight.size() <
6189 requested_block_from_this_peer) {
6190 std::list<QueuedBlock>::iterator *queuedBlockIt = nullptr;
6191 if (!BlockRequested(config, pfrom.GetId(), *pindex,
6192 &queuedBlockIt)) {
6193 if (!(*queuedBlockIt)->partialBlock) {
6194 (*queuedBlockIt)
6195 ->partialBlock.reset(
6196 new PartiallyDownloadedBlock(config,
6197 &m_mempool));
6198 } else {
6199 // The block was already in flight using compact
6200 // blocks from the same peer.
6201 LogPrint(BCLog::NET, "Peer sent us compact block "
6202 "we were already syncing!\n");
6203 return;
6204 }
6205 }
6206
6207 PartiallyDownloadedBlock &partialBlock =
6208 *(*queuedBlockIt)->partialBlock;
6209 ReadStatus status =
6210 partialBlock.InitData(cmpctblock, vExtraTxnForCompact);
6211 if (status == READ_STATUS_INVALID) {
6212 // Reset in-flight state in case Misbehaving does not
6213 // result in a disconnect
6214 RemoveBlockRequest(pindex->GetBlockHash(),
6215 pfrom.GetId());
6216 Misbehaving(*peer, "invalid compact block");
6217 return;
6218 } else if (status == READ_STATUS_FAILED) {
6219 if (first_in_flight) {
6220 // Duplicate txindices, the block is now in-flight,
6221 // so just request it.
6222 std::vector<CInv> vInv(1);
6223 vInv[0] = CInv(MSG_BLOCK, blockhash);
6224 MakeAndPushMessage(pfrom, NetMsgType::GETDATA,
6225 vInv);
6226 } else {
6227 // Give up for this peer and wait for other peer(s)
6228 RemoveBlockRequest(pindex->GetBlockHash(),
6229 pfrom.GetId());
6230 }
6231 return;
6232 }
6233
6235 for (size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {
6236 if (!partialBlock.IsTxAvailable(i)) {
6237 req.indices.push_back(i);
6238 }
6239 }
6240 if (req.indices.empty()) {
6241 // Dirty hack to jump to BLOCKTXN code (TODO: move
6242 // message handling into their own functions)
6244 txn.blockhash = blockhash;
6245 blockTxnMsg << txn;
6246 fProcessBLOCKTXN = true;
6247 } else if (first_in_flight) {
6248 // We will try to round-trip any compact blocks we get
6249 // on failure, as long as it's first...
6250 req.blockhash = pindex->GetBlockHash();
6251 MakeAndPushMessage(pfrom, NetMsgType::GETBLOCKTXN, req);
6252 } else if (pfrom.m_bip152_highbandwidth_to &&
6253 (!pfrom.IsInboundConn() ||
6254 IsBlockRequestedFromOutbound(blockhash) ||
6255 already_in_flight <
6257 // ... or it's a hb relay peer and:
6258 // - peer is outbound, or
6259 // - we already have an outbound attempt in flight (so
6260 // we'll take what we can get), or
6261 // - it's not the final parallel download slot (which we
6262 // may reserve for first outbound)
6263 req.blockhash = pindex->GetBlockHash();
6264 MakeAndPushMessage(pfrom, NetMsgType::GETBLOCKTXN, req);
6265 } else {
6266 // Give up for this peer and wait for other peer(s)
6267 RemoveBlockRequest(pindex->GetBlockHash(),
6268 pfrom.GetId());
6269 }
6270 } else {
6271 // This block is either already in flight from a different
6272 // peer, or this peer has too many blocks outstanding to
6273 // download from. Optimistically try to reconstruct anyway
6274 // since we might be able to without any round trips.
6275 PartiallyDownloadedBlock tempBlock(config, &m_mempool);
6276 ReadStatus status =
6277 tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
6278 if (status != READ_STATUS_OK) {
6279 // TODO: don't ignore failures
6280 return;
6281 }
6282 std::vector<CTransactionRef> dummy;
6283 status = tempBlock.FillBlock(*pblock, dummy);
6284 if (status == READ_STATUS_OK) {
6285 fBlockReconstructed = true;
6286 }
6287 }
6288 } else {
6289 if (requested_block_from_this_peer) {
6290 // We requested this block, but its far into the future, so
6291 // our mempool will probably be useless - request the block
6292 // normally.
6293 std::vector<CInv> vInv(1);
6294 vInv[0] = CInv(MSG_BLOCK, blockhash);
6295 MakeAndPushMessage(pfrom, NetMsgType::GETDATA, vInv);
6296 return;
6297 } else {
6298 // If this was an announce-cmpctblock, we want the same
6299 // treatment as a header message.
6300 fRevertToHeaderProcessing = true;
6301 }
6302 }
6303 } // cs_main
6304
6305 if (fProcessBLOCKTXN) {
6306 return ProcessMessage(config, pfrom, NetMsgType::BLOCKTXN,
6307 blockTxnMsg, time_received, interruptMsgProc);
6308 }
6309
6310 if (fRevertToHeaderProcessing) {
6311 // Headers received from HB compact block peers are permitted to be
6312 // relayed before full validation (see BIP 152), so we don't want to
6313 // disconnect the peer if the header turns out to be for an invalid
6314 // block. Note that if a peer tries to build on an invalid chain,
6315 // that will be detected and the peer will be banned.
6316 return ProcessHeadersMessage(config, pfrom, *peer,
6317 {cmpctblock.header},
6318 /*via_compact_block=*/true);
6319 }
6320
6321 if (fBlockReconstructed) {
6322 // If we got here, we were able to optimistically reconstruct a
6323 // block that is in flight from some other peer.
6324 {
6325 LOCK(cs_main);
6326 mapBlockSource.emplace(pblock->GetHash(),
6327 std::make_pair(pfrom.GetId(), false));
6328 }
6329 // Setting force_processing to true means that we bypass some of
6330 // our anti-DoS protections in AcceptBlock, which filters
6331 // unrequested blocks that might be trying to waste our resources
6332 // (eg disk space). Because we only try to reconstruct blocks when
6333 // we're close to caught up (via the CanDirectFetch() requirement
6334 // above, combined with the behavior of not requesting blocks until
6335 // we have a chain with at least the minimum chain work), and we
6336 // ignore compact blocks with less work than our tip, it is safe to
6337 // treat reconstructed compact blocks as having been requested.
6338 ProcessBlock(config, pfrom, pblock, /*force_processing=*/true,
6339 /*min_pow_checked=*/true);
6340 // hold cs_main for CBlockIndex::IsValid()
6341 LOCK(cs_main);
6342 if (pindex->IsValid(BlockValidity::TRANSACTIONS)) {
6343 // Clear download state for this block, which is in process from
6344 // some other peer. We do this after calling. ProcessNewBlock so
6345 // that a malleated cmpctblock announcement can't be used to
6346 // interfere with block relay.
6347 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
6348 }
6349 }
6350 return;
6351 }
6352
6353 if (msg_type == NetMsgType::BLOCKTXN) {
6354 // Ignore blocktxn received while importing
6355 if (m_chainman.m_blockman.LoadingBlocks()) {
6357 "Unexpected blocktxn message received from peer %d\n",
6358 pfrom.GetId());
6359 return;
6360 }
6361
6362 BlockTransactions resp;
6363 vRecv >> resp;
6364
6365 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
6366 bool fBlockRead = false;
6367 {
6368 LOCK(cs_main);
6369
6370 auto range_flight = mapBlocksInFlight.equal_range(resp.blockhash);
6371 size_t already_in_flight =
6372 std::distance(range_flight.first, range_flight.second);
6373 bool requested_block_from_this_peer{false};
6374
6375 // Multimap ensures ordering of outstanding requests. It's either
6376 // empty or first in line.
6377 bool first_in_flight =
6378 already_in_flight == 0 ||
6379 (range_flight.first->second.first == pfrom.GetId());
6380
6381 while (range_flight.first != range_flight.second) {
6382 auto [node_id, block_it] = range_flight.first->second;
6383 if (node_id == pfrom.GetId() && block_it->partialBlock) {
6384 requested_block_from_this_peer = true;
6385 break;
6386 }
6387 range_flight.first++;
6388 }
6389
6390 if (!requested_block_from_this_peer) {
6392 "Peer %d sent us block transactions for block "
6393 "we weren't expecting\n",
6394 pfrom.GetId());
6395 return;
6396 }
6397
6398 PartiallyDownloadedBlock &partialBlock =
6399 *range_flight.first->second.second->partialBlock;
6400 ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
6401 if (status == READ_STATUS_INVALID) {
6402 // Reset in-flight state in case of Misbehaving does not
6403 // result in a disconnect.
6404 RemoveBlockRequest(resp.blockhash, pfrom.GetId());
6405 Misbehaving(
6406 *peer,
6407 "invalid compact block/non-matching block transactions");
6408 return;
6409 } else if (status == READ_STATUS_FAILED) {
6410 if (first_in_flight) {
6411 // Might have collided, fall back to getdata now :(
6412 std::vector<CInv> invs;
6413 invs.push_back(CInv(MSG_BLOCK, resp.blockhash));
6414 MakeAndPushMessage(pfrom, NetMsgType::GETDATA, invs);
6415 } else {
6416 RemoveBlockRequest(resp.blockhash, pfrom.GetId());
6417 LogPrint(
6418 BCLog::NET,
6419 "Peer %d sent us a compact block but it failed to "
6420 "reconstruct, waiting on first download to complete\n",
6421 pfrom.GetId());
6422 return;
6423 }
6424 } else {
6425 // Block is either okay, or possibly we received
6426 // READ_STATUS_CHECKBLOCK_FAILED.
6427 // Note that CheckBlock can only fail for one of a few reasons:
6428 // 1. bad-proof-of-work (impossible here, because we've already
6429 // accepted the header)
6430 // 2. merkleroot doesn't match the transactions given (already
6431 // caught in FillBlock with READ_STATUS_FAILED, so
6432 // impossible here)
6433 // 3. the block is otherwise invalid (eg invalid coinbase,
6434 // block is too big, too many sigChecks, etc).
6435 // So if CheckBlock failed, #3 is the only possibility.
6436 // Under BIP 152, we don't DoS-ban unless proof of work is
6437 // invalid (we don't require all the stateless checks to have
6438 // been run). This is handled below, so just treat this as
6439 // though the block was successfully read, and rely on the
6440 // handling in ProcessNewBlock to ensure the block index is
6441 // updated, etc.
6442
6443 // it is now an empty pointer
6444 RemoveBlockRequest(resp.blockhash, pfrom.GetId());
6445 fBlockRead = true;
6446 // mapBlockSource is used for potentially punishing peers and
6447 // updating which peers send us compact blocks, so the race
6448 // between here and cs_main in ProcessNewBlock is fine.
6449 // BIP 152 permits peers to relay compact blocks after
6450 // validating the header only; we should not punish peers
6451 // if the block turns out to be invalid.
6452 mapBlockSource.emplace(resp.blockhash,
6453 std::make_pair(pfrom.GetId(), false));
6454 }
6455 } // Don't hold cs_main when we call into ProcessNewBlock
6456 if (fBlockRead) {
6457 // Since we requested this block (it was in mapBlocksInFlight),
6458 // force it to be processed, even if it would not be a candidate for
6459 // new tip (missing previous block, chain not long enough, etc)
6460 // This bypasses some anti-DoS logic in AcceptBlock (eg to prevent
6461 // disk-space attacks), but this should be safe due to the
6462 // protections in the compact block handler -- see related comment
6463 // in compact block optimistic reconstruction handling.
6464 ProcessBlock(config, pfrom, pblock, /*force_processing=*/true,
6465 /*min_pow_checked=*/true);
6466 }
6467 return;
6468 }
6469
6470 if (msg_type == NetMsgType::HEADERS) {
6471 // Ignore headers received while importing
6472 if (m_chainman.m_blockman.LoadingBlocks()) {
6474 "Unexpected headers message received from peer %d\n",
6475 pfrom.GetId());
6476 return;
6477 }
6478
6479 std::vector<CBlockHeader> headers;
6480
6481 // Bypass the normal CBlock deserialization, as we don't want to risk
6482 // deserializing 2000 full blocks.
6483 unsigned int nCount = ReadCompactSize(vRecv);
6484 if (nCount > MAX_HEADERS_RESULTS) {
6485 Misbehaving(*peer,
6486 strprintf("too-many-headers: headers message size = %u",
6487 nCount));
6488 return;
6489 }
6490 headers.resize(nCount);
6491 for (unsigned int n = 0; n < nCount; n++) {
6492 vRecv >> headers[n];
6493 // Ignore tx count; assume it is 0.
6494 ReadCompactSize(vRecv);
6495 }
6496
6497 ProcessHeadersMessage(config, pfrom, *peer, std::move(headers),
6498 /*via_compact_block=*/false);
6499
6500 // Check if the headers presync progress needs to be reported to
6501 // validation. This needs to be done without holding the
6502 // m_headers_presync_mutex lock.
6503 if (m_headers_presync_should_signal.exchange(false)) {
6504 HeadersPresyncStats stats;
6505 {
6506 LOCK(m_headers_presync_mutex);
6507 auto it =
6508 m_headers_presync_stats.find(m_headers_presync_bestpeer);
6509 if (it != m_headers_presync_stats.end()) {
6510 stats = it->second;
6511 }
6512 }
6513 if (stats.second) {
6514 m_chainman.ReportHeadersPresync(
6515 stats.first, stats.second->first, stats.second->second);
6516 }
6517 }
6518
6519 return;
6520 }
6521
6522 if (msg_type == NetMsgType::BLOCK) {
6523 // Ignore block received while importing
6524 if (m_chainman.m_blockman.LoadingBlocks()) {
6526 "Unexpected block message received from peer %d\n",
6527 pfrom.GetId());
6528 return;
6529 }
6530
6531 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
6532 vRecv >> *pblock;
6533
6534 LogPrint(BCLog::NET, "received block %s peer=%d\n",
6535 pblock->GetHash().ToString(), pfrom.GetId());
6536
6537 const CBlockIndex *prev_block{
6538 WITH_LOCK(m_chainman.GetMutex(),
6539 return m_chainman.m_blockman.LookupBlockIndex(
6540 pblock->hashPrevBlock))};
6541
6542 if (IsBlockMutated(/*block=*/*pblock)) {
6544 "Received mutated block from peer=%d\n", peer->m_id);
6545 Misbehaving(*peer, "mutated block");
6547 RemoveBlockRequest(pblock->GetHash(), peer->m_id));
6548 return;
6549 }
6550
6551 // Process all blocks from whitelisted peers, even if not requested,
6552 // unless we're still syncing with the network. Such an unrequested
6553 // block may still be processed, subject to the conditions in
6554 // AcceptBlock().
6555 bool forceProcessing = pfrom.HasPermission(NetPermissionFlags::NoBan) &&
6556 !m_chainman.IsInitialBlockDownload();
6557 const BlockHash hash = pblock->GetHash();
6558 bool min_pow_checked = false;
6559 {
6560 LOCK(cs_main);
6561 // Always process the block if we requested it, since we may
6562 // need it even when it's not a candidate for a new best tip.
6563 forceProcessing = IsBlockRequested(hash);
6564 RemoveBlockRequest(hash, pfrom.GetId());
6565 // mapBlockSource is only used for punishing peers and setting
6566 // which peers send us compact blocks, so the race between here and
6567 // cs_main in ProcessNewBlock is fine.
6568 mapBlockSource.emplace(hash, std::make_pair(pfrom.GetId(), true));
6569
6570 // Check work on this block against our anti-dos thresholds.
6571 if (prev_block &&
6572 prev_block->nChainWork +
6573 CalculateHeadersWork({pblock->GetBlockHeader()}) >=
6574 GetAntiDoSWorkThreshold()) {
6575 min_pow_checked = true;
6576 }
6577 }
6578 ProcessBlock(config, pfrom, pblock, forceProcessing, min_pow_checked);
6579 return;
6580 }
6581
6582 if (msg_type == NetMsgType::AVAHELLO) {
6583 if (!m_avalanche) {
6584 return;
6585 }
6586 {
6588 if (pfrom.m_avalanche_pubkey.has_value()) {
6589 LogPrint(
6591 "Ignoring avahello from peer %d: already in our node set\n",
6592 pfrom.GetId());
6593 return;
6594 }
6595
6596 avalanche::Delegation delegation;
6597 vRecv >> delegation;
6598
6599 // A delegation with an all zero limited id indicates that the peer
6600 // has no proof, so we're done.
6601 if (delegation.getLimitedProofId() != uint256::ZERO) {
6603 CPubKey pubkey;
6604 if (!delegation.verify(state, pubkey)) {
6605 Misbehaving(*peer, "invalid-delegation");
6606 return;
6607 }
6608 pfrom.m_avalanche_pubkey = std::move(pubkey);
6609
6610 HashWriter sighasher{};
6611 sighasher << delegation.getId();
6612 sighasher << pfrom.nRemoteHostNonce;
6613 sighasher << pfrom.GetLocalNonce();
6614 sighasher << pfrom.nRemoteExtraEntropy;
6615 sighasher << pfrom.GetLocalExtraEntropy();
6616
6618 vRecv >> sig;
6619 if (!(*pfrom.m_avalanche_pubkey)
6620 .VerifySchnorr(sighasher.GetHash(), sig)) {
6621 Misbehaving(*peer, "invalid-avahello-signature");
6622 return;
6623 }
6624
6625 // If we don't know this proof already, add it to the tracker so
6626 // it can be requested.
6627 const avalanche::ProofId proofid(delegation.getProofId());
6628 if (!AlreadyHaveProof(proofid)) {
6629 const bool preferred = isPreferredDownloadPeer(pfrom);
6630 LOCK(cs_proofrequest);
6631 AddProofAnnouncement(pfrom, proofid,
6632 GetTime<std::chrono::microseconds>(),
6633 preferred);
6634 }
6635
6636 uint32_t max_elements{AVALANCHE_MAX_ELEMENT_POLL_LEGACY};
6637 if (pfrom.GetCommonVersion() >=
6639 !vRecv.empty()) {
6640 vRecv >> max_elements;
6641 // max_elements below AVALANCHE_MAX_ELEMENT_POLL_LEGACY is
6642 // invalid
6643 if (max_elements < AVALANCHE_MAX_ELEMENT_POLL_LEGACY) {
6644 Misbehaving(*peer, "avahello-max-elements-too-low");
6645 return;
6646 }
6647 }
6648
6649 // Don't check the return value. If it fails we probably don't
6650 // know about the proof yet.
6651 m_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
6652 return pm.addNode(pfrom.GetId(), proofid, max_elements);
6653 });
6654 }
6655
6656 pfrom.m_avalanche_enabled = true;
6657 }
6658
6659 // Send getavaaddr and getavaproofs to our avalanche outbound or
6660 // manual connections
6661 if (!pfrom.IsInboundConn()) {
6662 MakeAndPushMessage(pfrom, NetMsgType::GETAVAADDR);
6663 WITH_LOCK(peer->m_addr_token_bucket_mutex,
6664 peer->m_addr_token_bucket += m_opts.max_addr_to_send);
6665
6666 if (peer->m_proof_relay && !m_chainman.IsInitialBlockDownload()) {
6667 MakeAndPushMessage(pfrom, NetMsgType::GETAVAPROOFS);
6668 peer->m_proof_relay->compactproofs_requested = true;
6669 }
6670 }
6671
6672 return;
6673 }
6674
6675 if (msg_type == NetMsgType::AVAPOLL) {
6676 if (!m_avalanche) {
6677 return;
6678 }
6679 const auto now = Now<SteadyMilliseconds>();
6680
6681 const auto last_poll = pfrom.m_last_poll;
6682 pfrom.m_last_poll = now;
6683
6684 if (now <
6685 last_poll + std::chrono::milliseconds(m_opts.avalanche_cooldown)) {
6687 "Ignoring repeated avapoll from peer %d: cooldown not "
6688 "elapsed\n",
6689 pfrom.GetId());
6690 return;
6691 }
6692
6693 const bool quorum_established = m_avalanche->isQuorumEstablished();
6694
6695 uint64_t round;
6696 Unserialize(vRecv, round);
6697
6698 unsigned int nCount = ReadCompactSize(vRecv);
6699 if (nCount > m_avalanche->getMaxElementPoll()) {
6700 Misbehaving(
6701 *peer,
6702 strprintf("too-many-ava-poll: poll message size = %u", nCount));
6703 return;
6704 }
6705
6706 std::vector<avalanche::Vote> votes;
6707 votes.reserve(nCount);
6708
6709 bool fPreconsensus{false};
6710 bool fStakingPreconsensus{false};
6711 {
6712 LOCK(::cs_main);
6713 const CBlockIndex *tip = m_chainman.ActiveTip();
6714 fPreconsensus = m_avalanche->isPreconsensusActivated(tip);
6715 fStakingPreconsensus =
6716 m_avalanche->isStakingPreconsensusActivated(tip);
6717 }
6718
6719 for (unsigned int n = 0; n < nCount; n++) {
6720 CInv inv;
6721 vRecv >> inv;
6722
6723 // Default vote for unknown inv type
6724 uint32_t vote = -1;
6725
6726 // We don't vote definitively until we have an established quorum
6727 if (!quorum_established) {
6728 votes.emplace_back(vote, inv.hash);
6729 continue;
6730 }
6731
6732 // If inv's type is known, get a vote for its hash
6733 switch (inv.type) {
6734 case MSG_TX: {
6735 if (fPreconsensus) {
6736 vote =
6737 GetAvalancheVoteForTx(*m_avalanche, TxId(inv.hash));
6738 }
6739 } break;
6740 case MSG_BLOCK: {
6741 vote = WITH_LOCK(cs_main, return GetAvalancheVoteForBlock(
6742 BlockHash(inv.hash)));
6743 } break;
6744 case MSG_AVA_PROOF: {
6746 *m_avalanche, avalanche::ProofId(inv.hash));
6747 } break;
6749 if (fStakingPreconsensus) {
6750 vote = m_avalanche->getStakeContenderStatus(
6752 }
6753 } break;
6754 default: {
6756 "poll inv type %d unknown from peer=%d\n",
6757 inv.type, pfrom.GetId());
6758 }
6759 }
6760
6761 votes.emplace_back(vote, inv.hash);
6762 }
6763
6764 // Send the query to the node.
6765 m_avalanche->sendResponse(
6766 &pfrom, avalanche::Response(round, m_opts.avalanche_cooldown,
6767 std::move(votes)));
6768 return;
6769 }
6770
6771 if (msg_type == NetMsgType::AVARESPONSE) {
6772 if (!m_avalanche) {
6773 return;
6774 }
6775 // As long as QUIC is not implemented, we need to sign response and
6776 // verify response's signatures in order to avoid any manipulation of
6777 // messages at the transport level.
6778 HashVerifier verifier(vRecv);
6780 verifier >> response;
6781
6783 vRecv >> sig;
6784
6785 {
6787 if (!pfrom.m_avalanche_pubkey.has_value() ||
6788 !(*pfrom.m_avalanche_pubkey)
6789 .VerifySchnorr(verifier.GetHash(), sig)) {
6790 Misbehaving(*peer, "invalid-ava-response-signature");
6791 return;
6792 }
6793 }
6794
6795 auto now = GetTime<std::chrono::seconds>();
6796
6797 std::vector<avalanche::VoteItemUpdate> updates;
6798 bool disconnect{false};
6799 std::string error;
6800 if (!m_avalanche->registerVotes(pfrom.GetId(), response, updates,
6801 disconnect, error)) {
6802 if (disconnect) {
6803 Misbehaving(*peer, error);
6804 return;
6805 }
6806
6807 // Otherwise the node may have got a network issue. Increase the
6808 // fault counter instead and only ban if we reached a threshold.
6809 // This allows for fault tolerance should there be a temporary
6810 // outage while still preventing DoS'ing behaviors, as the counter
6811 // is reset if no fault occured over some time period.
6814
6815 // Allow up to 12 messages before increasing the ban score. Since
6816 // the queries are cleared after 10s, this is at least 2 minutes
6817 // of network outage tolerance over the 1h window.
6818 if (pfrom.m_avalanche_message_fault_counter > 12) {
6819 LogPrint(
6821 "Repeated failure to register votes from peer %d: %s\n",
6822 pfrom.GetId(), error);
6824 if (pfrom.m_avalanche_message_fault_score > 100) {
6825 Misbehaving(*peer, error);
6826 }
6827 return;
6828 }
6829 }
6830
6831 // If no fault occurred within the last hour, reset the fault counter
6832 if (now > (pfrom.m_avalanche_last_message_fault.load() + 1h)) {
6834 }
6835
6836 pfrom.invsVoted(response.GetVotes().size());
6837
6838 auto logVoteUpdate = [](const auto &voteUpdate,
6839 const std::string &voteItemTypeStr,
6840 const auto &voteItemId) {
6841 std::string voteOutcome;
6842 bool alwaysPrint = false;
6843 switch (voteUpdate.getStatus()) {
6845 voteOutcome = "invalidated";
6846 alwaysPrint = true;
6847 break;
6849 voteOutcome = "rejected";
6850 break;
6852 voteOutcome = "accepted";
6853 break;
6855 voteOutcome = "finalized";
6856 // Don't log tx finalization unconditionally as it can be
6857 // quite spammy.
6858 alwaysPrint = voteItemTypeStr != "tx";
6859 break;
6861 voteOutcome = "stalled";
6862 alwaysPrint = true;
6863 break;
6864
6865 // No default case, so the compiler can warn about missing
6866 // cases
6867 }
6868
6869 // Always log the stake contenders to the avalanche category
6870 alwaysPrint &= (voteItemTypeStr != "contender");
6871
6872 if (alwaysPrint) {
6873 LogPrintf("Avalanche %s %s %s\n", voteOutcome, voteItemTypeStr,
6874 voteItemId.ToString());
6875 } else {
6876 // Only print these messages if -debug=avalanche is set
6877 LogPrint(BCLog::AVALANCHE, "Avalanche %s %s %s\n", voteOutcome,
6878 voteItemTypeStr, voteItemId.ToString());
6879 }
6880 };
6881
6882 bool shouldActivateBestChain = false;
6883
6884 bool fPreconsensus{false};
6885 bool fStakingPreconsensus{false};
6886 {
6887 LOCK(::cs_main);
6888 const CBlockIndex *tip = m_chainman.ActiveTip();
6889 fPreconsensus = m_avalanche->isPreconsensusActivated(tip);
6890 fStakingPreconsensus =
6891 m_avalanche->isStakingPreconsensusActivated(tip);
6892 }
6893
6894 for (const auto &u : updates) {
6895 const avalanche::AnyVoteItem &item = u.getVoteItem();
6896
6897 // Don't use a visitor here as we want to ignore unsupported item
6898 // types. This comes in handy when adding new types.
6899 if (auto pitem = std::get_if<const avalanche::ProofRef>(&item)) {
6900 avalanche::ProofRef proof = *pitem;
6901 const avalanche::ProofId &proofid = proof->getId();
6902
6903 logVoteUpdate(u, "proof", proofid);
6904
6905 auto rejectionMode =
6907 auto nextCooldownTimePoint = GetTime<std::chrono::seconds>();
6908 switch (u.getStatus()) {
6910 m_avalanche->withPeerManager(
6911 [&](avalanche::PeerManager &pm) {
6912 pm.setInvalid(proofid);
6913 });
6914 // Fallthrough
6916 // Invalidate mode removes the proof from all proof
6917 // pools
6918 rejectionMode =
6920 // Fallthrough
6922 if (!m_avalanche->withPeerManager(
6923 [&](avalanche::PeerManager &pm) {
6924 return pm.rejectProof(proofid,
6925 rejectionMode);
6926 })) {
6928 "ERROR: Failed to reject proof: %s\n",
6929 proofid.GetHex());
6930 }
6931 break;
6933 m_avalanche->setRecentlyFinalized(proofid);
6934 nextCooldownTimePoint += std::chrono::seconds(
6935 m_opts.avalanche_peer_replacement_cooldown);
6937 if (!m_avalanche->withPeerManager(
6938 [&](avalanche::PeerManager &pm) {
6939 pm.registerProof(
6940 proof,
6941 avalanche::PeerManager::
6942 RegistrationMode::FORCE_ACCEPT);
6943 return pm.forPeer(
6944 proofid,
6945 [&](const avalanche::Peer &peer) {
6946 pm.updateNextPossibleConflictTime(
6947 peer.peerid,
6948 nextCooldownTimePoint);
6949 if (u.getStatus() ==
6950 avalanche::VoteStatus::
6951 Finalized) {
6952 pm.setFinalized(peer.peerid);
6953 }
6954 // Only fail if the peer was not
6955 // created
6956 return true;
6957 });
6958 })) {
6960 "ERROR: Failed to accept proof: %s\n",
6961 proofid.GetHex());
6962 }
6963 break;
6964 }
6965 }
6966
6967 auto getBlockFromIndex = [this](const CBlockIndex *pindex) {
6968 // First check if the block is cached before reading
6969 // from disk.
6970 std::shared_ptr<const CBlock> pblock = WITH_LOCK(
6971 m_most_recent_block_mutex, return m_most_recent_block);
6972
6973 if (!pblock || pblock->GetHash() != pindex->GetBlockHash()) {
6974 std::shared_ptr<CBlock> pblockRead =
6975 std::make_shared<CBlock>();
6976 if (!m_chainman.m_blockman.ReadBlock(*pblockRead,
6977 *pindex)) {
6978 assert(!"cannot load block from disk");
6979 }
6980 pblock = pblockRead;
6981 }
6982 return pblock;
6983 };
6984
6985 if (auto pitem = std::get_if<const CBlockIndex *>(&item)) {
6986 CBlockIndex *pindex = const_cast<CBlockIndex *>(*pitem);
6987
6988 shouldActivateBestChain = true;
6989
6990 logVoteUpdate(u, "block", pindex->GetBlockHash());
6991
6992 switch (u.getStatus()) {
6995 m_chainman.ActiveChainstate().ParkBlock(state, pindex);
6996 if (!state.IsValid()) {
6997 LogPrintf("ERROR: Database error: %s\n",
6998 state.GetRejectReason());
6999 return;
7000 }
7001 } break;
7004 m_chainman.ActiveChainstate().ParkBlock(state, pindex);
7005 if (!state.IsValid()) {
7006 LogPrintf("ERROR: Database error: %s\n",
7007 state.GetRejectReason());
7008 return;
7009 }
7010
7011 auto pblock = getBlockFromIndex(pindex);
7012 assert(pblock);
7013
7014 WITH_LOCK(cs_main, GetMainSignals().BlockInvalidated(
7015 pindex, pblock));
7016 } break;
7018 LOCK(cs_main);
7019 m_chainman.ActiveChainstate().UnparkBlock(pindex);
7020 } break;
7022 m_avalanche->setRecentlyFinalized(
7023 pindex->GetBlockHash());
7024
7025 m_avalanche->cleanupStakingRewards(pindex->nHeight);
7026
7027 std::unique_ptr<node::CBlockTemplate> blockTemplate;
7028 {
7029 LOCK(cs_main);
7030 auto &chainstate = m_chainman.ActiveChainstate();
7031 chainstate.UnparkBlock(pindex);
7032
7033 const bool newlyFinalized =
7034 !chainstate.IsBlockAvalancheFinalized(pindex) &&
7035 chainstate.AvalancheFinalizeBlock(pindex,
7036 *m_avalanche);
7037
7038 // Skip if the block is already finalized, aka an
7039 // ancestor of the finalized tip.
7040 if (fPreconsensus && newlyFinalized) {
7041 auto pblock = getBlockFromIndex(pindex);
7042 assert(pblock);
7043
7044 {
7045 // If the finalized block is not the tip, we
7046 // need to keep track of the transactions
7047 // from the non final blocks, so that we can
7048 // check if they were finalized by
7049 // pre-consensus. If these transactions were
7050 // pruned from the radix tree, their
7051 // finalization status could be lost in the
7052 // case the non final blocks are later
7053 // rejected.
7054 CBlockIndex *tip = m_chainman.ActiveTip();
7055 std::unordered_set<TxId, SaltedTxIdHasher>
7056 confirmedTxIdsInNonFinalizedBlocks;
7057 for (const CBlockIndex *block = tip;
7058 block != nullptr && block != pindex;
7059 block = block->pprev) {
7060 auto currentBlock =
7061 getBlockFromIndex(block);
7062 assert(currentBlock);
7063 for (const auto &tx :
7064 currentBlock->vtx) {
7065 confirmedTxIdsInNonFinalizedBlocks
7066 .insert(tx->GetId());
7067 }
7068 }
7069
7070 // Remove the transactions that are not
7071 // confirmed
7072 LOCK(m_mempool.cs);
7073 m_mempool.removeForFinalizedBlock(
7074 confirmedTxIdsInNonFinalizedBlocks);
7075
7076 // Now add mempool transactions to the poll.
7077 // To determine which transaction to add, we
7078 // leverage the legacy block template
7079 // construction method and build a template
7080 // with the most valuable txs in it. These
7081 // transactions are sorted topologically;
7082 // parents come before children, so we can
7083 // poll for children first and optimize the
7084 // number of polls.
7085 node::BlockAssembler blockAssembler(
7086 config, chainstate, &m_mempool,
7087 m_avalanche);
7088 blockAssembler.pblocktemplate.reset(
7089 new node::CBlockTemplate());
7090
7091 if (blockAssembler.pblocktemplate) {
7092 blockAssembler.addTxs(m_mempool);
7093 blockTemplate = std::move(
7094 blockAssembler.pblocktemplate);
7095 }
7096 }
7097 }
7098 } // release cs_main
7099
7100 if (blockTemplate) {
7101 // We could check if the tx is final already
7102 // but addToReconcile will skip the recently
7103 // finalized txs, so let's abuse this
7104 // feature and avoid a tree lookup for each
7105 // tx as an optimization.
7106 for (const auto &templateEntry :
7107 reverse_iterate(blockTemplate->entries)) {
7108 m_avalanche->addToReconcile(templateEntry.tx);
7109 }
7110 }
7111 } break;
7113 // Fall back on Nakamoto consensus in the absence of
7114 // Avalanche votes for other competing or descendant
7115 // blocks.
7116 break;
7117 }
7118 }
7119
7120 if (fStakingPreconsensus) {
7121 if (auto pitem =
7122 std::get_if<const avalanche::StakeContenderId>(&item)) {
7123 const avalanche::StakeContenderId contenderId = *pitem;
7124 logVoteUpdate(u, "contender", contenderId);
7125
7126 switch (u.getStatus()) {
7129 m_avalanche->rejectStakeContender(contenderId);
7130 break;
7131 }
7133 m_avalanche->setRecentlyFinalized(contenderId);
7134 m_avalanche->finalizeStakeContender(contenderId);
7135 break;
7136 }
7138 m_avalanche->acceptStakeContender(contenderId);
7139 break;
7140 }
7142 break;
7143 }
7144 }
7145 }
7146
7147 if (!fPreconsensus) {
7148 continue;
7149 }
7150
7151 if (auto pitem = std::get_if<const CTransactionRef>(&item)) {
7152 const CTransactionRef tx = *pitem;
7153 assert(tx != nullptr);
7154
7155 const TxId &txid = tx->GetId();
7156 const auto status{u.getStatus()};
7157
7158 if (status != avalanche::VoteStatus::Finalized) {
7159 // Because we also want to log the parents txs of this
7160 // finalized tx, we log the finalization later.
7161 logVoteUpdate(u, "tx", txid);
7162 }
7163
7164 switch (status) {
7165 case avalanche::VoteStatus::Invalid: // Fallthrough
7167 // Remove from the mempool and the finalized tree, as
7168 // well as all the children txs. Note that removal from
7169 // the finalized tree is only a safety net and should
7170 // never happen.
7171 LOCK2(cs_main, m_mempool.cs);
7172
7173 std::shared_ptr<const std::vector<Coin>> spentCoins;
7174 if (status == avalanche::VoteStatus::Invalid) {
7175 // Get the spent coins before removing the tx from
7176 // the mempool.
7177 CCoinsViewMemPool coinViewMempool(
7178 &m_chainman.ActiveChainstate().CoinsTip(),
7179 m_mempool);
7180 CCoinsViewCache coinViewCache(&coinViewMempool);
7181 auto _spentCoins = GetSpentCoins(tx, coinViewCache);
7182 // spentCoins can be null here if the parent tx has
7183 // been invalidated already
7184 spentCoins =
7185 _spentCoins.has_value()
7186 ? std::make_shared<const std::vector<Coin>>(
7187 std::move(*_spentCoins))
7188 : nullptr;
7189 }
7190
7191 if (m_mempool.exists(txid)) {
7192 m_mempool.removeRecursive(
7194
7195 std::vector<CTransactionRef> conflictingTxs =
7196 m_mempool.withConflicting(
7197 [&tx](const TxConflicting &conflicting) {
7198 return conflicting.GetConflictTxs(tx);
7199 });
7200
7201 if (conflictingTxs.size() > 0) {
7202 // Pull the first tx only, erase the others so
7203 // they can be re-downloaded if needed.
7204 auto result = m_chainman.ProcessTransaction(
7205 conflictingTxs[0]);
7206 if (!result.m_state.IsValid()) {
7207 LogPrint(
7209 "Attempting to pull a now invalid "
7210 "conflicting tx %s to mempool\n",
7211 conflictingTxs[0]->GetId().ToString());
7212 }
7213 }
7214
7215 m_mempool.withConflicting(
7216 [&conflictingTxs,
7217 &tx](TxConflicting &conflicting) {
7218 for (const auto &conflictingTx :
7219 conflictingTxs) {
7220 conflicting.EraseTx(
7221 conflictingTx->GetId());
7222 }
7223
7224 // Note that we don't store the descendants,
7225 // which should be re-downloaded. This could
7226 // be optimized but we will have to manage
7227 // the topological ordering.
7228 conflicting.AddTx(tx, NO_NODE);
7229 });
7230 }
7231
7232 if (status == avalanche::VoteStatus::Invalid) {
7233 // Also remove from the conflicting pool. If it was
7234 // in the mempool (unlikely) we just moved it there.
7235 m_mempool.withConflicting(
7236 [&txid](TxConflicting &conflicting) {
7237 conflicting.EraseTx(txid);
7238 });
7239
7240 m_recent_rejects.insert(txid);
7241
7242 AddToCompactExtraTransactions(tx);
7243
7245 spentCoins);
7246 }
7247
7248 break;
7249 }
7251 // fallthrough
7253 {
7254 LOCK2(cs_main, m_mempool.cs);
7255 if (m_mempool.withConflicting(
7256 [&txid](const TxConflicting &conflicting) {
7257 return conflicting.HaveTx(txid);
7258 })) {
7259 // Swap conflicting txs from/to the mempool
7260 std::vector<CTransactionRef>
7261 mempool_conflicting_txs;
7262 for (const auto &txin : tx->vin) {
7263 // Find the conflicting txs
7264 if (CTransactionRef conflict =
7265 m_mempool.GetConflictTx(
7266 txin.prevout)) {
7267 mempool_conflicting_txs.push_back(
7268 std::move(conflict));
7269 }
7270 }
7271 m_mempool.removeConflicts(*tx);
7272
7273 auto result = m_chainman.ProcessTransaction(tx);
7274 assert(result.m_state.IsValid());
7275
7276 m_mempool.withConflicting(
7277 [&txid, &mempool_conflicting_txs](
7278 TxConflicting &conflicting) {
7279 conflicting.EraseTx(txid);
7280 // Store the first tx only, the others
7281 // can be re-downloaded if needed.
7282 if (mempool_conflicting_txs.size() >
7283 0) {
7284 conflicting.AddTx(
7285 mempool_conflicting_txs[0],
7286 NO_NODE);
7287 }
7288 });
7289 }
7290 }
7291
7292 if (status == avalanche::VoteStatus::Finalized) {
7293 LOCK2(cs_main, m_mempool.cs);
7294 auto it = m_mempool.GetIter(txid);
7295 if (!it.has_value()) {
7296 LogPrint(
7298 "Error: finalized tx (%s) is not in the "
7299 "mempool\n",
7300 txid.ToString());
7301 break;
7302 }
7303
7304 std::vector<TxId> finalizedTxIds;
7305 m_mempool.setAvalancheFinalized(
7306 **it, m_chainparams.GetConsensus(),
7307 *Assert(m_chainman.ActiveTip()),
7308 finalizedTxIds);
7309
7310 for (const auto &finalized_txid : finalizedTxIds) {
7311 m_avalanche->setRecentlyFinalized(
7312 finalized_txid);
7313 // Log the parent tx being implicitely finalized
7314 // as well
7315 logVoteUpdate(u, "tx", finalized_txid);
7316 }
7317
7318 // NO_THREAD_SAFETY_ANALYSIS because
7319 // m_recent_rejects requires cs_main in the lambda
7320 m_mempool.withConflicting(
7321 [&](TxConflicting &conflicting)
7323 std::vector<CTransactionRef>
7324 conflictingTxs =
7325 conflicting.GetConflictTxs(tx);
7326 for (const auto &conflictingTx :
7327 conflictingTxs) {
7328 m_recent_rejects.insert(
7329 conflictingTx->GetId());
7330 conflicting.EraseTx(
7331 conflictingTx->GetId());
7332 }
7333 });
7334 }
7335
7336 break;
7337 }
7339 LOCK(cs_main);
7340
7341 // If the tx is stale, there is no point keeping it
7342 // around as it will no be mined. Let's remove it but
7343 // also forget we got it so it can be eventually
7344 // re-downloaded.
7345 {
7346 LOCK(m_mempool.cs);
7347 m_mempool.removeRecursive(
7349
7350 m_mempool.withConflicting(
7351 [&txid](TxConflicting &conflicting) {
7352 conflicting.EraseTx(txid);
7353 });
7354 }
7355
7356 // Make sure we can request this tx again
7357 m_txrequest.ForgetInvId(txid);
7358
7359 {
7360 // Save the stalled txids so that we can relay them
7361 // to our peers.
7362 LOCK(m_peer_mutex);
7363 for (auto &it : m_peer_map) {
7364 auto tx_relay = (*it.second).GetTxRelay();
7365 if (!tx_relay) {
7366 continue;
7367 }
7368
7369 LOCK(tx_relay->m_tx_inventory_mutex);
7370
7371 // We limit the size of the stalled txs set to
7372 // avoid unbounded memory growth. In practice,
7373 // this should not be an issue as stalled txs
7374 // should be few and far between. If we are at
7375 // the limit, remove the oldest entries.
7376 auto &stalled_by_time =
7377 tx_relay->m_avalanche_stalled_txids
7378 .get<by_time>();
7379 if (stalled_by_time.size() >=
7381 stalled_by_time.erase(
7382 stalled_by_time.begin()->timeAdded);
7383 }
7384
7385 tx_relay->m_avalanche_stalled_txids.insert(
7386 {txid, now});
7387 }
7388 }
7389
7390 AddToCompactExtraTransactions(tx);
7391
7392 break;
7393 }
7394 }
7395 }
7396 }
7397
7398 if (shouldActivateBestChain) {
7400 if (!m_chainman.ActiveChainstate().ActivateBestChain(
7401 state, /*pblock=*/nullptr, m_avalanche)) {
7402 LogPrintf("failed to activate chain (%s)\n", state.ToString());
7403 }
7404 }
7405
7406 return;
7407 }
7408
7409 if (msg_type == NetMsgType::AVAPROOF) {
7410 if (!m_avalanche) {
7411 return;
7412 }
7413 auto proof = RCUPtr<avalanche::Proof>::make();
7414 vRecv >> *proof;
7415
7416 ReceivedAvalancheProof(pfrom, *peer, proof);
7417
7418 return;
7419 }
7420
7421 if (msg_type == NetMsgType::GETAVAPROOFS) {
7422 if (!m_avalanche) {
7423 return;
7424 }
7425 if (peer->m_proof_relay == nullptr) {
7426 return;
7427 }
7428
7429 peer->m_proof_relay->lastSharedProofsUpdate =
7430 GetTime<std::chrono::seconds>();
7431
7432 peer->m_proof_relay->sharedProofs =
7433 m_avalanche->withPeerManager([&](const avalanche::PeerManager &pm) {
7434 return pm.getShareableProofsSnapshot();
7435 });
7436
7437 avalanche::CompactProofs compactProofs(
7438 peer->m_proof_relay->sharedProofs);
7439 MakeAndPushMessage(pfrom, NetMsgType::AVAPROOFS, compactProofs);
7440
7441 return;
7442 }
7443
7444 if (msg_type == NetMsgType::AVAPROOFS) {
7445 if (!m_avalanche) {
7446 return;
7447 }
7448 if (peer->m_proof_relay == nullptr) {
7449 return;
7450 }
7451
7452 // Only process the compact proofs if we requested them
7453 if (!peer->m_proof_relay->compactproofs_requested) {
7454 LogPrint(BCLog::AVALANCHE, "Ignoring unsollicited avaproofs\n");
7455 return;
7456 }
7457 peer->m_proof_relay->compactproofs_requested = false;
7458
7459 avalanche::CompactProofs compactProofs;
7460 try {
7461 vRecv >> compactProofs;
7462 } catch (std::ios_base::failure &e) {
7463 // This compact proofs have non contiguous or overflowing indexes
7464 Misbehaving(*peer, "avaproofs-bad-indexes");
7465 return;
7466 }
7467
7468 // If there are prefilled proofs, process them first
7469 for (const auto &prefilledProof : compactProofs.getPrefilledProofs()) {
7470 if (!ReceivedAvalancheProof(pfrom, *peer, prefilledProof.proof)) {
7471 // If we got an invalid proof, the peer is getting banned and we
7472 // can bail out.
7473 return;
7474 }
7475 }
7476
7477 // If there is no shortid, avoid parsing/responding/accounting for the
7478 // message.
7479 if (compactProofs.getShortIDs().size() == 0) {
7480 return;
7481 }
7482
7483 // To determine the chance that the number of entries in a bucket
7484 // exceeds N, we use the fact that the number of elements in a single
7485 // bucket is binomially distributed (with n = the number of shorttxids
7486 // S, and p = 1 / the number of buckets), that in the worst case the
7487 // number of buckets is equal to S (due to std::unordered_map having a
7488 // default load factor of 1.0), and that the chance for any bucket to
7489 // exceed N elements is at most buckets * (the chance that any given
7490 // bucket is above N elements). Thus:
7491 // P(max_elements_per_bucket > N) <=
7492 // S * (1 - cdf(binomial(n=S,p=1/S), N))
7493 // If we assume up to 21000000, allowing 15 elements per bucket should
7494 // only fail once per ~2.5 million avaproofs transfers (per peer and
7495 // connection).
7496 // TODO re-evaluate the bucket count to a more realistic value.
7497 // TODO: In the case of a shortid-collision, we should request all the
7498 // proofs which collided. For now, we only request one, which is not
7499 // that bad considering this event is expected to be very rare.
7500 auto shortIdProcessor =
7502 compactProofs.getShortIDs(), 15);
7503
7504 if (shortIdProcessor.hasOutOfBoundIndex()) {
7505 // This should be catched by deserialization, but catch it here as
7506 // well as a good measure.
7507 Misbehaving(*peer, "avaproofs-bad-indexes");
7508 return;
7509 }
7510 if (!shortIdProcessor.isEvenlyDistributed()) {
7511 // This is suspicious, don't ban but bail out
7512 return;
7513 }
7514
7515 std::vector<std::pair<avalanche::ProofId, bool>> remoteProofsStatus;
7516 m_avalanche->withPeerManager([&](const avalanche::PeerManager &pm) {
7517 pm.forEachPeer([&](const avalanche::Peer &peer) {
7518 assert(peer.proof);
7519 uint64_t shortid = compactProofs.getShortID(peer.getProofId());
7520
7521 int added =
7522 shortIdProcessor.matchKnownItem(shortid, peer.proof);
7523
7524 // No collision
7525 if (added >= 0) {
7526 // Because we know the proof, we can determine if our peer
7527 // has it (added = 1) or not (added = 0) and update the
7528 // remote proof status accordingly.
7529 remoteProofsStatus.emplace_back(peer.getProofId(),
7530 added > 0);
7531 }
7532
7533 // In order to properly determine which proof is missing, we
7534 // need to keep scanning for all our proofs.
7535 return true;
7536 });
7537 });
7538
7540 for (size_t i = 0; i < compactProofs.size(); i++) {
7541 if (shortIdProcessor.getItem(i) == nullptr) {
7542 req.indices.push_back(i);
7543 }
7544 }
7545
7546 MakeAndPushMessage(pfrom, NetMsgType::AVAPROOFSREQ, req);
7547
7548 const NodeId nodeid = pfrom.GetId();
7549
7550 // We want to keep a count of how many nodes we successfully requested
7551 // avaproofs from as this is used to determine when we are confident our
7552 // quorum is close enough to the other participants.
7553 m_avalanche->avaproofsSent(nodeid);
7554
7555 // Only save remote proofs from stakers
7557 return pfrom.m_avalanche_pubkey.has_value())) {
7558 m_avalanche->withPeerManager(
7559 [&remoteProofsStatus, nodeid](avalanche::PeerManager &pm) {
7560 for (const auto &[proofid, present] : remoteProofsStatus) {
7561 pm.saveRemoteProof(proofid, nodeid, present);
7562 }
7563 });
7564 }
7565
7566 return;
7567 }
7568
7569 if (msg_type == NetMsgType::AVAPROOFSREQ) {
7570 if (peer->m_proof_relay == nullptr) {
7571 return;
7572 }
7573
7574 avalanche::ProofsRequest proofreq;
7575 vRecv >> proofreq;
7576
7577 auto requestedIndiceIt = proofreq.indices.begin();
7578 uint32_t treeIndice = 0;
7579 peer->m_proof_relay->sharedProofs.forEachLeaf([&](const auto &proof) {
7580 if (requestedIndiceIt == proofreq.indices.end()) {
7581 // No more indice to process
7582 return false;
7583 }
7584
7585 if (treeIndice++ == *requestedIndiceIt) {
7586 MakeAndPushMessage(pfrom, NetMsgType::AVAPROOF, *proof);
7587 requestedIndiceIt++;
7588 }
7589
7590 return true;
7591 });
7592
7593 peer->m_proof_relay->sharedProofs = {};
7594 return;
7595 }
7596
7597 if (msg_type == NetMsgType::GETADDR) {
7598 // This asymmetric behavior for inbound and outbound connections was
7599 // introduced to prevent a fingerprinting attack: an attacker can send
7600 // specific fake addresses to users' AddrMan and later request them by
7601 // sending getaddr messages. Making nodes which are behind NAT and can
7602 // only make outgoing connections ignore the getaddr message mitigates
7603 // the attack.
7604 if (!pfrom.IsInboundConn()) {
7606 "Ignoring \"getaddr\" from %s connection. peer=%d\n",
7607 pfrom.ConnectionTypeAsString(), pfrom.GetId());
7608 return;
7609 }
7610
7611 // Since this must be an inbound connection, SetupAddressRelay will
7612 // never fail.
7613 Assume(SetupAddressRelay(pfrom, *peer));
7614
7615 // Only send one GetAddr response per connection to reduce resource
7616 // waste and discourage addr stamping of INV announcements.
7617 if (peer->m_getaddr_recvd) {
7618 LogPrint(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n",
7619 pfrom.GetId());
7620 return;
7621 }
7622 peer->m_getaddr_recvd = true;
7623
7624 peer->m_addrs_to_send.clear();
7625 std::vector<CAddress> vAddr;
7626 const size_t maxAddrToSend = m_opts.max_addr_to_send;
7628 vAddr = m_connman.GetAddresses(maxAddrToSend, MAX_PCT_ADDR_TO_SEND,
7629 /* network */ std::nullopt);
7630 } else {
7631 vAddr = m_connman.GetAddresses(pfrom, maxAddrToSend,
7633 }
7634 for (const CAddress &addr : vAddr) {
7635 PushAddress(*peer, addr);
7636 }
7637 return;
7638 }
7639
7640 if (msg_type == NetMsgType::GETAVAADDR) {
7641 auto now = GetTime<std::chrono::seconds>();
7642 if (now < pfrom.m_nextGetAvaAddr) {
7643 // Prevent a peer from exhausting our resources by spamming
7644 // getavaaddr messages.
7645 return;
7646 }
7647
7648 // Only accept a getavaaddr every GETAVAADDR_INTERVAL at most
7650
7651 if (!SetupAddressRelay(pfrom, *peer)) {
7653 "Ignoring getavaaddr message from %s peer=%d\n",
7654 pfrom.ConnectionTypeAsString(), pfrom.GetId());
7655 return;
7656 }
7657
7658 auto availabilityScoreComparator = [](const CNode *lhs,
7659 const CNode *rhs) {
7660 double scoreLhs = lhs->getAvailabilityScore();
7661 double scoreRhs = rhs->getAvailabilityScore();
7662
7663 if (scoreLhs != scoreRhs) {
7664 return scoreLhs > scoreRhs;
7665 }
7666
7667 return lhs < rhs;
7668 };
7669
7670 // Get up to MAX_ADDR_TO_SEND addresses of the nodes which are the
7671 // most active in the avalanche network. Account for 0 availability as
7672 // well so we can send addresses even if we did not start polling yet.
7673 std::set<const CNode *, decltype(availabilityScoreComparator)> avaNodes(
7674 availabilityScoreComparator);
7675 m_connman.ForEachNode([&](const CNode *pnode) {
7676 if (!pnode->m_avalanche_enabled ||
7677 pnode->getAvailabilityScore() < 0.) {
7678 return;
7679 }
7680
7681 avaNodes.insert(pnode);
7682 if (avaNodes.size() > m_opts.max_addr_to_send) {
7683 avaNodes.erase(std::prev(avaNodes.end()));
7684 }
7685 });
7686
7687 peer->m_addrs_to_send.clear();
7688 for (const CNode *pnode : avaNodes) {
7689 PushAddress(*peer, pnode->addr);
7690 }
7691
7692 return;
7693 }
7694
7695 if (msg_type == NetMsgType::MEMPOOL) {
7696 if (!(peer->m_our_services & NODE_BLOOM) &&
7700 "mempool request with bloom filters disabled, "
7701 "disconnect peer=%d\n",
7702 pfrom.GetId());
7703 pfrom.fDisconnect = true;
7704 }
7705 return;
7706 }
7707
7708 if (m_connman.OutboundTargetReached(false) &&
7712 "mempool request with bandwidth limit reached, "
7713 "disconnect peer=%d\n",
7714 pfrom.GetId());
7715 pfrom.fDisconnect = true;
7716 }
7717 return;
7718 }
7719
7720 if (auto tx_relay = peer->GetTxRelay()) {
7721 LOCK(tx_relay->m_tx_inventory_mutex);
7722 tx_relay->m_send_mempool = true;
7723 }
7724 return;
7725 }
7726
7727 if (msg_type == NetMsgType::PING) {
7728 if (pfrom.GetCommonVersion() > BIP0031_VERSION) {
7729 uint64_t nonce = 0;
7730 vRecv >> nonce;
7731 // Echo the message back with the nonce. This allows for two useful
7732 // features:
7733 //
7734 // 1) A remote node can quickly check if the connection is
7735 // operational.
7736 // 2) Remote nodes can measure the latency of the network thread. If
7737 // this node is overloaded it won't respond to pings quickly and the
7738 // remote node can avoid sending us more work, like chain download
7739 // requests.
7740 //
7741 // The nonce stops the remote getting confused between different
7742 // pings: without it, if the remote node sends a ping once per
7743 // second and this node takes 5 seconds to respond to each, the 5th
7744 // ping the remote sends would appear to return very quickly.
7745 MakeAndPushMessage(pfrom, NetMsgType::PONG, nonce);
7746 }
7747 return;
7748 }
7749
7750 if (msg_type == NetMsgType::PONG) {
7751 const auto ping_end = time_received;
7752 uint64_t nonce = 0;
7753 size_t nAvail = vRecv.in_avail();
7754 bool bPingFinished = false;
7755 std::string sProblem;
7756
7757 if (nAvail >= sizeof(nonce)) {
7758 vRecv >> nonce;
7759
7760 // Only process pong message if there is an outstanding ping (old
7761 // ping without nonce should never pong)
7762 if (peer->m_ping_nonce_sent != 0) {
7763 if (nonce == peer->m_ping_nonce_sent) {
7764 // Matching pong received, this ping is no longer
7765 // outstanding
7766 bPingFinished = true;
7767 const auto ping_time = ping_end - peer->m_ping_start.load();
7768 if (ping_time.count() >= 0) {
7769 // Let connman know about this successful ping-pong
7770 pfrom.PongReceived(ping_time);
7771 } else {
7772 // This should never happen
7773 sProblem = "Timing mishap";
7774 }
7775 } else {
7776 // Nonce mismatches are normal when pings are overlapping
7777 sProblem = "Nonce mismatch";
7778 if (nonce == 0) {
7779 // This is most likely a bug in another implementation
7780 // somewhere; cancel this ping
7781 bPingFinished = true;
7782 sProblem = "Nonce zero";
7783 }
7784 }
7785 } else {
7786 sProblem = "Unsolicited pong without ping";
7787 }
7788 } else {
7789 // This is most likely a bug in another implementation somewhere;
7790 // cancel this ping
7791 bPingFinished = true;
7792 sProblem = "Short payload";
7793 }
7794
7795 if (!(sProblem.empty())) {
7797 "pong peer=%d: %s, %x expected, %x received, %u bytes\n",
7798 pfrom.GetId(), sProblem, peer->m_ping_nonce_sent, nonce,
7799 nAvail);
7800 }
7801 if (bPingFinished) {
7802 peer->m_ping_nonce_sent = 0;
7803 }
7804 return;
7805 }
7806
7807 if (msg_type == NetMsgType::FILTERLOAD) {
7808 if (!(peer->m_our_services & NODE_BLOOM)) {
7810 "filterload received despite not offering bloom services "
7811 "from peer=%d; disconnecting\n",
7812 pfrom.GetId());
7813 pfrom.fDisconnect = true;
7814 return;
7815 }
7816 CBloomFilter filter;
7817 vRecv >> filter;
7818
7819 if (!filter.IsWithinSizeConstraints()) {
7820 // There is no excuse for sending a too-large filter
7821 Misbehaving(*peer, "too-large bloom filter");
7822 } else if (auto tx_relay = peer->GetTxRelay()) {
7823 {
7824 LOCK(tx_relay->m_bloom_filter_mutex);
7825 tx_relay->m_bloom_filter.reset(new CBloomFilter(filter));
7826 tx_relay->m_relay_txs = true;
7827 }
7828 pfrom.m_bloom_filter_loaded = true;
7829 }
7830 return;
7831 }
7832
7833 if (msg_type == NetMsgType::FILTERADD) {
7834 if (!(peer->m_our_services & NODE_BLOOM)) {
7836 "filteradd received despite not offering bloom services "
7837 "from peer=%d; disconnecting\n",
7838 pfrom.GetId());
7839 pfrom.fDisconnect = true;
7840 return;
7841 }
7842 std::vector<uint8_t> vData;
7843 vRecv >> vData;
7844
7845 // Nodes must NEVER send a data item > 520 bytes (the max size for a
7846 // script data object, and thus, the maximum size any matched object can
7847 // have) in a filteradd message.
7848 bool bad = false;
7849 if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) {
7850 bad = true;
7851 } else if (auto tx_relay = peer->GetTxRelay()) {
7852 LOCK(tx_relay->m_bloom_filter_mutex);
7853 if (tx_relay->m_bloom_filter) {
7854 tx_relay->m_bloom_filter->insert(vData);
7855 } else {
7856 bad = true;
7857 }
7858 }
7859 if (bad) {
7860 // The structure of this code doesn't really allow for a good error
7861 // code. We'll go generic.
7862 Misbehaving(*peer, "bad filteradd message");
7863 }
7864 return;
7865 }
7866
7867 if (msg_type == NetMsgType::FILTERCLEAR) {
7868 if (!(peer->m_our_services & NODE_BLOOM)) {
7870 "filterclear received despite not offering bloom services "
7871 "from peer=%d; disconnecting\n",
7872 pfrom.GetId());
7873 pfrom.fDisconnect = true;
7874 return;
7875 }
7876 auto tx_relay = peer->GetTxRelay();
7877 if (!tx_relay) {
7878 return;
7879 }
7880
7881 {
7882 LOCK(tx_relay->m_bloom_filter_mutex);
7883 tx_relay->m_bloom_filter = nullptr;
7884 tx_relay->m_relay_txs = true;
7885 }
7886 pfrom.m_bloom_filter_loaded = false;
7887 pfrom.m_relays_txs = true;
7888 return;
7889 }
7890
7891 if (msg_type == NetMsgType::FEEFILTER) {
7892 Amount newFeeFilter = Amount::zero();
7893 vRecv >> newFeeFilter;
7894 if (MoneyRange(newFeeFilter)) {
7895 if (auto tx_relay = peer->GetTxRelay()) {
7896 tx_relay->m_fee_filter_received = newFeeFilter;
7897 }
7898 LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n",
7899 CFeeRate(newFeeFilter).ToString(), pfrom.GetId());
7900 }
7901 return;
7902 }
7903
7904 if (msg_type == NetMsgType::GETCFILTERS) {
7905 ProcessGetCFilters(pfrom, *peer, vRecv);
7906 return;
7907 }
7908
7909 if (msg_type == NetMsgType::GETCFHEADERS) {
7910 ProcessGetCFHeaders(pfrom, *peer, vRecv);
7911 return;
7912 }
7913
7914 if (msg_type == NetMsgType::GETCFCHECKPT) {
7915 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
7916 return;
7917 }
7918
7919 if (msg_type == NetMsgType::NOTFOUND) {
7920 std::vector<CInv> vInv;
7921 vRecv >> vInv;
7922 // A peer might send up to 1 notfound per getdata request, but no more
7923 if (vInv.size() <= PROOF_REQUEST_PARAMS.max_peer_announcements +
7926 for (CInv &inv : vInv) {
7927 if (inv.IsMsgTx()) {
7928 // If we receive a NOTFOUND message for a tx we requested,
7929 // mark the announcement for it as completed in
7930 // InvRequestTracker.
7931 LOCK(::cs_main);
7932 m_txrequest.ReceivedResponse(pfrom.GetId(), TxId(inv.hash));
7933 continue;
7934 }
7935 if (inv.IsMsgProof()) {
7936 if (!m_avalanche) {
7937 continue;
7938 }
7939 LOCK(cs_proofrequest);
7940 m_proofrequest.ReceivedResponse(
7941 pfrom.GetId(), avalanche::ProofId(inv.hash));
7942 }
7943 }
7944 }
7945 return;
7946 }
7947
7948 // Ignore unknown commands for extensibility
7949 LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n",
7950 SanitizeString(msg_type), pfrom.GetId());
7951 return;
7952}
7953
7954bool PeerManagerImpl::MaybeDiscourageAndDisconnect(CNode &pnode, Peer &peer) {
7955 {
7956 LOCK(peer.m_misbehavior_mutex);
7957
7958 // There's nothing to do if the m_should_discourage flag isn't set
7959 if (!peer.m_should_discourage) {
7960 return false;
7961 }
7962
7963 peer.m_should_discourage = false;
7964 } // peer.m_misbehavior_mutex
7965
7967 // We never disconnect or discourage peers for bad behavior if they have
7968 // NetPermissionFlags::NoBan permission
7969 LogPrintf("Warning: not punishing noban peer %d!\n", peer.m_id);
7970 return false;
7971 }
7972
7973 if (pnode.IsManualConn()) {
7974 // We never disconnect or discourage manual peers for bad behavior
7975 LogPrintf("Warning: not punishing manually connected peer %d!\n",
7976 peer.m_id);
7977 return false;
7978 }
7979
7980 if (pnode.addr.IsLocal()) {
7981 // We disconnect local peers for bad behavior but don't discourage
7982 // (since that would discourage all peers on the same local address)
7984 "Warning: disconnecting but not discouraging %s peer %d!\n",
7985 pnode.m_inbound_onion ? "inbound onion" : "local", peer.m_id);
7986 pnode.fDisconnect = true;
7987 return true;
7988 }
7989
7990 // Normal case: Disconnect the peer and discourage all nodes sharing the
7991 // address
7992 LogPrint(BCLog::NET, "Disconnecting and discouraging peer %d!\n",
7993 peer.m_id);
7994 if (m_banman) {
7995 m_banman->Discourage(pnode.addr);
7996 }
7997 m_connman.DisconnectNode(pnode.addr);
7998 return true;
7999}
8000
8001bool PeerManagerImpl::ProcessMessages(const Config &config, CNode *pfrom,
8002 std::atomic<bool> &interruptMsgProc) {
8003 AssertLockHeld(g_msgproc_mutex);
8004
8005 PeerRef peer = GetPeerRef(pfrom->GetId());
8006 if (peer == nullptr) {
8007 return false;
8008 }
8009
8010 {
8011 LOCK(peer->m_getdata_requests_mutex);
8012 if (!peer->m_getdata_requests.empty()) {
8013 ProcessGetData(config, *pfrom, *peer, interruptMsgProc);
8014 }
8015 }
8016
8017 const bool processed_orphan = ProcessOrphanTx(config, *peer);
8018
8019 if (pfrom->fDisconnect) {
8020 return false;
8021 }
8022
8023 if (processed_orphan) {
8024 return true;
8025 }
8026
8027 // this maintains the order of responses and prevents m_getdata_requests to
8028 // grow unbounded
8029 {
8030 LOCK(peer->m_getdata_requests_mutex);
8031 if (!peer->m_getdata_requests.empty()) {
8032 return true;
8033 }
8034 }
8035
8036 // Don't bother if send buffer is too full to respond anyway
8037 if (pfrom->fPauseSend) {
8038 return false;
8039 }
8040
8041 auto poll_result{pfrom->PollMessage()};
8042 if (!poll_result) {
8043 // No message to process
8044 return false;
8045 }
8046
8047 CNetMessage &msg{poll_result->first};
8048 bool fMoreWork = poll_result->second;
8049
8050 TRACE6(net, inbound_message, pfrom->GetId(), pfrom->m_addr_name.c_str(),
8051 pfrom->ConnectionTypeAsString().c_str(), msg.m_type.c_str(),
8052 msg.m_recv.size(), msg.m_recv.data());
8053
8054 if (m_opts.capture_messages) {
8055 CaptureMessage(pfrom->addr, msg.m_type, MakeUCharSpan(msg.m_recv),
8056 /*is_incoming=*/true);
8057 }
8058
8059 try {
8060 ProcessMessage(config, *pfrom, msg.m_type, msg.m_recv, msg.m_time,
8061 interruptMsgProc);
8062 if (interruptMsgProc) {
8063 return false;
8064 }
8065
8066 {
8067 LOCK(peer->m_getdata_requests_mutex);
8068 if (!peer->m_getdata_requests.empty()) {
8069 fMoreWork = true;
8070 }
8071 }
8072 // Does this peer has an orphan ready to reconsider?
8073 // (Note: we may have provided a parent for an orphan provided by
8074 // another peer that was already processed; in that case, the extra work
8075 // may not be noticed, possibly resulting in an unnecessary 100ms delay)
8076 if (m_mempool.withOrphanage([&peer](TxOrphanage &orphanage) {
8077 return orphanage.HaveTxToReconsider(peer->m_id);
8078 })) {
8079 fMoreWork = true;
8080 }
8081 } catch (const std::exception &e) {
8082 LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' (%s) caught\n",
8083 __func__, SanitizeString(msg.m_type), msg.m_message_size,
8084 e.what(), typeid(e).name());
8085 } catch (...) {
8086 LogPrint(BCLog::NET, "%s(%s, %u bytes): Unknown exception caught\n",
8087 __func__, SanitizeString(msg.m_type), msg.m_message_size);
8088 }
8089
8090 return fMoreWork;
8091}
8092
8093void PeerManagerImpl::ConsiderEviction(CNode &pto, Peer &peer,
8094 std::chrono::seconds time_in_seconds) {
8096
8097 CNodeState &state = *State(pto.GetId());
8098
8099 if (!state.m_chain_sync.m_protect && pto.IsOutboundOrBlockRelayConn() &&
8100 state.fSyncStarted) {
8101 // This is an outbound peer subject to disconnection if they don't
8102 // announce a block with as much work as the current tip within
8103 // CHAIN_SYNC_TIMEOUT + HEADERS_RESPONSE_TIME seconds (note: if their
8104 // chain has more work than ours, we should sync to it, unless it's
8105 // invalid, in which case we should find that out and disconnect from
8106 // them elsewhere).
8107 if (state.pindexBestKnownBlock != nullptr &&
8108 state.pindexBestKnownBlock->nChainWork >=
8109 m_chainman.ActiveChain().Tip()->nChainWork) {
8110 if (state.m_chain_sync.m_timeout != 0s) {
8111 state.m_chain_sync.m_timeout = 0s;
8112 state.m_chain_sync.m_work_header = nullptr;
8113 state.m_chain_sync.m_sent_getheaders = false;
8114 }
8115 } else if (state.m_chain_sync.m_timeout == 0s ||
8116 (state.m_chain_sync.m_work_header != nullptr &&
8117 state.pindexBestKnownBlock != nullptr &&
8118 state.pindexBestKnownBlock->nChainWork >=
8119 state.m_chain_sync.m_work_header->nChainWork)) {
8120 // Our best block known by this peer is behind our tip, and we're
8121 // either noticing that for the first time, OR this peer was able to
8122 // catch up to some earlier point where we checked against our tip.
8123 // Either way, set a new timeout based on current tip.
8124 state.m_chain_sync.m_timeout = time_in_seconds + CHAIN_SYNC_TIMEOUT;
8125 state.m_chain_sync.m_work_header = m_chainman.ActiveChain().Tip();
8126 state.m_chain_sync.m_sent_getheaders = false;
8127 } else if (state.m_chain_sync.m_timeout > 0s &&
8128 time_in_seconds > state.m_chain_sync.m_timeout) {
8129 // No evidence yet that our peer has synced to a chain with work
8130 // equal to that of our tip, when we first detected it was behind.
8131 // Send a single getheaders message to give the peer a chance to
8132 // update us.
8133 if (state.m_chain_sync.m_sent_getheaders) {
8134 // They've run out of time to catch up!
8135 LogPrintf(
8136 "Disconnecting outbound peer %d for old chain, best known "
8137 "block = %s\n",
8138 pto.GetId(),
8139 state.pindexBestKnownBlock != nullptr
8140 ? state.pindexBestKnownBlock->GetBlockHash().ToString()
8141 : "<none>");
8142 pto.fDisconnect = true;
8143 } else {
8144 assert(state.m_chain_sync.m_work_header);
8145 // Here, we assume that the getheaders message goes out,
8146 // because it'll either go out or be skipped because of a
8147 // getheaders in-flight already, in which case the peer should
8148 // still respond to us with a sufficiently high work chain tip.
8149 MaybeSendGetHeaders(
8150 pto, GetLocator(state.m_chain_sync.m_work_header->pprev),
8151 peer);
8152 LogPrint(
8153 BCLog::NET,
8154 "sending getheaders to outbound peer=%d to verify chain "
8155 "work (current best known block:%s, benchmark blockhash: "
8156 "%s)\n",
8157 pto.GetId(),
8158 state.pindexBestKnownBlock != nullptr
8159 ? state.pindexBestKnownBlock->GetBlockHash().ToString()
8160 : "<none>",
8161 state.m_chain_sync.m_work_header->GetBlockHash()
8162 .ToString());
8163 state.m_chain_sync.m_sent_getheaders = true;
8164 // Bump the timeout to allow a response, which could clear the
8165 // timeout (if the response shows the peer has synced), reset
8166 // the timeout (if the peer syncs to the required work but not
8167 // to our tip), or result in disconnect (if we advance to the
8168 // timeout and pindexBestKnownBlock has not sufficiently
8169 // progressed)
8170 state.m_chain_sync.m_timeout =
8171 time_in_seconds + HEADERS_RESPONSE_TIME;
8172 }
8173 }
8174 }
8175}
8176
8177void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now) {
8178 // If we have any extra block-relay-only peers, disconnect the youngest
8179 // unless it's given us a block -- in which case, compare with the
8180 // second-youngest, and out of those two, disconnect the peer who least
8181 // recently gave us a block.
8182 // The youngest block-relay-only peer would be the extra peer we connected
8183 // to temporarily in order to sync our tip; see net.cpp.
8184 // Note that we use higher nodeid as a measure for most recent connection.
8185 if (m_connman.GetExtraBlockRelayCount() > 0) {
8186 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0},
8187 next_youngest_peer{-1, 0};
8188
8189 m_connman.ForEachNode([&](CNode *pnode) {
8190 if (!pnode->IsBlockOnlyConn() || pnode->fDisconnect) {
8191 return;
8192 }
8193 if (pnode->GetId() > youngest_peer.first) {
8194 next_youngest_peer = youngest_peer;
8195 youngest_peer.first = pnode->GetId();
8196 youngest_peer.second = pnode->m_last_block_time;
8197 }
8198 });
8199
8200 NodeId to_disconnect = youngest_peer.first;
8201 if (youngest_peer.second > next_youngest_peer.second) {
8202 // Our newest block-relay-only peer gave us a block more recently;
8203 // disconnect our second youngest.
8204 to_disconnect = next_youngest_peer.first;
8205 }
8206
8207 m_connman.ForNode(
8208 to_disconnect,
8211 // Make sure we're not getting a block right now, and that we've
8212 // been connected long enough for this eviction to happen at
8213 // all. Note that we only request blocks from a peer if we learn
8214 // of a valid headers chain with at least as much work as our
8215 // tip.
8216 CNodeState *node_state = State(pnode->GetId());
8217 if (node_state == nullptr ||
8218 (now - pnode->m_connected >= MINIMUM_CONNECT_TIME &&
8219 node_state->vBlocksInFlight.empty())) {
8220 pnode->fDisconnect = true;
8222 "disconnecting extra block-relay-only peer=%d "
8223 "(last block received at time %d)\n",
8224 pnode->GetId(),
8226 return true;
8227 } else {
8228 LogPrint(
8229 BCLog::NET,
8230 "keeping block-relay-only peer=%d chosen for eviction "
8231 "(connect time: %d, blocks_in_flight: %d)\n",
8232 pnode->GetId(), count_seconds(pnode->m_connected),
8233 node_state->vBlocksInFlight.size());
8234 }
8235 return false;
8236 });
8237 }
8238
8239 // Check whether we have too many OUTBOUND_FULL_RELAY peers
8240 if (m_connman.GetExtraFullOutboundCount() <= 0) {
8241 return;
8242 }
8243
8244 // If we have more OUTBOUND_FULL_RELAY peers than we target, disconnect one.
8245 // Pick the OUTBOUND_FULL_RELAY peer that least recently announced us a new
8246 // block, with ties broken by choosing the more recent connection (higher
8247 // node id)
8248 NodeId worst_peer = -1;
8249 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
8250
8251 m_connman.ForEachNode([&](CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(
8252 ::cs_main) {
8254
8255 // Only consider OUTBOUND_FULL_RELAY peers that are not already marked
8256 // for disconnection
8257 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) {
8258 return;
8259 }
8260 CNodeState *state = State(pnode->GetId());
8261 if (state == nullptr) {
8262 // shouldn't be possible, but just in case
8263 return;
8264 }
8265 // Don't evict our protected peers
8266 if (state->m_chain_sync.m_protect) {
8267 return;
8268 }
8269 if (state->m_last_block_announcement < oldest_block_announcement ||
8270 (state->m_last_block_announcement == oldest_block_announcement &&
8271 pnode->GetId() > worst_peer)) {
8272 worst_peer = pnode->GetId();
8273 oldest_block_announcement = state->m_last_block_announcement;
8274 }
8275 });
8276
8277 if (worst_peer == -1) {
8278 return;
8279 }
8280
8281 bool disconnected = m_connman.ForNode(
8282 worst_peer, [&](CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
8284
8285 // Only disconnect a peer that has been connected to us for some
8286 // reasonable fraction of our check-frequency, to give it time for
8287 // new information to have arrived. Also don't disconnect any peer
8288 // we're trying to download a block from.
8289 CNodeState &state = *State(pnode->GetId());
8290 if (now - pnode->m_connected > MINIMUM_CONNECT_TIME &&
8291 state.vBlocksInFlight.empty()) {
8293 "disconnecting extra outbound peer=%d (last block "
8294 "announcement received at time %d)\n",
8295 pnode->GetId(), oldest_block_announcement);
8296 pnode->fDisconnect = true;
8297 return true;
8298 } else {
8300 "keeping outbound peer=%d chosen for eviction "
8301 "(connect time: %d, blocks_in_flight: %d)\n",
8302 pnode->GetId(), count_seconds(pnode->m_connected),
8303 state.vBlocksInFlight.size());
8304 return false;
8305 }
8306 });
8307
8308 if (disconnected) {
8309 // If we disconnected an extra peer, that means we successfully
8310 // connected to at least one peer after the last time we detected a
8311 // stale tip. Don't try any more extra peers until we next detect a
8312 // stale tip, to limit the load we put on the network from these extra
8313 // connections.
8314 m_connman.SetTryNewOutboundPeer(false);
8315 }
8316}
8317
8318void PeerManagerImpl::CheckForStaleTipAndEvictPeers() {
8319 LOCK(cs_main);
8320
8321 auto now{GetTime<std::chrono::seconds>()};
8322
8323 EvictExtraOutboundPeers(now);
8324
8325 if (now > m_stale_tip_check_time) {
8326 // Check whether our tip is stale, and if so, allow using an extra
8327 // outbound peer.
8328 if (!m_chainman.m_blockman.LoadingBlocks() &&
8329 m_connman.GetNetworkActive() && m_connman.GetUseAddrmanOutgoing() &&
8330 TipMayBeStale()) {
8331 LogPrintf("Potential stale tip detected, will try using extra "
8332 "outbound peer (last tip update: %d seconds ago)\n",
8333 count_seconds(now - m_last_tip_update.load()));
8334 m_connman.SetTryNewOutboundPeer(true);
8335 } else if (m_connman.GetTryNewOutboundPeer()) {
8336 m_connman.SetTryNewOutboundPeer(false);
8337 }
8338 m_stale_tip_check_time = now + STALE_CHECK_INTERVAL;
8339 }
8340
8341 if (!m_initial_sync_finished && CanDirectFetch()) {
8342 m_connman.StartExtraBlockRelayPeers();
8343 m_initial_sync_finished = true;
8344 }
8345}
8346
8347void PeerManagerImpl::MaybeSendPing(CNode &node_to, Peer &peer,
8348 std::chrono::microseconds now) {
8349 if (m_connman.ShouldRunInactivityChecks(
8350 node_to, std::chrono::duration_cast<std::chrono::seconds>(now)) &&
8351 peer.m_ping_nonce_sent &&
8352 now > peer.m_ping_start.load() + TIMEOUT_INTERVAL) {
8353 // The ping timeout is using mocktime. To disable the check during
8354 // testing, increase -peertimeout.
8355 LogPrint(BCLog::NET, "ping timeout: %fs peer=%d\n",
8356 0.000001 * count_microseconds(now - peer.m_ping_start.load()),
8357 peer.m_id);
8358 node_to.fDisconnect = true;
8359 return;
8360 }
8361
8362 bool pingSend = false;
8363
8364 if (peer.m_ping_queued) {
8365 // RPC ping request by user
8366 pingSend = true;
8367 }
8368
8369 if (peer.m_ping_nonce_sent == 0 &&
8370 now > peer.m_ping_start.load() + PING_INTERVAL) {
8371 // Ping automatically sent as a latency probe & keepalive.
8372 pingSend = true;
8373 }
8374
8375 if (pingSend) {
8376 uint64_t nonce;
8377 do {
8378 nonce = FastRandomContext().rand64();
8379 } while (nonce == 0);
8380 peer.m_ping_queued = false;
8381 peer.m_ping_start = now;
8382 if (node_to.GetCommonVersion() > BIP0031_VERSION) {
8383 peer.m_ping_nonce_sent = nonce;
8384 MakeAndPushMessage(node_to, NetMsgType::PING, nonce);
8385 } else {
8386 // Peer is too old to support ping command with nonce, pong will
8387 // never arrive.
8388 peer.m_ping_nonce_sent = 0;
8389 MakeAndPushMessage(node_to, NetMsgType::PING);
8390 }
8391 }
8392}
8393
8394void PeerManagerImpl::MaybeSendAddr(CNode &node, Peer &peer,
8395 std::chrono::microseconds current_time) {
8396 // Nothing to do for non-address-relay peers
8397 if (!peer.m_addr_relay_enabled) {
8398 return;
8399 }
8400
8401 LOCK(peer.m_addr_send_times_mutex);
8402 if (fListen && !m_chainman.IsInitialBlockDownload() &&
8403 peer.m_next_local_addr_send < current_time) {
8404 // If we've sent before, clear the bloom filter for the peer, so
8405 // that our self-announcement will actually go out. This might
8406 // be unnecessary if the bloom filter has already rolled over
8407 // since our last self-announcement, but there is only a small
8408 // bandwidth cost that we can incur by doing this (which happens
8409 // once a day on average).
8410 if (peer.m_next_local_addr_send != 0us) {
8411 peer.m_addr_known->reset();
8412 }
8413 if (std::optional<CService> local_service = GetLocalAddrForPeer(node)) {
8414 CAddress local_addr{*local_service, peer.m_our_services,
8415 Now<NodeSeconds>()};
8416 PushAddress(peer, local_addr);
8417 }
8418 peer.m_next_local_addr_send =
8419 current_time +
8420 m_rng.rand_exp_duration(AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
8421 }
8422
8423 // We sent an `addr` message to this peer recently. Nothing more to do.
8424 if (current_time <= peer.m_next_addr_send) {
8425 return;
8426 }
8427
8428 peer.m_next_addr_send =
8429 current_time + m_rng.rand_exp_duration(AVG_ADDRESS_BROADCAST_INTERVAL);
8430
8431 const size_t max_addr_to_send = m_opts.max_addr_to_send;
8432 if (!Assume(peer.m_addrs_to_send.size() <= max_addr_to_send)) {
8433 // Should be impossible since we always check size before adding to
8434 // m_addrs_to_send. Recover by trimming the vector.
8435 peer.m_addrs_to_send.resize(max_addr_to_send);
8436 }
8437
8438 // Remove addr records that the peer already knows about, and add new
8439 // addrs to the m_addr_known filter on the same pass.
8440 auto addr_already_known =
8441 [&peer](const CAddress &addr)
8442 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex) {
8443 bool ret = peer.m_addr_known->contains(addr.GetKey());
8444 if (!ret) {
8445 peer.m_addr_known->insert(addr.GetKey());
8446 }
8447 return ret;
8448 };
8449 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(),
8450 peer.m_addrs_to_send.end(),
8451 addr_already_known),
8452 peer.m_addrs_to_send.end());
8453
8454 // No addr messages to send
8455 if (peer.m_addrs_to_send.empty()) {
8456 return;
8457 }
8458
8459 const char *msg_type;
8460 CNetAddr::Encoding ser_enc;
8461 if (peer.m_wants_addrv2) {
8462 msg_type = NetMsgType::ADDRV2;
8463 ser_enc = CNetAddr::Encoding::V2;
8464 } else {
8465 msg_type = NetMsgType::ADDR;
8466 ser_enc = CNetAddr::Encoding::V1;
8467 }
8468 MakeAndPushMessage(
8469 node, msg_type,
8471 peer.m_addrs_to_send));
8472 peer.m_addrs_to_send.clear();
8473
8474 // we only send the big addr message once
8475 if (peer.m_addrs_to_send.capacity() > 40) {
8476 peer.m_addrs_to_send.shrink_to_fit();
8477 }
8478}
8479
8480void PeerManagerImpl::MaybeSendSendHeaders(CNode &node, Peer &peer) {
8481 // Delay sending SENDHEADERS (BIP 130) until we're done with an
8482 // initial-headers-sync with this peer. Receiving headers announcements for
8483 // new blocks while trying to sync their headers chain is problematic,
8484 // because of the state tracking done.
8485 if (!peer.m_sent_sendheaders &&
8486 node.GetCommonVersion() >= SENDHEADERS_VERSION) {
8487 LOCK(cs_main);
8488 CNodeState &state = *State(node.GetId());
8489 if (state.pindexBestKnownBlock != nullptr &&
8490 state.pindexBestKnownBlock->nChainWork >
8491 m_chainman.MinimumChainWork()) {
8492 // Tell our peer we prefer to receive headers rather than inv's
8493 // We send this to non-NODE NETWORK peers as well, because even
8494 // non-NODE NETWORK peers can announce blocks (such as pruning
8495 // nodes)
8496 MakeAndPushMessage(node, NetMsgType::SENDHEADERS);
8497 peer.m_sent_sendheaders = true;
8498 }
8499 }
8500}
8501
8502void PeerManagerImpl::MaybeSendFeefilter(
8503 CNode &pto, Peer &peer, std::chrono::microseconds current_time) {
8504 if (m_opts.ignore_incoming_txs) {
8505 return;
8506 }
8507 if (pto.GetCommonVersion() < FEEFILTER_VERSION) {
8508 return;
8509 }
8510 // peers with the forcerelay permission should not filter txs to us
8512 return;
8513 }
8514 // Don't send feefilter messages to outbound block-relay-only peers since
8515 // they should never announce transactions to us, regardless of feefilter
8516 // state.
8517 if (pto.IsBlockOnlyConn()) {
8518 return;
8519 }
8520
8521 Amount currentFilter = m_mempool.GetMinFee().GetFeePerK();
8522
8523 if (m_chainman.IsInitialBlockDownload()) {
8524 // Received tx-inv messages are discarded when the active
8525 // chainstate is in IBD, so tell the peer to not send them.
8526 currentFilter = MAX_MONEY;
8527 } else {
8528 static const Amount MAX_FILTER{m_fee_filter_rounder.round(MAX_MONEY)};
8529 if (peer.m_fee_filter_sent == MAX_FILTER) {
8530 // Send the current filter if we sent MAX_FILTER previously
8531 // and made it out of IBD.
8532 peer.m_next_send_feefilter = 0us;
8533 }
8534 }
8535 if (current_time > peer.m_next_send_feefilter) {
8536 Amount filterToSend = m_fee_filter_rounder.round(currentFilter);
8537 // We always have a fee filter of at least the min relay fee
8538 filterToSend =
8539 std::max(filterToSend, m_mempool.m_min_relay_feerate.GetFeePerK());
8540 if (filterToSend != peer.m_fee_filter_sent) {
8541 MakeAndPushMessage(pto, NetMsgType::FEEFILTER, filterToSend);
8542 peer.m_fee_filter_sent = filterToSend;
8543 }
8544 peer.m_next_send_feefilter =
8545 current_time +
8546 m_rng.rand_exp_duration(AVG_FEEFILTER_BROADCAST_INTERVAL);
8547 }
8548 // If the fee filter has changed substantially and it's still more than
8549 // MAX_FEEFILTER_CHANGE_DELAY until scheduled broadcast, then move the
8550 // broadcast to within MAX_FEEFILTER_CHANGE_DELAY.
8551 else if (current_time + MAX_FEEFILTER_CHANGE_DELAY <
8552 peer.m_next_send_feefilter &&
8553 (currentFilter < 3 * peer.m_fee_filter_sent / 4 ||
8554 currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
8555 peer.m_next_send_feefilter =
8556 current_time +
8557 FastRandomContext().randrange<std::chrono::microseconds>(
8559 }
8560}
8561
8562namespace {
8563class CompareInvMempoolOrder {
8564 CTxMemPool *mp;
8565
8566public:
8567 explicit CompareInvMempoolOrder(CTxMemPool *_mempool) : mp(_mempool) {}
8568
8569 bool operator()(std::set<TxId>::iterator a, std::set<TxId>::iterator b) {
8574 return mp->CompareTopologically(*b, *a);
8575 }
8576};
8577} // namespace
8578
8579bool PeerManagerImpl::RejectIncomingTxs(const CNode &peer) const {
8580 // block-relay-only peers may never send txs to us
8581 if (peer.IsBlockOnlyConn()) {
8582 return true;
8583 }
8584 if (peer.IsFeelerConn()) {
8585 return true;
8586 }
8587 // In -blocksonly mode, peers need the 'relay' permission to send txs to us
8588 if (m_opts.ignore_incoming_txs &&
8590 return true;
8591 }
8592 return false;
8593}
8594
8595bool PeerManagerImpl::SetupAddressRelay(const CNode &node, Peer &peer) {
8596 // We don't participate in addr relay with outbound block-relay-only
8597 // connections to prevent providing adversaries with the additional
8598 // information of addr traffic to infer the link.
8599 if (node.IsBlockOnlyConn()) {
8600 return false;
8601 }
8602
8603 if (!peer.m_addr_relay_enabled.exchange(true)) {
8604 // During version message processing (non-block-relay-only outbound
8605 // peers) or on first addr-related message we have received (inbound
8606 // peers), initialize m_addr_known.
8607 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
8608 }
8609
8610 return true;
8611}
8612
8613bool PeerManagerImpl::SendMessages(const Config &config, CNode *pto) {
8614 AssertLockHeld(g_msgproc_mutex);
8615
8616 PeerRef peer = GetPeerRef(pto->GetId());
8617 if (!peer) {
8618 return false;
8619 }
8620 const Consensus::Params &consensusParams = m_chainparams.GetConsensus();
8621
8622 // We must call MaybeDiscourageAndDisconnect first, to ensure that we'll
8623 // disconnect misbehaving peers even before the version handshake is
8624 // complete.
8625 if (MaybeDiscourageAndDisconnect(*pto, *peer)) {
8626 return true;
8627 }
8628
8629 // Don't send anything until the version handshake is complete
8630 if (!pto->fSuccessfullyConnected || pto->fDisconnect) {
8631 return true;
8632 }
8633
8634 const auto current_time{GetTime<std::chrono::microseconds>()};
8635
8636 if (pto->IsAddrFetchConn() &&
8637 current_time - pto->m_connected > 10 * AVG_ADDRESS_BROADCAST_INTERVAL) {
8639 "addrfetch connection timeout; disconnecting peer=%d\n",
8640 pto->GetId());
8641 pto->fDisconnect = true;
8642 return true;
8643 }
8644
8645 MaybeSendPing(*pto, *peer, current_time);
8646
8647 // MaybeSendPing may have marked peer for disconnection
8648 if (pto->fDisconnect) {
8649 return true;
8650 }
8651
8652 bool sync_blocks_and_headers_from_peer = false;
8653
8654 MaybeSendAddr(*pto, *peer, current_time);
8655
8656 MaybeSendSendHeaders(*pto, *peer);
8657
8658 {
8659 LOCK(cs_main);
8660
8661 CNodeState &state = *State(pto->GetId());
8662
8663 // Start block sync
8664 if (m_chainman.m_best_header == nullptr) {
8665 m_chainman.m_best_header = m_chainman.ActiveChain().Tip();
8666 }
8667
8668 // Determine whether we might try initial headers sync or parallel
8669 // block download from this peer -- this mostly affects behavior while
8670 // in IBD (once out of IBD, we sync from all peers).
8671 if (state.fPreferredDownload) {
8672 sync_blocks_and_headers_from_peer = true;
8673 } else if (CanServeBlocks(*peer) && !pto->IsAddrFetchConn()) {
8674 // Typically this is an inbound peer. If we don't have any outbound
8675 // peers, or if we aren't downloading any blocks from such peers,
8676 // then allow block downloads from this peer, too.
8677 // We prefer downloading blocks from outbound peers to avoid
8678 // putting undue load on (say) some home user who is just making
8679 // outbound connections to the network, but if our only source of
8680 // the latest blocks is from an inbound peer, we have to be sure to
8681 // eventually download it (and not just wait indefinitely for an
8682 // outbound peer to have it).
8683 if (m_num_preferred_download_peers == 0 ||
8684 mapBlocksInFlight.empty()) {
8685 sync_blocks_and_headers_from_peer = true;
8686 }
8687 }
8688
8689 if (!state.fSyncStarted && CanServeBlocks(*peer) &&
8690 !m_chainman.m_blockman.LoadingBlocks()) {
8691 // Only actively request headers from a single peer, unless we're
8692 // close to today.
8693 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) ||
8694 m_chainman.m_best_header->Time() > GetAdjustedTime() - 24h) {
8695 const CBlockIndex *pindexStart = m_chainman.m_best_header;
8704 if (pindexStart->pprev) {
8705 pindexStart = pindexStart->pprev;
8706 }
8707 if (MaybeSendGetHeaders(*pto, GetLocator(pindexStart), *peer)) {
8708 LogPrint(
8709 BCLog::NET,
8710 "initial getheaders (%d) to peer=%d (startheight:%d)\n",
8711 pindexStart->nHeight, pto->GetId(),
8712 peer->m_starting_height);
8713
8714 state.fSyncStarted = true;
8715 peer->m_headers_sync_timeout =
8716 current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE +
8717 (
8718 // Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to
8719 // microseconds before scaling to maintain precision
8720 std::chrono::microseconds{
8722 Ticks<std::chrono::seconds>(
8723 GetAdjustedTime() -
8724 m_chainman.m_best_header->Time()) /
8725 consensusParams.nPowTargetSpacing);
8726 nSyncStarted++;
8727 }
8728 }
8729 }
8730
8731 //
8732 // Try sending block announcements via headers
8733 //
8734 {
8735 // If we have less than MAX_BLOCKS_TO_ANNOUNCE in our list of block
8736 // hashes we're relaying, and our peer wants headers announcements,
8737 // then find the first header not yet known to our peer but would
8738 // connect, and send. If no header would connect, or if we have too
8739 // many blocks, or if the peer doesn't want headers, just add all to
8740 // the inv queue.
8741 LOCK(peer->m_block_inv_mutex);
8742 std::vector<CBlock> vHeaders;
8743 bool fRevertToInv =
8744 ((!peer->m_prefers_headers &&
8745 (!state.m_requested_hb_cmpctblocks ||
8746 peer->m_blocks_for_headers_relay.size() > 1)) ||
8747 peer->m_blocks_for_headers_relay.size() >
8749 // last header queued for delivery
8750 const CBlockIndex *pBestIndex = nullptr;
8751 // ensure pindexBestKnownBlock is up-to-date
8752 ProcessBlockAvailability(pto->GetId());
8753
8754 if (!fRevertToInv) {
8755 bool fFoundStartingHeader = false;
8756 // Try to find first header that our peer doesn't have, and then
8757 // send all headers past that one. If we come across an headers
8758 // that aren't on m_chainman.ActiveChain(), give up.
8759 for (const BlockHash &hash : peer->m_blocks_for_headers_relay) {
8760 const CBlockIndex *pindex =
8761 m_chainman.m_blockman.LookupBlockIndex(hash);
8762 assert(pindex);
8763 if (m_chainman.ActiveChain()[pindex->nHeight] != pindex) {
8764 // Bail out if we reorged away from this block
8765 fRevertToInv = true;
8766 break;
8767 }
8768 if (pBestIndex != nullptr && pindex->pprev != pBestIndex) {
8769 // This means that the list of blocks to announce don't
8770 // connect to each other. This shouldn't really be
8771 // possible to hit during regular operation (because
8772 // reorgs should take us to a chain that has some block
8773 // not on the prior chain, which should be caught by the
8774 // prior check), but one way this could happen is by
8775 // using invalidateblock / reconsiderblock repeatedly on
8776 // the tip, causing it to be added multiple times to
8777 // m_blocks_for_headers_relay. Robustly deal with this
8778 // rare situation by reverting to an inv.
8779 fRevertToInv = true;
8780 break;
8781 }
8782 pBestIndex = pindex;
8783 if (fFoundStartingHeader) {
8784 // add this to the headers message
8785 vHeaders.push_back(pindex->GetBlockHeader());
8786 } else if (PeerHasHeader(&state, pindex)) {
8787 // Keep looking for the first new block.
8788 continue;
8789 } else if (pindex->pprev == nullptr ||
8790 PeerHasHeader(&state, pindex->pprev)) {
8791 // Peer doesn't have this header but they do have the
8792 // prior one. Start sending headers.
8793 fFoundStartingHeader = true;
8794 vHeaders.push_back(pindex->GetBlockHeader());
8795 } else {
8796 // Peer doesn't have this header or the prior one --
8797 // nothing will connect, so bail out.
8798 fRevertToInv = true;
8799 break;
8800 }
8801 }
8802 }
8803 if (!fRevertToInv && !vHeaders.empty()) {
8804 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
8805 // We only send up to 1 block as header-and-ids, as
8806 // otherwise probably means we're doing an initial-ish-sync
8807 // or they're slow.
8809 "%s sending header-and-ids %s to peer=%d\n",
8810 __func__, vHeaders.front().GetHash().ToString(),
8811 pto->GetId());
8812
8813 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
8814 {
8815 LOCK(m_most_recent_block_mutex);
8816 if (m_most_recent_block_hash ==
8817 pBestIndex->GetBlockHash()) {
8818 cached_cmpctblock_msg =
8820 *m_most_recent_compact_block);
8821 }
8822 }
8823 if (cached_cmpctblock_msg.has_value()) {
8824 PushMessage(*pto,
8825 std::move(cached_cmpctblock_msg.value()));
8826 } else {
8827 CBlock block;
8828 const bool ret{m_chainman.m_blockman.ReadBlock(
8829 block, *pBestIndex)};
8830 assert(ret);
8831 CBlockHeaderAndShortTxIDs cmpctblock(
8832 block, FastRandomContext().rand64());
8833 MakeAndPushMessage(*pto, NetMsgType::CMPCTBLOCK,
8834 cmpctblock);
8835 }
8836 state.pindexBestHeaderSent = pBestIndex;
8837 } else if (peer->m_prefers_headers) {
8838 if (vHeaders.size() > 1) {
8840 "%s: %u headers, range (%s, %s), to peer=%d\n",
8841 __func__, vHeaders.size(),
8842 vHeaders.front().GetHash().ToString(),
8843 vHeaders.back().GetHash().ToString(),
8844 pto->GetId());
8845 } else {
8847 "%s: sending header %s to peer=%d\n", __func__,
8848 vHeaders.front().GetHash().ToString(),
8849 pto->GetId());
8850 }
8851 MakeAndPushMessage(*pto, NetMsgType::HEADERS, vHeaders);
8852 state.pindexBestHeaderSent = pBestIndex;
8853 } else {
8854 fRevertToInv = true;
8855 }
8856 }
8857 if (fRevertToInv) {
8858 // If falling back to using an inv, just try to inv the tip. The
8859 // last entry in m_blocks_for_headers_relay was our tip at some
8860 // point in the past.
8861 if (!peer->m_blocks_for_headers_relay.empty()) {
8862 const BlockHash &hashToAnnounce =
8863 peer->m_blocks_for_headers_relay.back();
8864 const CBlockIndex *pindex =
8865 m_chainman.m_blockman.LookupBlockIndex(hashToAnnounce);
8866 assert(pindex);
8867
8868 // Warn if we're announcing a block that is not on the main
8869 // chain. This should be very rare and could be optimized
8870 // out. Just log for now.
8871 if (m_chainman.ActiveChain()[pindex->nHeight] != pindex) {
8872 LogPrint(
8873 BCLog::NET,
8874 "Announcing block %s not on main chain (tip=%s)\n",
8875 hashToAnnounce.ToString(),
8876 m_chainman.ActiveChain()
8877 .Tip()
8878 ->GetBlockHash()
8879 .ToString());
8880 }
8881
8882 // If the peer's chain has this block, don't inv it back.
8883 if (!PeerHasHeader(&state, pindex)) {
8884 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
8886 "%s: sending inv peer=%d hash=%s\n", __func__,
8887 pto->GetId(), hashToAnnounce.ToString());
8888 }
8889 }
8890 }
8891 peer->m_blocks_for_headers_relay.clear();
8892 }
8893 } // release cs_main
8894
8895 //
8896 // Message: inventory
8897 //
8898 std::vector<CInv> vInv;
8899 auto addInvAndMaybeFlush = [&](uint32_t type, const uint256 &hash) {
8900 vInv.emplace_back(type, hash);
8901 if (vInv.size() == MAX_INV_SZ) {
8902 MakeAndPushMessage(*pto, NetMsgType::INV, std::move(vInv));
8903 vInv.clear();
8904 }
8905 };
8906
8907 {
8908 LOCK(cs_main);
8909
8910 {
8911 LOCK(peer->m_block_inv_mutex);
8912
8913 vInv.reserve(std::max<size_t>(peer->m_blocks_for_inv_relay.size(),
8915 config.GetMaxBlockSize() /
8916 1000000));
8917
8918 // Add blocks
8919 for (const BlockHash &hash : peer->m_blocks_for_inv_relay) {
8920 addInvAndMaybeFlush(MSG_BLOCK, hash);
8921 }
8922 peer->m_blocks_for_inv_relay.clear();
8923 }
8924
8925 auto computeNextInvSendTime =
8926 [&](std::chrono::microseconds &next)
8927 EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex) -> bool {
8928 bool fSendTrickle = pto->HasPermission(NetPermissionFlags::NoBan);
8929
8930 if (next < current_time) {
8931 fSendTrickle = true;
8932 if (pto->IsInboundConn()) {
8933 next = NextInvToInbounds(
8935 } else {
8936 // Skip delay for outbound peers, as there is less privacy
8937 // concern for them.
8938 next = current_time;
8939 }
8940 }
8941
8942 return fSendTrickle;
8943 };
8944
8945 // Add proofs to inventory
8946 if (peer->m_proof_relay != nullptr) {
8947 LOCK(peer->m_proof_relay->m_proof_inventory_mutex);
8948
8949 if (computeNextInvSendTime(
8950 peer->m_proof_relay->m_next_inv_send_time)) {
8951 auto it =
8952 peer->m_proof_relay->m_proof_inventory_to_send.begin();
8953 while (it !=
8954 peer->m_proof_relay->m_proof_inventory_to_send.end()) {
8955 const avalanche::ProofId proofid = *it;
8956
8957 it = peer->m_proof_relay->m_proof_inventory_to_send.erase(
8958 it);
8959
8960 if (peer->m_proof_relay->m_proof_inventory_known_filter
8961 .contains(proofid)) {
8962 continue;
8963 }
8964
8965 peer->m_proof_relay->m_proof_inventory_known_filter.insert(
8966 proofid);
8967 addInvAndMaybeFlush(MSG_AVA_PROOF, proofid);
8968 peer->m_proof_relay->m_recently_announced_proofs.insert(
8969 proofid);
8970 }
8971 }
8972 }
8973
8974 if (auto tx_relay = peer->GetTxRelay()) {
8975 LOCK(tx_relay->m_tx_inventory_mutex);
8976 // Check whether periodic sends should happen
8977 const bool fSendTrickle =
8978 computeNextInvSendTime(tx_relay->m_next_inv_send_time);
8979
8980 // Time to send but the peer has requested we not relay
8981 // transactions.
8982 if (fSendTrickle) {
8983 LOCK(tx_relay->m_bloom_filter_mutex);
8984 if (!tx_relay->m_relay_txs) {
8985 tx_relay->m_tx_inventory_to_send.clear();
8986 }
8987 }
8988
8989 // Respond to BIP35 mempool requests
8990 if (fSendTrickle && tx_relay->m_send_mempool) {
8991 auto vtxinfo = m_mempool.infoAll();
8992 tx_relay->m_send_mempool = false;
8993 const CFeeRate filterrate{
8994 tx_relay->m_fee_filter_received.load()};
8995
8996 LOCK(tx_relay->m_bloom_filter_mutex);
8997
8998 for (const auto &txinfo : vtxinfo) {
8999 const TxId &txid = txinfo.tx->GetId();
9000 tx_relay->m_tx_inventory_to_send.erase(txid);
9001 // Don't send transactions that peers will not put into
9002 // their mempool
9003 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
9004 continue;
9005 }
9006 if (tx_relay->m_bloom_filter &&
9007 !tx_relay->m_bloom_filter->IsRelevantAndUpdate(
9008 *txinfo.tx)) {
9009 continue;
9010 }
9011 tx_relay->m_tx_inventory_known_filter.insert(txid);
9012 // Responses to MEMPOOL requests bypass the
9013 // m_recently_announced_invs filter.
9014 addInvAndMaybeFlush(MSG_TX, txid);
9015 }
9016 tx_relay->m_last_mempool_req =
9017 std::chrono::duration_cast<std::chrono::seconds>(
9018 current_time);
9019 }
9020
9021 // Determine transactions to relay
9022 if (fSendTrickle) {
9023 // Produce a vector with all candidates for sending
9024 std::vector<std::set<TxId>::iterator> vInvTx;
9025 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
9026 for (std::set<TxId>::iterator it =
9027 tx_relay->m_tx_inventory_to_send.begin();
9028 it != tx_relay->m_tx_inventory_to_send.end(); it++) {
9029 vInvTx.push_back(it);
9030 }
9031 const CFeeRate filterrate{
9032 tx_relay->m_fee_filter_received.load()};
9033 // Send out the inventory in the order of admission to our
9034 // mempool, which is guaranteed to be a topological sort order.
9035 // A heap is used so that not all items need sorting if only a
9036 // few are being sent.
9037 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
9038 std::make_heap(vInvTx.begin(), vInvTx.end(),
9039 compareInvMempoolOrder);
9040 // No reason to drain out at many times the network's
9041 // capacity, especially since we have many peers and some
9042 // will draw much shorter delays.
9043 unsigned int nRelayedTransactions = 0;
9044 LOCK(tx_relay->m_bloom_filter_mutex);
9045 while (!vInvTx.empty() &&
9046 nRelayedTransactions < INVENTORY_BROADCAST_MAX_PER_MB *
9047 config.GetMaxBlockSize() /
9048 1000000) {
9049 // Fetch the top element from the heap
9050 std::pop_heap(vInvTx.begin(), vInvTx.end(),
9051 compareInvMempoolOrder);
9052 std::set<TxId>::iterator it = vInvTx.back();
9053 vInvTx.pop_back();
9054 const TxId txid = *it;
9055 // Remove it from the to-be-sent set
9056 tx_relay->m_tx_inventory_to_send.erase(it);
9057 // Check if not in the filter already
9058 if (tx_relay->m_tx_inventory_known_filter.contains(txid) &&
9059 tx_relay->m_avalanche_stalled_txids.count(txid) == 0) {
9060 continue;
9061 }
9062 // Not in the mempool anymore? don't bother sending it.
9063 auto txinfo = m_mempool.info(txid);
9064 if (!txinfo.tx) {
9065 continue;
9066 }
9067 // Peer told you to not send transactions at that
9068 // feerate? Don't bother sending it.
9069 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
9070 continue;
9071 }
9072 if (tx_relay->m_bloom_filter &&
9073 !tx_relay->m_bloom_filter->IsRelevantAndUpdate(
9074 *txinfo.tx)) {
9075 continue;
9076 }
9077 // Send
9078 tx_relay->m_recently_announced_invs.insert(txid);
9079 addInvAndMaybeFlush(MSG_TX, txid);
9080 nRelayedTransactions++;
9081 tx_relay->m_tx_inventory_known_filter.insert(txid);
9082 tx_relay->m_avalanche_stalled_txids.erase(txid);
9083 }
9084 }
9085 }
9086 } // release cs_main
9087
9088 if (!vInv.empty()) {
9089 MakeAndPushMessage(*pto, NetMsgType::INV, vInv);
9090 }
9091
9092 {
9093 LOCK(cs_main);
9094
9095 CNodeState &state = *State(pto->GetId());
9096
9097 // Detect whether we're stalling
9098 auto stalling_timeout = m_block_stalling_timeout.load();
9099 if (state.m_stalling_since.count() &&
9100 state.m_stalling_since < current_time - stalling_timeout) {
9101 // Stalling only triggers when the block download window cannot
9102 // move. During normal steady state, the download window should be
9103 // much larger than the to-be-downloaded set of blocks, so
9104 // disconnection should only happen during initial block download.
9105 LogPrintf("Peer=%d is stalling block download, disconnecting\n",
9106 pto->GetId());
9107 pto->fDisconnect = true;
9108 // Increase timeout for the next peer so that we don't disconnect
9109 // multiple peers if our own bandwidth is insufficient.
9110 const auto new_timeout =
9111 std::min(2 * stalling_timeout, BLOCK_STALLING_TIMEOUT_MAX);
9112 if (stalling_timeout != new_timeout &&
9113 m_block_stalling_timeout.compare_exchange_strong(
9114 stalling_timeout, new_timeout)) {
9115 LogPrint(
9116 BCLog::NET,
9117 "Increased stalling timeout temporarily to %d seconds\n",
9118 count_seconds(new_timeout));
9119 }
9120 return true;
9121 }
9122 // In case there is a block that has been in flight from this peer for
9123 // block_interval * (1 + 0.5 * N) (with N the number of peers from which
9124 // we're downloading validated blocks), disconnect due to timeout.
9125 // We compensate for other peers to prevent killing off peers due to our
9126 // own downstream link being saturated. We only count validated
9127 // in-flight blocks so peers can't advertise non-existing block hashes
9128 // to unreasonably increase our timeout.
9129 if (state.vBlocksInFlight.size() > 0) {
9130 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
9131 int nOtherPeersWithValidatedDownloads =
9132 m_peers_downloading_from - 1;
9133 if (current_time >
9134 state.m_downloading_since +
9135 std::chrono::seconds{consensusParams.nPowTargetSpacing} *
9138 nOtherPeersWithValidatedDownloads)) {
9139 LogPrintf("Timeout downloading block %s from peer=%d, "
9140 "disconnecting\n",
9141 queuedBlock.pindex->GetBlockHash().ToString(),
9142 pto->GetId());
9143 pto->fDisconnect = true;
9144 return true;
9145 }
9146 }
9147
9148 // Check for headers sync timeouts
9149 if (state.fSyncStarted &&
9150 peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
9151 // Detect whether this is a stalling initial-headers-sync peer
9152 if (m_chainman.m_best_header->Time() <= GetAdjustedTime() - 24h) {
9153 if (current_time > peer->m_headers_sync_timeout &&
9154 nSyncStarted == 1 &&
9155 (m_num_preferred_download_peers -
9156 state.fPreferredDownload >=
9157 1)) {
9158 // Disconnect a peer (without NetPermissionFlags::NoBan
9159 // permission) if it is our only sync peer, and we have
9160 // others we could be using instead. Note: If all our peers
9161 // are inbound, then we won't disconnect our sync peer for
9162 // stalling; we have bigger problems if we can't get any
9163 // outbound peers.
9165 LogPrintf("Timeout downloading headers from peer=%d, "
9166 "disconnecting\n",
9167 pto->GetId());
9168 pto->fDisconnect = true;
9169 return true;
9170 } else {
9171 LogPrintf("Timeout downloading headers from noban "
9172 "peer=%d, not disconnecting\n",
9173 pto->GetId());
9174 // Reset the headers sync state so that we have a chance
9175 // to try downloading from a different peer. Note: this
9176 // will also result in at least one more getheaders
9177 // message to be sent to this peer (eventually).
9178 state.fSyncStarted = false;
9179 nSyncStarted--;
9180 peer->m_headers_sync_timeout = 0us;
9181 }
9182 }
9183 } else {
9184 // After we've caught up once, reset the timeout so we can't
9185 // trigger disconnect later.
9186 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
9187 }
9188 }
9189
9190 // Check that outbound peers have reasonable chains GetTime() is used by
9191 // this anti-DoS logic so we can test this using mocktime.
9192 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
9193 } // release cs_main
9194
9195 std::vector<CInv> vGetData;
9196
9197 //
9198 // Message: getdata (blocks)
9199 //
9200 {
9201 LOCK(cs_main);
9202
9203 CNodeState &state = *State(pto->GetId());
9204
9205 if (CanServeBlocks(*peer) &&
9206 ((sync_blocks_and_headers_from_peer && !IsLimitedPeer(*peer)) ||
9207 !m_chainman.IsInitialBlockDownload()) &&
9208 state.vBlocksInFlight.size() < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
9209 std::vector<const CBlockIndex *> vToDownload;
9210 NodeId staller = -1;
9211 auto get_inflight_budget = [&state]() {
9212 return std::max(
9214 static_cast<int>(state.vBlocksInFlight.size()));
9215 };
9216
9217 // If a snapshot chainstate is in use, we want to find its next
9218 // blocks before the background chainstate to prioritize getting to
9219 // network tip.
9220 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload,
9221 staller);
9222 if (m_chainman.BackgroundSyncInProgress() &&
9223 !IsLimitedPeer(*peer)) {
9224 // If the background tip is not an ancestor of the snapshot
9225 // block, we need to start requesting blocks from their last
9226 // common ancestor.
9227 const CBlockIndex *from_tip =
9229 m_chainman.GetSnapshotBaseBlock());
9230
9231 TryDownloadingHistoricalBlocks(
9232 *peer, get_inflight_budget(), vToDownload, from_tip,
9233 Assert(m_chainman.GetSnapshotBaseBlock()));
9234 }
9235 for (const CBlockIndex *pindex : vToDownload) {
9236 vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
9237 BlockRequested(config, pto->GetId(), *pindex);
9238 LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n",
9239 pindex->GetBlockHash().ToString(), pindex->nHeight,
9240 pto->GetId());
9241 }
9242 if (state.vBlocksInFlight.empty() && staller != -1) {
9243 if (State(staller)->m_stalling_since == 0us) {
9244 State(staller)->m_stalling_since = current_time;
9245 LogPrint(BCLog::NET, "Stall started peer=%d\n", staller);
9246 }
9247 }
9248 }
9249 } // release cs_main
9250
9251 auto addGetDataAndMaybeFlush = [&](uint32_t type, const uint256 &hash) {
9252 CInv inv(type, hash);
9253 LogPrint(BCLog::NET, "Requesting %s from peer=%d\n", inv.ToString(),
9254 pto->GetId());
9255 vGetData.push_back(std::move(inv));
9256 if (vGetData.size() >= MAX_GETDATA_SZ) {
9257 MakeAndPushMessage(*pto, NetMsgType::GETDATA, std::move(vGetData));
9258 vGetData.clear();
9259 }
9260 };
9261
9262 //
9263 // Message: getdata (proof)
9264 //
9265 if (m_avalanche) {
9266 LOCK(cs_proofrequest);
9267 std::vector<std::pair<NodeId, avalanche::ProofId>> expired;
9268 auto requestable =
9269 m_proofrequest.GetRequestable(pto->GetId(), current_time, &expired);
9270 for (const auto &entry : expired) {
9272 "timeout of inflight proof %s from peer=%d\n",
9273 entry.second.ToString(), entry.first);
9274 }
9275 for (const auto &proofid : requestable) {
9276 if (!AlreadyHaveProof(proofid)) {
9277 addGetDataAndMaybeFlush(MSG_AVA_PROOF, proofid);
9278 m_proofrequest.RequestedData(
9279 pto->GetId(), proofid,
9280 current_time + PROOF_REQUEST_PARAMS.getdata_interval);
9281 } else {
9282 // We have already seen this proof, no need to download.
9283 // This is just a belt-and-suspenders, as this should
9284 // already be called whenever a proof becomes
9285 // AlreadyHaveProof().
9286 m_proofrequest.ForgetInvId(proofid);
9287 }
9288 }
9289 }
9290
9291 //
9292 // Message: getdata (transactions)
9293 //
9294 {
9295 LOCK(cs_main);
9296 std::vector<std::pair<NodeId, TxId>> expired;
9297 auto requestable =
9298 m_txrequest.GetRequestable(pto->GetId(), current_time, &expired);
9299 for (const auto &entry : expired) {
9300 LogPrint(BCLog::NET, "timeout of inflight tx %s from peer=%d\n",
9301 entry.second.ToString(), entry.first);
9302 }
9303 for (const TxId &txid : requestable) {
9304 // Exclude m_recent_rejects_package_reconsiderable: we may be
9305 // requesting a missing parent that was previously rejected for
9306 // being too low feerate.
9307 if (!AlreadyHaveTx(txid, /*include_reconsiderable=*/false)) {
9308 addGetDataAndMaybeFlush(MSG_TX, txid);
9309 m_txrequest.RequestedData(
9310 pto->GetId(), txid,
9311 current_time + TX_REQUEST_PARAMS.getdata_interval);
9312 } else {
9313 // We have already seen this transaction, no need to download.
9314 // This is just a belt-and-suspenders, as this should already be
9315 // called whenever a transaction becomes AlreadyHaveTx().
9316 m_txrequest.ForgetInvId(txid);
9317 }
9318 }
9319
9320 if (!vGetData.empty()) {
9321 MakeAndPushMessage(*pto, NetMsgType::GETDATA, vGetData);
9322 }
9323
9324 } // release cs_main
9325 MaybeSendFeefilter(*pto, *peer, current_time);
9326 return true;
9327}
9328
9329bool PeerManagerImpl::ReceivedAvalancheProof(CNode &node, Peer &peer,
9330 const avalanche::ProofRef &proof) {
9331 assert(proof != nullptr);
9332
9333 const avalanche::ProofId &proofid = proof->getId();
9334
9335 AddKnownProof(peer, proofid);
9336
9337 if (m_chainman.IsInitialBlockDownload()) {
9338 // We cannot reliably verify proofs during IBD, so bail out early and
9339 // keep the inventory as pending so it can be requested when the node
9340 // has synced.
9341 return true;
9342 }
9343
9344 const NodeId nodeid = node.GetId();
9345
9346 const bool isStaker = WITH_LOCK(node.cs_avalanche_pubkey,
9347 return node.m_avalanche_pubkey.has_value());
9348 auto saveProofIfStaker = [this, isStaker](const CNode &node,
9349 const avalanche::ProofId &proofid,
9350 const NodeId nodeid) -> bool {
9351 if (isStaker) {
9352 return m_avalanche->withPeerManager(
9353 [&](avalanche::PeerManager &pm) {
9354 return pm.saveRemoteProof(proofid, nodeid, true);
9355 });
9356 }
9357
9358 return false;
9359 };
9360
9361 {
9362 LOCK(cs_proofrequest);
9363 m_proofrequest.ReceivedResponse(nodeid, proofid);
9364
9365 if (AlreadyHaveProof(proofid)) {
9366 m_proofrequest.ForgetInvId(proofid);
9367 saveProofIfStaker(node, proofid, nodeid);
9368 return true;
9369 }
9370 }
9371
9372 // registerProof should not be called while cs_proofrequest because it
9373 // holds cs_main and that creates a potential deadlock during shutdown
9374
9376 if (m_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
9377 return pm.registerProof(proof, state);
9378 })) {
9379 WITH_LOCK(cs_proofrequest, m_proofrequest.ForgetInvId(proofid));
9380 RelayProof(proofid);
9381
9382 node.m_last_proof_time = GetTime<std::chrono::seconds>();
9383
9384 LogPrint(BCLog::NET, "New avalanche proof: peer=%d, proofid %s\n",
9385 nodeid, proofid.ToString());
9386 }
9387
9389 m_avalanche->withPeerManager(
9390 [&](avalanche::PeerManager &pm) { pm.setInvalid(proofid); });
9391 Misbehaving(peer, state.GetRejectReason());
9392 return false;
9393 }
9394
9396 // This is possible that a proof contains a utxo we don't know yet, so
9397 // don't ban for this.
9398 return false;
9399 }
9400
9401 // Unlike other reasons we can expect lots of peers to send a proof that we
9402 // have dangling. In this case we don't want to print a lot of useless debug
9403 // message, the proof will be polled as soon as it's considered again.
9404 if (!m_avalanche->reconcileOrFinalize(proof) &&
9407 "Not polling the avalanche proof (%s): peer=%d, proofid %s\n",
9408 state.IsValid() ? "not-worth-polling"
9409 : state.GetRejectReason(),
9410 nodeid, proofid.ToString());
9411 }
9412
9413 saveProofIfStaker(node, proofid, nodeid);
9414 return true;
9415}
bool MoneyRange(const Amount nValue)
Definition: amount.h:171
static constexpr Amount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition: amount.h:170
@ READ_STATUS_OK
@ READ_STATUS_INVALID
@ READ_STATUS_FAILED
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterType
Definition: blockfilter.h:88
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
@ CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ SCRIPTS
Scripts & signatures ok.
@ TREE
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
arith_uint256 GetBlockProof(const CBlockIndex &block)
Definition: chain.cpp:74
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
Definition: chain.cpp:41
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params &params)
Return the time it would take to redo the work difference between from and to, assuming the current h...
Definition: chain.cpp:89
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
Definition: chain.cpp:112
#define Assert(val)
Identity function.
Definition: check.h:84
#define Assume(val)
Assume is the identity function.
Definition: check.h:97
Stochastic address manager.
Definition: addrman.h:68
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
Definition: addrman.cpp:1321
void Good(const CService &addr, bool test_before_evict=true, NodeSeconds time=Now< NodeSeconds >())
Mark an entry as accessible, possibly moving it from "new" to "tried".
Definition: addrman.cpp:1294
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
Definition: addrman.cpp:1289
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
Definition: addrman.cpp:1325
Definition: banman.h:59
void Discourage(const CNetAddr &net_addr)
Definition: banman.cpp:116
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
Definition: banman.cpp:83
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
Definition: banman.cpp:78
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< CTransactionRef > txn
std::vector< uint32_t > indices
A CService with information about it as peer.
Definition: protocol.h:442
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
Definition: protocol.h:554
static constexpr SerParams V1_NETWORK
Definition: protocol.h:495
NodeSeconds nTime
Always included in serialization, except in the network format on INIT_PROTO_VERSION.
Definition: protocol.h:552
static constexpr SerParams V2_NETWORK
Definition: protocol.h:497
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:23
BlockHash GetHash() const
Definition: block.cpp:11
uint32_t nTime
Definition: block.h:29
BlockHash hashPrevBlock
Definition: block.h:27
Definition: block.h:60
std::vector< CTransactionRef > vtx
Definition: block.h:63
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:25
bool IsValid(enum BlockValidity nUpTo=BlockValidity::TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
Definition: blockindex.h:191
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: blockindex.h:32
CBlockHeader GetBlockHeader() const
Definition: blockindex.h:117
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
Definition: blockindex.h:51
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
Definition: blockindex.h:154
int64_t GetBlockTime() const
Definition: blockindex.h:160
unsigned int nTx
Number of transactions in this block.
Definition: blockindex.h:55
NodeSeconds Time() const
Definition: blockindex.h:156
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: blockindex.cpp:62
BlockHash GetBlockHash() const
Definition: blockindex.h:130
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: blockindex.h:38
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
Definition: blockindex.h:97
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
Definition: bloom.h:44
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
Definition: bloom.cpp:93
An in-memory indexed chain of blocks.
Definition: chain.h:138
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:154
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
Definition: chain.h:178
int Height() const
Return the maximal height in the chain.
Definition: chain.h:190
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition: chain.h:170
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:86
const CBlock & GenesisBlock() const
Definition: chainparams.h:112
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:98
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:358
CCoinsView that brings transactions from a mempool into view.
Definition: txmempool.h:652
Definition: net.h:841
void ForEachNode(const NodeFn &func)
Definition: net.h:947
bool OutboundTargetReached(bool historicalBlockServingLimit) const
check if the outbound target is reached.
Definition: net.cpp:3009
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
Definition: net.cpp:3204
bool GetNetworkActive() const
Definition: net.h:933
bool GetTryNewOutboundPeer() const
Definition: net.cpp:1729
void SetTryNewOutboundPeer(bool flag)
Definition: net.cpp:1733
int GetExtraBlockRelayCount() const
Definition: net.cpp:1761
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
Definition: net.cpp:1558
void StartExtraBlockRelayPeers()
Definition: net.h:992
bool DisconnectNode(const std::string &node)
Definition: net.cpp:2920
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
Definition: net.cpp:3216
int GetExtraFullOutboundCount() const
Definition: net.cpp:1745
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network) const
Return all or many randomly selected addresses, optionally by network.
Definition: net.cpp:2788
bool CheckIncomingNonce(uint64_t nonce)
Definition: net.cpp:399
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
Definition: net.cpp:1289
bool GetUseAddrmanOutgoing() const
Definition: net.h:934
Fee rate in satoshis per kilobyte: Amount / kB.
Definition: feerate.h:21
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:54
Inv(ventory) message data.
Definition: protocol.h:589
bool IsMsgCmpctBlk() const
Definition: protocol.h:628
bool IsMsgBlk() const
Definition: protocol.h:620
std::string ToString() const
Definition: protocol.cpp:191
uint32_t type
Definition: protocol.h:591
bool IsMsgTx() const
Definition: protocol.h:608
bool IsMsgStakeContender() const
Definition: protocol.h:616
bool IsMsgFilteredBlk() const
Definition: protocol.h:624
uint256 hash
Definition: protocol.h:592
bool IsMsgProof() const
Definition: protocol.h:612
bool IsGenBlkMsg() const
Definition: protocol.h:633
void TransactionInvalidated(const CTransactionRef &tx, std::shared_ptr< const std::vector< Coin > > spent_coins)
Used to create a Merkle proof (usually from a subset of transactions), which consists of a block head...
Definition: merkleblock.h:147
std::vector< std::pair< size_t, uint256 > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
Definition: merkleblock.h:159
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
Definition: netaddress.h:245
bool IsRoutable() const
Definition: netaddress.cpp:516
static constexpr SerParams V1
Definition: netaddress.h:255
bool IsValid() const
Definition: netaddress.cpp:477
bool IsLocal() const
Definition: netaddress.cpp:451
@ V2
BIP155 encoding.
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Definition: netaddress.cpp:532
Transport protocol agnostic message container.
Definition: net.h:262
Information about a peer.
Definition: net.h:395
Mutex cs_avalanche_pubkey
Definition: net.h:590
bool IsFeelerConn() const
Definition: net.h:521
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
Definition: net.h:432
bool ExpectServicesFromConn() const
Definition: net.h:535
std::atomic< int > nVersion
Definition: net.h:442
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
Definition: net.h:573
bool IsInboundConn() const
Definition: net.h:527
bool HasPermission(NetPermissionFlags permission) const
Definition: net.h:455
bool IsOutboundOrBlockRelayConn() const
Definition: net.h:494
NodeId GetId() const
Definition: net.h:690
bool IsManualConn() const
Definition: net.h:515
std::atomic< int64_t > nTimeOffset
Definition: net.h:433
const std::string m_addr_name
Definition: net.h:438
std::string ConnectionTypeAsString() const
Definition: net.h:736
void SetCommonVersion(int greatest_common_version)
Definition: net.h:712
std::atomic< bool > m_bip152_highbandwidth_to
Definition: net.h:565
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
Definition: net.h:579
std::atomic< bool > m_bip152_highbandwidth_from
Definition: net.h:567
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
Definition: net.h:685
std::atomic_bool fSuccessfullyConnected
Definition: net.h:458
bool IsAddrFetchConn() const
Definition: net.h:523
uint64_t GetLocalNonce() const
Definition: net.h:692
const CAddress addr
Definition: net.h:435
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
Definition: net.cpp:631
bool IsBlockOnlyConn() const
Definition: net.h:517
int GetCommonVersion() const
Definition: net.h:716
bool IsFullOutboundConn() const
Definition: net.h:510
uint64_t nRemoteHostNonce
Definition: net.h:444
Mutex m_subver_mutex
cleanSubVer is a sanitized string of the user agent byte array we read from the wire.
Definition: net.h:451
std::atomic_bool fPauseSend
Definition: net.h:467
std::chrono::seconds m_nextGetAvaAddr
Definition: net.h:620
uint64_t nRemoteExtraEntropy
Definition: net.h:446
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
Definition: net.cpp:3138
uint64_t GetLocalExtraEntropy() const
Definition: net.h:693
SteadyMilliseconds m_last_poll
Definition: net.h:636
double getAvailabilityScore() const
Definition: net.cpp:3079
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
Definition: net.h:585
void updateAvailabilityScore(double decayFactor)
The availability score is calculated using an exponentially weighted average.
Definition: net.cpp:3064
std::atomic< std::chrono::seconds > m_avalanche_last_message_fault
Definition: net.h:623
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e.
Definition: net.h:441
std::atomic< int > m_avalanche_message_fault_counter
How much faulty messages did this node accumulate.
Definition: net.h:628
std::atomic< bool > m_avalanche_enabled
Definition: net.h:588
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
Definition: net.h:645
std::atomic_bool fDisconnect
Definition: net.h:461
std::atomic< int > m_avalanche_message_fault_score
This score is incremented for every new faulty message received when m_avalanche_message_fault_counte...
Definition: net.h:634
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
Definition: net.h:653
void invsVoted(uint32_t count)
The node voted for count invs.
Definition: net.cpp:3060
bool IsAvalancheOutboundConnection() const
Definition: net.h:531
An encapsulated public key.
Definition: pubkey.h:31
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Definition: bloom.h:115
Simple class for background tasks that should be run periodically or once "after a while".
Definition: scheduler.h:41
void scheduleEvery(Predicate p, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat p until it return false.
Definition: scheduler.cpp:115
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
Definition: scheduler.h:56
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:573
std::vector< uint8_t > GetKey() const
std::string ToStringAddrPort() const
SipHash-2-4.
Definition: siphash.h:14
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
Definition: siphash.cpp:83
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
Definition: siphash.cpp:36
std::set< std::reference_wrapper< const CTxMemPoolEntryRef >, CompareIteratorById > Parents
Definition: mempool_entry.h:70
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:221
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:300
void RemoveUnbroadcastTx(const TxId &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
Definition: txmempool.cpp:825
CFeeRate GetMinFee() const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
Definition: txmempool.h:463
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition: txmempool.h:317
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:269
bool CompareTopologically(const TxId &txida, const TxId &txidb) const
Definition: txmempool.cpp:503
TxMempoolInfo info(const TxId &txid) const
Definition: txmempool.cpp:686
size_t DynamicMemoryUsage() const
Definition: txmempool.cpp:814
bool setAvalancheFinalized(const CTxMemPoolEntryRef &tx, const Consensus::Params &params, const CBlockIndex &active_chain_tip, std::vector< TxId > &finalizedTxIds) EXCLUSIVE_LOCKS_REQUIRED(bool isAvalancheFinalizedPreConsensus(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:546
std::vector< TxMempoolInfo > infoAll() const
Definition: txmempool.cpp:535
CTransactionRef GetConflictTx(const COutPoint &prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Get the transaction in the pool that spends the same prevout.
Definition: txmempool.cpp:739
bool exists(const TxId &txid) const
Definition: txmempool.h:535
std::set< TxId > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
Definition: txmempool.h:574
auto withOrphanage(Callable &&func) const EXCLUSIVE_LOCKS_REQUIRED(!cs_orphanage)
Definition: txmempool.h:595
const CFeeRate m_min_relay_feerate
Definition: txmempool.h:356
auto withConflicting(Callable &&func) const EXCLUSIVE_LOCKS_REQUIRED(!cs_conflicting)
Definition: txmempool.h:603
void removeForFinalizedBlock(const std::unordered_set< TxId, SaltedTxIdHasher > &confirmedTxIdsInNonFinalizedBlocks) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:328
unsigned long size() const
Definition: txmempool.h:500
std::optional< txiter > GetIter(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given txid, if found.
Definition: txmempool.cpp:744
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void BlockConnected(ChainstateRole role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1191
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
Definition: validation.h:1442
const CBlockIndex * GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The tip of the background sync chain.
Definition: validation.h:1462
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block, avalanche::Processor *const avalanche=nullptr) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
Definition: validation.h:1323
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Definition: validation.h:1449
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
Definition: validation.h:1456
bool ProcessNewBlockHeaders(const std::vector< CBlockHeader > &block, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr, const std::optional< CCheckpointData > &test_checkpoints=std::nullopt) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const arith_uint256 & MinimumChainWork() const
Definition: validation.h:1293
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Definition: validation.h:1443
void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
Check to see if caches are out of balance and if so, call ResizeCoinsCaches() as needed.
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:1332
Definition: config.h:19
virtual uint64_t GetMaxBlockSize() const =0
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:118
bool empty() const
Definition: streams.h:152
size_type size() const
Definition: streams.h:151
void ignore(size_t num_ignore)
Definition: streams.h:276
int in_avail() const
Definition: streams.h:255
Fast randomness source.
Definition: random.h:411
uint64_t rand64() noexcept
Generate a random 64-bit integer.
Definition: random.h:432
Reads data from an underlying stream, while hashing the read data.
Definition: hash.h:150
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:99
HeadersSyncState:
Definition: headerssync.h:98
@ FINAL
We're done syncing with this peer and can discard any remaining state.
@ PRESYNC
PRESYNC means the peer has not yet demonstrated their chain has sufficient work and we're only buildi...
size_t Count(NodeId peer) const
Count how many announcements a peer has (REQUESTED, CANDIDATE, and COMPLETED combined).
Definition: invrequest.h:309
size_t CountInFlight(NodeId peer) const
Count how many REQUESTED announcements a peer has.
Definition: invrequest.h:296
Interface for message handling.
Definition: net.h:790
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
Definition: net.h:795
virtual bool ProcessMessages(const Config &config, CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual bool SendMessages(const Config &config, CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void InitializeNode(const Config &config, CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state, queue any initial messages)
virtual void FinalizeNode(const Config &config, const CNode &node)=0
Handle removal of a peer (clear state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< CTransactionRef > &extra_txn)
bool IsTxAvailable(size_t index) const
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
virtual std::optional< std::string > FetchBlock(const Config &config, NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual void SendPings()=0
Send ping message to all peers.
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, avalanche::Processor *const avalanche, Options opts)
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
virtual bool IgnoresIncomingTxs()=0
Whether this node ignores txs received over p2p.
virtual void ProcessMessage(const Config &config, CNode &pfrom, const std::string &msg_type, DataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void UnitTestMisbehaving(const NodeId peer_id)=0
Public for unit testing.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests....
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
Definition: rcu.h:112
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
Definition: random.h:266
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:94
int EraseTx(const TxId &txid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase a tx by txid.
Definition: txpool.cpp:50
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase all txs announced by a peer (eg, after that peer disconnects)
Definition: txpool.cpp:94
std::vector< CTransactionRef > GetChildrenFromSamePeer(const CTransactionRef &parent, NodeId nodeid) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get all children that spend from this tx and were received from nodeid.
Definition: txpool.cpp:281
bool AddTx(const CTransactionRef &tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a new transaction to the pool.
Definition: txpool.cpp:15
unsigned int LimitTxs(unsigned int max_txs, FastRandomContext &rng) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Limit the txs to the given maximum.
Definition: txpool.cpp:115
void EraseForBlock(const CBlock &block) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase all txs included in or invalidated by a new block.
Definition: txpool.cpp:239
std::vector< CTransactionRef > GetConflictTxs(const CTransactionRef &tx) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Definition: txpool.cpp:191
void AddChildrenToWorkSet(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add any tx that list a particular tx as a parent into the from peer's work set.
Definition: txpool.cpp:151
std::vector< std::pair< CTransactionRef, NodeId > > GetChildrenFromDifferentPeer(const CTransactionRef &parent, NodeId nodeid) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get all children that spend from this tx but were not received from nodeid.
Definition: txpool.cpp:326
bool IsValid() const
Definition: validation.h:119
std::string GetRejectReason() const
Definition: validation.h:123
Result GetResult() const
Definition: validation.h:122
std::string ToString() const
Definition: validation.h:125
bool IsInvalid() const
Definition: validation.h:120
256-bit unsigned big integer.
const std::vector< PrefilledProof > & getPrefilledProofs() const
Definition: compactproofs.h:76
uint64_t getShortID(const ProofId &proofid) const
const std::vector< uint64_t > & getShortIDs() const
Definition: compactproofs.h:79
ProofId getProofId() const
Definition: delegation.cpp:56
bool verify(DelegationState &state, CPubKey &auth) const
Definition: delegation.cpp:73
const DelegationId & getId() const
Definition: delegation.h:59
const LimitedProofId & getLimitedProofId() const
Definition: delegation.h:60
bool addNode(NodeId nodeid, const ProofId &proofid, size_t max_elements)
Node API.
Definition: peermanager.cpp:33
bool shouldRequestMoreNodes()
Returns true if we encountered a lack of node since the last call.
Definition: peermanager.h:338
bool exists(const ProofId &proofid) const
Return true if the (valid) proof exists, but only for non-dangling proofs.
Definition: peermanager.h:413
bool forPeer(const ProofId &proofid, Callable &&func) const
Definition: peermanager.h:421
void removeUnbroadcastProof(const ProofId &proofid)
const ProofRadixTree & getShareableProofsSnapshot() const
Definition: peermanager.h:528
bool isBoundToPeer(const ProofId &proofid) const
bool saveRemoteProof(const ProofId &proofid, const NodeId nodeid, const bool present)
void forEachPeer(Callable &&func) const
Definition: peermanager.h:427
void setInvalid(const ProofId &proofid)
bool isInvalid(const ProofId &proofid) const
bool isImmature(const ProofId &proofid) const
auto getUnbroadcastProofs() const
Definition: peermanager.h:443
bool isInConflictingPool(const ProofId &proofid) const
void sendResponse(CNode *pfrom, Response response) const
Definition: processor.cpp:559
bool addToReconcile(const AnyVoteItem &item) EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:442
bool isStakingPreconsensusActivated(const CBlockIndex *pprev) const
Definition: processor.cpp:1544
int64_t getAvaproofsNodeCounter() const
Definition: processor.h:358
bool sendHello(CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
Send a avahello message.
Definition: processor.cpp:751
void setRecentlyFinalized(const uint256 &itemId) EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:521
size_t getMaxElementPoll() const
Definition: processor.h:422
bool isQuorumEstablished() LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:838
void cleanupStakingRewards(const int minHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards
Definition: processor.cpp:983
ProofRef getLocalProof() const
Definition: processor.cpp:773
void acceptStakeContender(const StakeContenderId &contenderId) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:1101
bool reconcileOrFinalize(const ProofRef &proof) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Wrapper around the addToReconcile for proofs that adds back the finalization flag to the peer if it i...
Definition: processor.cpp:460
int getStakeContenderStatus(const StakeContenderId &contenderId) const EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Track votes on stake contenders.
Definition: processor.cpp:1078
void sendDelayedAvahello() EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
Definition: processor.cpp:756
void finalizeStakeContender(const StakeContenderId &contenderId) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:1106
bool isPreconsensusActivated(const CBlockIndex *pprev) const
Definition: processor.cpp:1540
auto withPeerManager(Callable &&func) const EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.h:320
bool registerVotes(NodeId nodeid, const Response &response, std::vector< VoteItemUpdate > &updates, bool &disconnect, std::string &error) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:565
void rejectStakeContender(const StakeContenderId &contenderId) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:1128
void avaproofsSent(NodeId nodeid) LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:817
std::vector< uint32_t > indices
std::string ToString() const
Definition: uint256.h:80
bool IsNull() const
Definition: uint256.h:32
std::string GetHex() const
Definition: uint256.cpp:16
Generate a new block, without valid proof-of-work.
Definition: miner.h:55
bool ReadRawBlock(std::vector< uint8_t > &block, const FlatFilePos &pos) const
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool LoadingBlocks() const
Definition: blockstorage.h:359
bool IsPruneMode() const
Whether running in -prune mode.
Definition: blockstorage.h:350
bool ReadBlock(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
256-bit opaque blob.
Definition: uint256.h:129
static const uint256 ZERO
Definition: uint256.h:134
@ BLOCK_CHECKPOINT
the block failed to meet one of our checkpoints
@ BLOCK_HEADER_LOW_WORK
the block header may be on a too-little-work chain
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ BLOCK_RESULT_UNSET
initial value. Block has not yet been rejected
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_CHILD_BEFORE_PARENT
This tx outputs are already spent in the mempool.
@ TX_MEMPOOL_POLICY
violated mempool's fee/size/descendant/etc limits
@ TX_PACKAGE_RECONSIDERABLE
fails some policy, but might be acceptable if submitted in a (different) package
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_PREMATURE_SPEND
transaction spends a coinbase too early, or violates locktime/sequence locks
@ TX_DUPLICATE
Tx already in mempool or in the chain.
@ TX_INPUTS_NOT_STANDARD
inputs failed policy rules
@ TX_CONFLICT
Tx conflicts with a finalized tx, i.e.
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
@ TX_AVALANCHE_RECONSIDERABLE
fails some policy, but might be reconsidered by avalanche voting
@ TX_NO_MEMPOOL
this node does not have a mempool so can't validate the transaction
@ TX_RESULT_UNSET
initial value. Tx has not yet been rejected
@ TX_CONSENSUS
invalid by consensus rules
static size_t RecursiveDynamicUsage(const CScript &script)
Definition: core_memusage.h:12
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
int64_t NodeId
Definition: eviction.h:16
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
Definition: chain.h:14
std::array< uint8_t, CPubKey::SCHNORR_SIZE > SchnorrSig
a Schnorr signature
Definition: key.h:25
bool fLogIPs
Definition: logging.cpp:24
#define LogPrintLevel(category, level,...)
Definition: logging.h:437
#define LogPrint(category,...)
Definition: logging.h:452
#define LogInfo(...)
Definition: logging.h:413
#define LogError(...)
Definition: logging.h:419
#define LogDebug(category,...)
Definition: logging.h:446
#define LogPrintf(...)
Definition: logging.h:424
static void pool cs
@ AVALANCHE
Definition: logging.h:91
@ TXPACKAGES
Definition: logging.h:99
@ NETDEBUG
Definition: logging.h:98
@ MEMPOOLREJ
Definition: logging.h:85
@ MEMPOOL
Definition: logging.h:71
@ NET
Definition: logging.h:69
CSerializedNetMsg Make(std::string msg_type, Args &&...args)
const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
Definition: protocol.cpp:36
const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
Definition: protocol.cpp:48
const char * AVAPROOFSREQ
Request for missing avalanche proofs after an avaproofs message has been processed.
Definition: protocol.cpp:58
const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
Definition: protocol.cpp:46
const char * BLOCK
The block message transmits a single serialized block.
Definition: protocol.cpp:30
const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
Definition: protocol.cpp:38
const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
Definition: protocol.cpp:29
const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
Definition: protocol.cpp:21
const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
Definition: protocol.cpp:39
const char * AVAPROOFS
The avaproofs message the proof short ids of all the valid proofs that we know.
Definition: protocol.cpp:57
const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
Definition: protocol.cpp:34
const char * GETAVAPROOFS
The getavaproofs message requests an avaproofs message that provides the proof short ids of all the v...
Definition: protocol.cpp:56
const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
Definition: protocol.cpp:41
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
Definition: protocol.cpp:31
const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
Definition: protocol.cpp:49
const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
Definition: protocol.cpp:35
const char * GETAVAADDR
The getavaaddr message requests an addr message from the receiving node, containing IP addresses of t...
Definition: protocol.cpp:55
const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
Definition: protocol.cpp:42
const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
Definition: protocol.cpp:32
const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
Definition: protocol.cpp:45
const char * TX
The tx message transmits a single transaction.
Definition: protocol.cpp:28
const char * AVAHELLO
Contains a delegation and a signature.
Definition: protocol.cpp:51
const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
Definition: protocol.cpp:37
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
Definition: protocol.cpp:20
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
Definition: protocol.cpp:18
const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
Definition: protocol.cpp:26
const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
Definition: protocol.cpp:40
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
Definition: protocol.cpp:27
const char * AVARESPONSE
Contains an avalanche::Response.
Definition: protocol.cpp:53
const char * GETDATA
The getdata message requests one or more data objects from another node.
Definition: protocol.cpp:24
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
Definition: protocol.cpp:19
const char * BLOCKTXN
Contains a BlockTransactions.
Definition: protocol.cpp:44
const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
Definition: protocol.cpp:47
const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
Definition: protocol.cpp:22
const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
Definition: protocol.cpp:33
const char * AVAPOLL
Contains an avalanche::Poll.
Definition: protocol.cpp:52
const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
Definition: protocol.cpp:25
const char * AVAPROOF
Contains an avalanche::Proof.
Definition: protocol.cpp:54
const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
Definition: protocol.cpp:50
const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
Definition: protocol.cpp:43
const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
Definition: protocol.cpp:23
ShortIdProcessor< PrefilledProof, ShortIdProcessorPrefilledProofAdapter, ProofRefCompare > ProofShortIdProcessor
Definition: compactproofs.h:52
std::variant< const ProofRef, const CBlockIndex *, const StakeContenderId, const CTransactionRef > AnyVoteItem
Definition: processor.h:104
RCUPtr< const Proof > ProofRef
Definition: proof.h:183
Definition: messages.h:12
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
bool fListen
Definition: net.cpp:129
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
Definition: net.cpp:246
std::function< void(const CAddress &addr, const std::string &msg_type, Span< const uint8_t > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
Definition: net.cpp:3308
std::string userAgent(const Config &config)
Definition: net.cpp:3256
bool IsReachable(enum Network net)
Definition: net.cpp:328
bool SeenLocal(const CService &addr)
vote for a local address
Definition: net.cpp:338
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
Definition: net.h:71
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
Definition: net.h:65
NetPermissionFlags
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
static constexpr size_t MAX_AVALANCHE_STALLED_TXIDS_PER_PEER
Maximum number of stalled avalanche txids to store per peer.
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto GETAVAADDR_INTERVAL
Minimum time between 2 successives getavaaddr messages from the same peer.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Verify that INVENTORY_MAX_RECENT_RELAY is enough to cache everything typically relayed before uncondi...
static constexpr unsigned int INVENTORY_BROADCAST_MAX_PER_MB
Maximum number of inventory items to send per transmission.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static uint32_t getAvalancheVoteForProof(const avalanche::Processor &avalanche, const avalanche::ProofId &id)
Decide a response for an Avalanche poll about the given proof.
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
bool IsAvalancheMessageType(const std::string &msg_type)
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/behind headers chain.
static std::chrono::microseconds ComputeRequestTime(const CNode &node, const InvRequestTracker< InvId > &requestTracker, const DataRequestParameters &requestParams, std::chrono::microseconds current_time, bool preferred)
Compute the request time for this announcement, current time plus delays for:
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr DataRequestParameters TX_REQUEST_PARAMS
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto AVALANCHE_AVAPROOFS_TIMEOUT
If no proof was requested from a compact proof message after this timeout expired,...
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr unsigned int INVENTORY_MAX_RECENT_RELAY
The number of most recently announced transactions a peer can request.
static constexpr auto UNCONDITIONAL_RELAY_DELAY
How long a transaction has to be in the mempool before it can unconditionally be relayed.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static constexpr DataRequestParameters PROOF_REQUEST_PARAMS
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static bool TooManyAnnouncements(const CNode &node, const InvRequestTracker< InvId > &requestTracker, const DataRequestParameters &requestParams)
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
bool IsProxy(const CNetAddr &addr)
Definition: netbase.cpp:842
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
Definition: nodeid.h:15
uint256 GetPackageHash(const Package &package)
Definition: packages.cpp:129
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
Definition: packages.h:40
static constexpr Amount DEFAULT_MIN_RELAY_TX_FEE_PER_KB(1000 *SATOSHI)
Default for -minrelaytxfee, minimum relay fee for transactions.
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
Response response
Definition: processor.cpp:536
SchnorrSig sig
Definition: processor.cpp:537
static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL_LEGACY
Legacy maximum element poll.
Definition: processor.h:63
void SetServiceFlagsIBDCache(bool state)
Set the current IBD status in order to figure out the desirable service flags.
Definition: protocol.cpp:164
ServiceFlags GetDesirableServiceFlags(ServiceFlags services)
Gets the set of service flags which are "desirable" for a given peer.
Definition: protocol.cpp:156
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH
Maximum length of incoming protocol messages (Currently 2MB).
Definition: protocol.h:25
static bool HasAllDesirableServiceFlags(ServiceFlags services)
A shortcut for (services & GetDesirableServiceFlags(services)) == GetDesirableServiceFlags(services),...
Definition: protocol.h:427
@ MSG_TX
Definition: protocol.h:573
@ MSG_AVA_STAKE_CONTENDER
Definition: protocol.h:581
@ MSG_AVA_PROOF
Definition: protocol.h:580
@ MSG_BLOCK
Definition: protocol.h:574
@ MSG_CMPCT_BLOCK
Defined in BIP152.
Definition: protocol.h:579
ServiceFlags
nServices flags.
Definition: protocol.h:335
@ NODE_NONE
Definition: protocol.h:338
@ NODE_NETWORK_LIMITED
Definition: protocol.h:365
@ NODE_BLOOM
Definition: protocol.h:352
@ NODE_NETWORK
Definition: protocol.h:342
@ NODE_COMPACT_FILTERS
Definition: protocol.h:360
@ NODE_AVALANCHE
Definition: protocol.h:380
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
Definition: protocol.h:435
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const int AVALANCHE_MAX_ELEMENT_BUMP_VERSION
Avalanche can poll up to 1024 items per message starting with this version.
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
Definition: random.h:512
reverse_range< T > reverse_iterate(T &x)
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:25
static std::string ToString(const CService &ip)
Definition: db.h:36
void Unserialize(Stream &, V)=delete
#define LIMITED_STRING(obj, n)
Definition: serialize.h:637
static auto WithParams(const Params &params, T &&t)
Return a wrapper around t that (de)serializes it with specified parameter params.
Definition: serialize.h:1329
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:469
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the Span constructor, but for (const) uint8_t member types only.
Definition: span.h:350
static const double AVALANCHE_STATISTICS_DECAY_FACTOR
Pre-computed decay factor for the avalanche statistics computation.
Definition: statistics.h:18
static constexpr std::chrono::minutes AVALANCHE_STATISTICS_REFRESH_PERIOD
Refresh period for the avalanche statistics computation.
Definition: statistics.h:11
Definition: amount.h:21
static constexpr Amount zero() noexcept
Definition: amount.h:34
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:108
std::vector< BlockHash > vHave
Definition: block.h:120
bool IsNull() const
Definition: block.h:135
std::chrono::microseconds m_ping_wait
Amount m_fee_filter_received
std::vector< int > vHeightInFlight
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
int64_t presync_height
ServiceFlags their_services
Parameters that influence chain consensus.
Definition: params.h:34
int64_t nPowTargetSpacing
Definition: params.h:85
std::chrono::seconds PowTargetSpacing() const
Definition: params.h:87
const std::chrono::seconds overloaded_peer_delay
How long to delay requesting data from overloaded peers (see max_peer_request_in_flight).
const size_t max_peer_announcements
Maximum number of inventories to consider for requesting, per peer.
const std::chrono::seconds nonpref_peer_delay
How long to delay requesting data from non-preferred peers.
const NetPermissionFlags bypass_request_limits_permissions
Permission flags a peer requires to bypass the request limits tracking limits and delay penalty.
const std::chrono::microseconds getdata_interval
How long to wait (in microseconds) before a data request from an additional peer.
const size_t max_peer_request_in_flight
Maximum number of in-flight data requests from a peer.
Validation result for a transaction evaluated by MemPoolAccept (single or package).
Definition: validation.h:212
const ResultType m_result_type
Result type.
Definition: validation.h:223
const TxValidationState m_state
Contains information about why the transaction failed.
Definition: validation.h:226
@ MEMPOOL_ENTRY
Valid, transaction was already in the mempool.
@ VALID
Fully validated, valid.
static time_point now() noexcept
Return current system time or mocked time, if set.
Definition: time.cpp:29
std::chrono::time_point< NodeClock > time_point
Definition: time.h:21
Validation result for package mempool acceptance.
Definition: validation.h:315
PackageValidationState m_state
Definition: validation.h:316
std::map< TxId, MempoolAcceptResult > m_tx_results
Map from txid to finished MempoolAcceptResults.
Definition: validation.h:324
This is a radix tree storing values identified by a unique key.
Definition: radix.h:39
A TxId is the identifier of a transaction.
Definition: txid.h:14
std::chrono::seconds registration_time
Definition: peermanager.h:93
const ProofId & getProofId() const
Definition: peermanager.h:108
ProofRef proof
Definition: peermanager.h:89
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
#define AssertLockNotHeld(cs)
Definition: sync.h:163
#define LOCK2(cs1, cs2)
Definition: sync.h:309
#define LOCK(cs)
Definition: sync.h:306
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:357
static int count
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
#define GUARDED_BY(x)
Definition: threadsafety.h:45
#define LOCKS_EXCLUDED(...)
Definition: threadsafety.h:55
#define NO_THREAD_SAFETY_ANALYSIS
Definition: threadsafety.h:58
#define PT_GUARDED_BY(x)
Definition: threadsafety.h:46
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:80
constexpr int64_t count_microseconds(std::chrono::microseconds t)
Definition: time.h:91
constexpr int64_t count_seconds(std::chrono::seconds t)
Definition: time.h:85
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
Definition: time.h:27
double CountSecondsDouble(SecondsDouble t)
Helper to count the seconds in any std::chrono::duration type.
Definition: time.h:104
NodeClock::time_point GetAdjustedTime()
Definition: timedata.cpp:35
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
Definition: timedata.cpp:45
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
#define TRACE6(context, event, a, b, c, d, e, f)
Definition: trace.h:45
@ AVALANCHE
Removed by avalanche vote.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
arith_uint256 CalculateHeadersWork(const std::vector< CBlockHeader > &headers)
Return the sum of the work on a given set of headers.
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept)
Validate (and maybe submit) a package to the mempool.
bool IsBlockMutated(const CBlock &block)
Check if a block has been mutated (with respect to its merkle root).
AssertLockHeld(pool.cs)
std::optional< std::vector< Coin > > GetSpentCoins(const CTransactionRef &ptx, const CCoinsViewCache &coins_view)
Get the coins spent by ptx from the coins_view.
assert(!tx.IsCoinBase())
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...
Definition: validation.h:99
CMainSignals & GetMainSignals()