76#include <initializer_list>
89#include <unordered_set>
210 const CBlockIndex* pindex;
212 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
246 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
249 const bool m_is_inbound;
252 Mutex m_misbehavior_mutex;
254 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
257 Mutex m_block_inv_mutex;
261 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
265 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
270 uint256 m_continuation_block
GUARDED_BY(m_block_inv_mutex) {};
276 std::atomic<uint64_t> m_ping_nonce_sent{0};
280 std::atomic<bool> m_ping_queued{
false};
283 std::atomic<bool> m_wtxid_relay{
false};
295 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
297 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
303 CRollingBloomFilter m_tx_inventory_known_filter
GUARDED_BY(m_tx_inventory_mutex){50000, 0.000001};
308 std::vector<Wtxid> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
312 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
315 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
318 uint64_t m_last_inv_sequence
GUARDED_BY(m_tx_inventory_mutex){1};
321 std::atomic<CAmount> m_fee_filter_received{0};
327 LOCK(m_tx_relay_mutex);
329 m_tx_relay = std::make_unique<Peer::TxRelay>();
330 return m_tx_relay.get();
335 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
364 std::atomic_bool m_addr_relay_enabled{
false};
368 mutable Mutex m_addr_send_times_mutex;
370 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
372 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
375 std::atomic_bool m_wants_addrv2{
false};
384 std::atomic<uint64_t> m_addr_rate_limited{0};
386 std::atomic<uint64_t> m_addr_processed{0};
392 Mutex m_getdata_requests_mutex;
394 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
400 Mutex m_headers_sync_mutex;
403 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
406 std::atomic<bool> m_sent_sendheaders{
false};
416 std::atomic<std::chrono::seconds> m_time_offset{0
s};
420 , m_our_services{our_services}
421 , m_is_inbound{is_inbound}
425 mutable Mutex m_tx_relay_mutex;
428 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
431using PeerRef = std::shared_ptr<Peer>;
441 const CBlockIndex* pindexBestKnownBlock{
nullptr};
443 uint256 hashLastUnknownBlock{};
445 const CBlockIndex* pindexLastCommonBlock{
nullptr};
447 const CBlockIndex* pindexBestHeaderSent{
nullptr};
449 bool fSyncStarted{
false};
451 std::chrono::microseconds m_stalling_since{0us};
452 std::list<QueuedBlock> vBlocksInFlight;
454 std::chrono::microseconds m_downloading_since{0us};
456 bool fPreferredDownload{
false};
458 bool m_requested_hb_cmpctblocks{
false};
460 bool m_provides_cmpctblocks{
false};
486 struct ChainSyncTimeoutState {
488 std::chrono::seconds m_timeout{0
s};
490 const CBlockIndex* m_work_header{
nullptr};
492 bool m_sent_getheaders{
false};
494 bool m_protect{
false};
497 ChainSyncTimeoutState m_chain_sync;
500 int64_t m_last_block_announcement{0};
503struct InvToSendBucket {
504 const double count_floor{0};
505 std::vector<Wtxid> backlog;
506 util::TokenBucket<NodeClock> size_bucket;
507 util::TokenBucket<NodeClock> count_bucket;
522 static constexpr double SIZE_INIT{12'000'000};
523 static constexpr double SIZE_CAP{50'000'000};
524 static constexpr double SIZE_REFILL{20'000};
526 static constexpr double INBOUND_COUNT_SECONDS{30};
528 InvToSendBucket(
unsigned int rate,
double mult)
530 size_bucket(SIZE_REFILL * mult, SIZE_INIT, SIZE_CAP),
531 count_bucket(rate * mult, rate * INBOUND_COUNT_SECONDS, rate * INBOUND_COUNT_SECONDS)
537 return !backlog.empty() && size_bucket.value() > 0 && count_bucket.value() > 0;
542 size_bucket.increment(now);
543 count_bucket.increment(now);
548 bool decrement(
double size)
550 bool size_ok = size_bucket.decrement(size, -50e3);
551 bool count_ok = count_bucket.decrement(1, count_floor);
552 return size_ok && count_ok;
555 PeerManagerInfo::InvBucketInfo info()
const
558 .backlog_count = backlog.size(),
559 .count_bucket = count_bucket.value(),
560 .size_bucket = size_bucket.value(),
568 PeerManagerImpl(CConnman& connman, AddrMan& addrman,
569 BanMan* banman, ChainstateManager& chainman,
570 CTxMemPool& pool, node::Warnings& warnings, Options opts);
573 void ActiveTipChange(
const CBlockIndex& new_tip,
bool)
override
575 void BlockConnected(
const ChainstateRole& role,
const std::shared_ptr<const CBlock>& pblock,
const CBlockIndex* pindexConnected)
override
577 void BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
override
579 void UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
override
581 void BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
override
583 void NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
override
588 void FinalizeNode(
const CNode& node)
override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex, !m_tx_download_mutex);
589 bool HasAllDesirableServiceFlags(
ServiceFlags services)
const override;
590 bool ProcessMessages(CNode& node, std::atomic<bool>& interrupt)
override
591 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex, !m_inv_to_send_mutex);
592 bool SendMessages(CNode& node)
override
593 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, g_msgproc_mutex, !m_tx_download_mutex, !m_inv_to_send_mutex);
596 void StartScheduledTasks(CScheduler& scheduler)
override;
597 void CheckForStaleTipAndEvictPeers()
override;
598 util::Expected<void, std::string> FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
override
601 std::vector<node::TxOrphanage::OrphanInfo> GetOrphanTransactions() override
EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);
603 std::vector<PrivateBroadcast::TxBroadcastInfo> GetPrivateBroadcastInfo() const override
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
608 void SetBestBlock(
int height, std::chrono::seconds time)
override
610 m_best_height = height;
611 m_best_block_time = time;
614 void UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
override;
618 void ProcessMessage(Peer& peer, CNode& pfrom,
const std::string& msg_type, DataStream& vRecv,
NodeClock::time_point time_received,
619 const std::atomic<bool>& interruptMsgProc)
620 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex, !m_inv_to_send_mutex);
629 void ReattemptInitialBroadcast(CScheduler& scheduler)
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_inv_to_send_mutex);
632 void ReattemptPrivateBroadcast(CScheduler& scheduler);
647 void Misbehaving(Peer& peer, const std::
string& message);
657 void MaybePunishNodeForBlock(
NodeId nodeid, const BlockValidationState& state,
658 bool via_compact_block, const std::
string& message =
"")
667 bool MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer);
680 bool MaybeDisconnectForTxRelayCapacity(CNode& node, const std::
string& msg_type,
681 std::optional<
NodeId> protect_peer = std::nullopt);
694 std::optional<node::PackageToValidate> ProcessInvalidTx(
NodeId nodeid, const
CTransactionRef& tx, const TxValidationState& result,
695 bool first_time_failure)
706 void ProcessPackageResult(const node::PackageToValidate& package_to_validate, const PackageMempoolAcceptResult& package_result)
720 bool ProcessOrphanTx(Peer& peer)
730 void ProcessHeadersMessage(CNode& pfrom, Peer& peer,
731 std::vector<CBlockHeader>&& headers,
732 bool via_compact_block)
736 bool CheckHeadersPoW(const std::vector<CBlockHeader>& headers, Peer& peer);
738 arith_uint256 GetAntiDoSWorkThreshold();
742 void HandleUnconnectingHeaders(CNode& pfrom, Peer& peer, const std::vector<CBlockHeader>& headers)
EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
744 bool CheckHeadersAreContinuous(const std::vector<CBlockHeader>& headers) const;
763 bool IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfrom,
764 std::vector<CBlockHeader>& headers)
777 bool TryLowWorkHeadersSync(Peer& peer, CNode& pfrom,
778 const CBlockIndex& chain_start_header,
779 std::vector<CBlockHeader>& headers)
790 bool MaybeSendGetHeaders(CNode& pfrom, const CBlockLocator& locator, Peer& peer)
EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
792 void HeadersDirectFetchBlocks(CNode& pfrom, const Peer& peer, const CBlockIndex& last_header);
794 void UpdatePeerStateForReceivedHeaders(CNode& pfrom, const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
797 void SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest&
req);
800 void PushMessage(CNode& node, CSerializedNetMsg&& msg)
const { m_connman.PushMessage(&node, std::move(msg)); }
801 template <
typename... Args>
802 void MakeAndPushMessage(CNode& node, std::string msg_type, Args&&...
args)
const
804 m_connman.PushMessage(&node,
NetMsg::Make(std::move(msg_type), std::forward<Args>(
args)...));
806 template <
typename... Args>
807 [[maybe_unused]]
void MakeAndPushFeature(CNode& node, std::string_view feature_id, Args&&...
args)
const
810 std::vector<unsigned char> feature_data;
811 VectorWriter{feature_data, 0, std::forward<Args>(
args)...};
817 void PushNodeVersion(CNode& pnode,
const Peer& peer);
826 void MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time)
EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
841 void MaybeSendFeefilter(CNode& node, Peer& peer, std::chrono::microseconds current_time)
EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
846 const SaltedUint256Hasher m_txhash_hasher;
849 const CChainParams& m_chainparams;
853 BanMan*
const m_banman;
854 ChainstateManager& m_chainman;
855 CTxMemPool& m_mempool;
866 node::TxDownloadManager m_txdownloadman
GUARDED_BY(m_tx_download_mutex);
868 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
871 std::atomic<int> m_best_height{-1};
873 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
878 node::Warnings& m_warnings;
879 TimeOffsets m_outbound_time_offsets{m_warnings};
881 const Options m_opts;
883 bool RejectIncomingTxs(
const CNode& peer)
const;
891 mutable Mutex m_peer_mutex;
898 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
908 uint32_t GetFetchFlags(
const Peer& peer)
const;
910 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
916 uint256 m_last_block_inv_triggering_headers_sync
GUARDED_BY(g_msgproc_mutex){};
927 std::atomic<int> m_wtxid_relay_peers{0};
945 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
946 std::chrono::seconds average_interval,
951 Mutex m_most_recent_block_mutex;
952 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
953 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
954 uint256 m_most_recent_block_hash
GUARDED_BY(m_most_recent_block_mutex);
955 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
959 Mutex m_headers_presync_mutex;
967 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
969 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
973 std::atomic_bool m_headers_presync_should_signal{
false};
1007 void TryDownloadingHistoricalBlocks(const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks, const CBlockIndex* from_tip, const CBlockIndex* target_block)
EXCLUSIVE_LOCKS_REQUIRED(
cs_main);
1036 void FindNextBlocks(std::vector<const CBlockIndex*>& vBlocks, const Peer& peer, CNodeState *state, const CBlockIndex *pindexWalk,
unsigned int count,
int nWindowEnd, const CChain* activeChain=
nullptr,
NodeId* nodeStaller=
nullptr)
EXCLUSIVE_LOCKS_REQUIRED(
cs_main);
1039 typedef std::multimap<uint256, std::pair<
NodeId, std::list<QueuedBlock>::iterator>> BlockDownloadMap;
1043 std::atomic<std::chrono::seconds> m_last_tip_update{0
s};
1046 CTransactionRef FindTxForGetData(
const Peer::TxRelay& tx_relay,
const GenTxid& gtxid)
1049 void ProcessGetData(CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
1054 void ProcessBlock(CNode& node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
1057 void ProcessCompactBlockTxns(CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
1087 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
1089 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1101 int64_t ApproximateBestBlockDepth() const;
1111 void ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& inv)
1129 bool PrepareBlockFilterRequest(CNode& node, Peer& peer,
1131 const uint256& stop_hash, uint32_t max_height_diff,
1132 const CBlockIndex*& stop_index,
1133 BlockFilterIndex*& filter_index);
1144 void ProcessGetCFilters(CNode& node, Peer& peer, DataStream& vRecv);
1155 void ProcessGetCFHeaders(CNode& node, Peer& peer, DataStream& vRecv);
1166 void ProcessGetCFCheckPt(CNode& node, Peer& peer, DataStream& vRecv);
1168 void ProcessPong(CNode& pfrom, Peer& peer, NodeClock::time_point ping_end, DataStream& vRecv);
1178 void ProcessAddrs(std::string_view msg_type, CNode& pfrom, Peer& peer, std::vector<CAddress>&& vAddr, const std::atomic<
bool>& interruptMsgProc)
1184 void LogBlockHeader(const CBlockIndex& index, const CNode& peer,
bool via_compact_block);
1187 PrivateBroadcast m_tx_for_private_broadcast;
1190 InvToSendBucket m_inbound_inv_bucket
GUARDED_BY(m_inv_to_send_mutex);
1191 InvToSendBucket m_outbound_inv_bucket
GUARDED_BY(m_inv_to_send_mutex);
1192 std::atomic<NodeClock::time_point> m_next_inv_bucket_check{NodeClock::time_point::min()};
1193 std::optional<NodeClock::time_point> m_next_inv_bucket_heartbeat
GUARDED_BY(m_inv_to_send_mutex);
1198const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const
1200 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1201 if (it == m_node_states.end())
1206CNodeState* PeerManagerImpl::State(
NodeId pnode)
1208 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1216static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1221void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1223 assert(peer.m_addr_known);
1224 peer.m_addr_known->insert(addr.
GetKey());
1227void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1232 assert(peer.m_addr_known);
1233 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1235 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1237 peer.m_addrs_to_send.push_back(addr);
1242static void AddKnownTx(Peer& peer,
const uint256& hash)
1244 auto tx_relay = peer.GetTxRelay();
1245 if (!tx_relay)
return;
1247 LOCK(tx_relay->m_tx_inventory_mutex);
1248 tx_relay->m_tx_inventory_known_filter.insert(hash);
1252static bool CanServeBlocks(
const Peer& peer)
1259static bool IsLimitedPeer(
const Peer& peer)
1266static bool CanServeWitnesses(
const Peer& peer)
1271std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1272 std::chrono::seconds average_interval,
1273 uint64_t network_key)
1275 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1276 auto& timer{it->second};
1278 timer = now + m_rng.rand_exp_duration(average_interval);
1283bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1285 return mapBlocksInFlight.contains(hash);
1288bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1290 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1291 auto [nodeid, block_it] = range.first->second;
1292 PeerRef peer{GetPeerRef(nodeid)};
1293 if (peer && !peer->m_is_inbound)
return true;
1299void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1301 auto range = mapBlocksInFlight.equal_range(hash);
1302 if (range.first == range.second) {
1310 while (range.first != range.second) {
1311 const auto& [node_id, list_it]{range.first->second};
1313 if (from_peer && *from_peer != node_id) {
1320 if (state.vBlocksInFlight.begin() == list_it) {
1324 state.vBlocksInFlight.erase(list_it);
1326 if (state.vBlocksInFlight.empty()) {
1328 m_peers_downloading_from--;
1330 state.m_stalling_since = 0us;
1332 range.first = mapBlocksInFlight.erase(range.first);
1336bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1340 CNodeState *state =
State(nodeid);
1341 assert(state !=
nullptr);
1346 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1347 if (range.first->second.first == nodeid) {
1349 *pit = &range.first->second.second;
1356 RemoveBlockRequest(hash, nodeid);
1358 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1359 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1360 if (state->vBlocksInFlight.size() == 1) {
1363 m_peers_downloading_from++;
1365 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1367 *pit = &itInFlight->second.second;
1372void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1379 if (m_opts.ignore_incoming_txs)
return;
1381 CNodeState* nodestate =
State(nodeid);
1382 PeerRef peer{GetPeerRef(nodeid)};
1383 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1388 int num_outbound_hb_peers = 0;
1389 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1390 if (*it == nodeid) {
1391 lNodesAnnouncingHeaderAndIDs.erase(it);
1392 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1395 PeerRef peer_ref{GetPeerRef(*it)};
1396 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1398 if (peer && peer->m_is_inbound) {
1401 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1402 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1403 if (remove_peer && !remove_peer->m_is_inbound) {
1406 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1415 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1418 if (nodeid_was_appended && lNodesAnnouncingHeaderAndIDs.size() > 3) {
1421 m_connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](CNode* pnodeStop) {
1422 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1424 pnodeStop->m_bip152_highbandwidth_to = false;
1427 lNodesAnnouncingHeaderAndIDs.pop_front();
1431bool PeerManagerImpl::TipMayBeStale()
1434 const Consensus::Params& consensusParams = m_chainparams.GetConsensus();
1435 if (m_last_tip_update.load() == 0s) {
1441int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1446bool PeerManagerImpl::CanDirectFetch()
1448 return m_chainman.ActiveChain().Tip()->Time() >
NodeClock::now() - m_chainparams.GetConsensus().PowTargetSpacing() * 20;
1453 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->
GetAncestor(pindex->nHeight))
1455 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->
GetAncestor(pindex->nHeight))
1460void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1461 CNodeState *state =
State(nodeid);
1462 assert(state !=
nullptr);
1464 if (!state->hashLastUnknownBlock.
IsNull()) {
1465 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock);
1467 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->
nChainWork) {
1468 state->pindexBestKnownBlock = pindex;
1470 state->hashLastUnknownBlock.
SetNull();
1475void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1476 CNodeState *state =
State(nodeid);
1477 assert(state !=
nullptr);
1479 ProcessBlockAvailability(nodeid);
1481 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
1484 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->
nChainWork) {
1485 state->pindexBestKnownBlock = pindex;
1489 state->hashLastUnknownBlock = hash;
1494void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1499 vBlocks.reserve(vBlocks.size() + count);
1500 CNodeState *state =
State(peer.m_id);
1501 assert(state !=
nullptr);
1504 ProcessBlockAvailability(peer.m_id);
1506 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->
nChainWork < m_chainman.ActiveChain().Tip()->nChainWork || state->pindexBestKnownBlock->
nChainWork < m_chainman.MinimumChainWork()) {
1515 const CBlockIndex* snap_base{m_chainman.CurrentChainstate().SnapshotBase()};
1518 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1526 auto fork_point =
LastCommonAncestor(state->pindexBestKnownBlock, m_chainman.ActiveTip());
1527 if (state->pindexLastCommonBlock ==
nullptr ||
1529 state->pindexBestKnownBlock->
GetAncestor(state->pindexLastCommonBlock->
nHeight) != state->pindexLastCommonBlock) {
1530 state->pindexLastCommonBlock = fork_point;
1532 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1535 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1541 FindNextBlocks(vBlocks, peer, state, pindexWalk, count, nWindowEnd, &m_chainman.ActiveChain(), &nodeStaller);
1544void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1549 if (vBlocks.size() >= count) {
1553 vBlocks.reserve(count);
1556 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->
GetAncestor(target_block->
nHeight) != target_block) {
1573void PeerManagerImpl::FindNextBlocks(std::vector<const CBlockIndex*>& vBlocks,
const Peer& peer, CNodeState *state,
const CBlockIndex *pindexWalk,
unsigned int count,
int nWindowEnd,
const CChain* activeChain,
NodeId* nodeStaller)
1575 std::vector<const CBlockIndex*> vToFetch;
1576 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->
nHeight, nWindowEnd + 1);
1577 bool is_limited_peer = IsLimitedPeer(peer);
1579 while (pindexWalk->
nHeight < nMaxHeight) {
1583 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(count - vBlocks.size(), 128));
1584 vToFetch.resize(nToFetch);
1585 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1586 vToFetch[nToFetch - 1] = pindexWalk;
1587 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1588 vToFetch[i - 1] = vToFetch[i]->pprev;
1595 for (
const CBlockIndex* pindex : vToFetch) {
1608 state->pindexLastCommonBlock = pindex;
1615 if (waitingfor == -1) {
1617 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1623 if (pindex->
nHeight > nWindowEnd) {
1625 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1627 if (nodeStaller) *nodeStaller = waitingfor;
1637 vBlocks.push_back(pindex);
1638 if (vBlocks.size() == count) {
1647void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1649 uint64_t my_services;
1651 uint64_t your_services;
1653 std::string my_user_agent;
1660 your_addr = CService{};
1661 my_user_agent =
"/pynode:0.0.1/";
1663 my_tx_relay =
false;
1665 const CAddress& addr{pnode.
addr};
1666 my_services = peer.m_our_services;
1671 my_height = m_best_height;
1672 my_tx_relay = !RejectIncomingTxs(pnode);
1691 BCLog::NET,
"send version message: version=%d, blocks=%d%s, txrelay=%d, peer=%d\n",
1694 my_tx_relay, pnode.
GetId());
1697void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1700 CNodeState *state =
State(node);
1701 if (state) state->m_last_block_announcement = time_in_seconds;
1704void PeerManagerImpl::InitializeNode(
const CNode& node,
ServiceFlags our_services)
1709 m_node_states.try_emplace(m_node_states.end(), nodeid);
1711 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1717 PeerRef peer = std::make_shared<Peer>(nodeid, our_services, node.
IsInboundConn());
1720 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1724void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler)
1728 for (
const auto& txid : unbroadcast_txids) {
1731 if (tx !=
nullptr) {
1732 InitiateTxBroadcastToAll(tx->GetWitnessHash());
1740 const auto delta = 10min +
FastRandomContext().randrange<std::chrono::milliseconds>(5min);
1741 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1744void PeerManagerImpl::ReattemptPrivateBroadcast(CScheduler& scheduler)
1748 size_t num_for_rebroadcast{0};
1749 const auto stale_txs = m_tx_for_private_broadcast.
GetStale();
1750 if (!stale_txs.empty()) {
1751 for (
const auto& stale_tx : stale_txs) {
1756 if (!m_tx_for_private_broadcast.
TryGrantRetry(stale_tx))
continue;
1758 "Reattempting broadcast of stale txid=%s wtxid=%s",
1759 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString());
1760 ++num_for_rebroadcast;
1763 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString(),
1764 mempool_acceptable.m_state.ToString());
1773 const auto delta{2min +
FastRandomContext().randrange<std::chrono::milliseconds>(1min)};
1774 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, delta);
1777void PeerManagerImpl::FinalizeNode(
const CNode& node)
1788 PeerRef peer = RemovePeer(nodeid);
1790 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1791 assert(m_wtxid_relay_peers >= 0);
1793 CNodeState *state =
State(nodeid);
1794 assert(state !=
nullptr);
1796 if (state->fSyncStarted)
1799 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1800 auto range = mapBlocksInFlight.equal_range(entry.pindex->
GetBlockHash());
1801 while (range.first != range.second) {
1802 auto [node_id, list_it] = range.first->second;
1803 if (node_id != nodeid) {
1806 range.first = mapBlocksInFlight.erase(range.first);
1811 LOCK(m_tx_download_mutex);
1812 m_txdownloadman.DisconnectedPeer(nodeid);
1814 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1815 m_num_preferred_download_peers -= state->fPreferredDownload;
1816 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1817 assert(m_peers_downloading_from >= 0);
1818 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1819 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1821 m_node_states.erase(nodeid);
1823 if (m_node_states.empty()) {
1825 assert(mapBlocksInFlight.empty());
1826 assert(m_num_preferred_download_peers == 0);
1827 assert(m_peers_downloading_from == 0);
1828 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1829 assert(m_wtxid_relay_peers == 0);
1830 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1842 LOCK(m_headers_presync_mutex);
1843 m_headers_presync_stats.erase(nodeid);
1861bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1864 return !(GetDesirableServiceFlags(services) & (~services));
1878PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1881 auto it = m_peer_map.find(
id);
1882 return it != m_peer_map.end() ? it->second :
nullptr;
1885PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1889 auto it = m_peer_map.find(
id);
1890 if (it != m_peer_map.end()) {
1891 ret = std::move(it->second);
1892 m_peer_map.erase(it);
1897std::vector<PeerRef> PeerManagerImpl::GetAllPeers()
const
1899 std::vector<PeerRef> peers;
1901 peers.reserve(m_peer_map.size());
1902 for (
const auto& [
_, peer] : m_peer_map) {
1903 peers.push_back(peer);
1908bool PeerManagerImpl::GetNodeStateStats(
NodeId nodeid, CNodeStateStats& stats)
const
1912 const CNodeState* state =
State(nodeid);
1913 if (state ==
nullptr)
1915 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->
nHeight : -1;
1916 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->
nHeight : -1;
1917 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1923 PeerRef peer = GetPeerRef(nodeid);
1924 if (peer ==
nullptr)
return false;
1932 NodeClock::duration ping_wait{0us};
1933 if ((0 != peer->m_ping_nonce_sent) && (peer->m_ping_start.load() >
NodeClock::epoch)) {
1937 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1940 LOCK(tx_relay->m_tx_inventory_mutex);
1942 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1954 LOCK(peer->m_headers_sync_mutex);
1955 if (peer->m_headers_sync) {
1964std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1966 LOCK(m_tx_download_mutex);
1967 return m_txdownloadman.GetOrphanTransactions();
1970PeerManagerInfo PeerManagerImpl::GetInfo()
const
1972 LOCK(m_inv_to_send_mutex);
1973 return PeerManagerInfo{
1974 .median_outbound_time_offset = m_outbound_time_offsets.
Median(),
1975 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1976 .private_broadcast = m_opts.private_broadcast,
1977 .tx_send_rate = m_opts.tx_send_rate,
1978 .inbound_bucket = m_inbound_inv_bucket.info(),
1979 .outbound_bucket = m_outbound_inv_bucket.info(),
1983std::vector<PrivateBroadcast::TxBroadcastInfo> PeerManagerImpl::GetPrivateBroadcastInfo()
const
1988std::vector<CTransactionRef> PeerManagerImpl::AbortPrivateBroadcast(
const uint256&
id)
1991 std::vector<CTransactionRef> removed_txs;
1993 size_t connections_cancelled{0};
1994 for (
const auto& tx_info : snapshot) {
1996 if (tx->GetHash().ToUint256() !=
id && tx->GetWitnessHash().ToUint256() !=
id)
continue;
1997 if (
const auto remaining_sends{m_tx_for_private_broadcast.
Remove(tx)}) {
1998 removed_txs.push_back(tx);
1999 connections_cancelled += *remaining_sends;
2007void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
2009 if (m_opts.max_extra_txs == 0)
return;
2010 if (vExtraTxnForCompact.size() < m_opts.max_extra_txs) {
2011 if (vExtraTxnForCompact.empty()) vExtraTxnForCompact.reserve(m_opts.max_extra_txs);
2012 vExtraTxnForCompact.emplace_back(tx->GetWitnessHash(), tx);
2014 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
2016 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
2019void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
2021 LOCK(peer.m_misbehavior_mutex);
2023 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
2024 peer.m_should_discourage =
true;
2032void PeerManagerImpl::MaybePunishNodeForBlock(
NodeId nodeid,
const BlockValidationState& state,
2033 bool via_compact_block,
const std::string& message)
2035 PeerRef peer{GetPeerRef(nodeid)};
2046 if (!via_compact_block) {
2047 if (peer) Misbehaving(*peer, message);
2055 if (peer && !via_compact_block && !peer->m_is_inbound) {
2056 if (peer) Misbehaving(*peer, message);
2063 if (peer) Misbehaving(*peer, message);
2067 if (peer) Misbehaving(*peer, message);
2072 if (message !=
"") {
2077bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex& block_index)
2086util::Expected<void, std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
2097 PeerRef peer = GetPeerRef(peer_id);
2098 if (peer ==
nullptr)
return util::Unexpected{
"Peer does not exist"};
2101 if (!CanServeWitnesses(*peer))
return util::Unexpected{
"Pre-SegWit peer"};
2104 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
2107 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
2114 bool success = m_connman.
ForNode(peer_id, [
this, &invs](CNode* node) {
2119 if (!success)
return util::Unexpected{
"Peer not fully connected"};
2130 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
2136 : m_rng{opts.deterministic_rng},
2138 m_chainparams(chainman.GetParams()),
2142 m_chainman(chainman),
2144 m_txdownloadman{
node::TxDownloadOptions{pool, opts.deterministic_rng}},
2145 m_warnings{warnings},
2147 m_inbound_inv_bucket(m_opts.tx_send_rate, 1.0),
2152 if (opts.reconcile_txs) {
2153 m_txreconciliation = std::make_unique<TxReconciliationTracker>(TXRECONCILIATION_VERSION);
2157void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2167 const auto delta = 10min +
FastRandomContext().randrange<std::chrono::milliseconds>(5min);
2168 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2170 if (m_opts.private_broadcast) {
2171 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2175void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2183 LOCK(m_tx_download_mutex);
2187 m_txdownloadman.ActiveTipChange();
2197void PeerManagerImpl::BlockConnected(
2198 const ChainstateRole& role,
2199 const std::shared_ptr<const CBlock>& pblock,
2200 const CBlockIndex* pindex)
2207 auto stalling_timeout = m_block_stalling_timeout.load();
2211 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2220 LOCK(m_tx_download_mutex);
2221 m_txdownloadman.BlockConnected(pblock);
2225void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2227 LOCK(m_tx_download_mutex);
2228 m_txdownloadman.BlockDisconnected();
2235void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2237 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2241 if (pindex->
nHeight <= m_highest_fast_announce)
2243 m_highest_fast_announce = pindex->
nHeight;
2247 uint256 hashBlock(pblock->GetHash());
2248 const std::shared_future<CSerializedNetMsg> lazy_ser{
2252 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2253 for (
const auto& tx : pblock->vtx) {
2254 most_recent_block_txs->emplace(tx->GetHash(), tx);
2255 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2258 LOCK(m_most_recent_block_mutex);
2259 m_most_recent_block_hash = hashBlock;
2260 m_most_recent_block = pblock;
2261 m_most_recent_compact_block = pcmpctblock;
2262 m_most_recent_block_txs = std::move(most_recent_block_txs);
2270 ProcessBlockAvailability(pnode->
GetId());
2274 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2276 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2277 hashBlock.ToString(), pnode->
GetId());
2279 const CSerializedNetMsg& ser_cmpctblock{lazy_ser.get()};
2280 PushMessage(*pnode, ser_cmpctblock.
Copy());
2281 state.pindexBestHeaderSent = pindex;
2290void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2292 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2295 if (fInitialDownload)
return;
2298 std::vector<uint256> vHashes;
2299 const CBlockIndex *pindexToAnnounce = pindexNew;
2300 while (pindexToAnnounce != pindexFork) {
2302 pindexToAnnounce = pindexToAnnounce->
pprev;
2312 for (
auto& it : m_peer_map) {
2313 Peer& peer = *it.second;
2314 LOCK(peer.m_block_inv_mutex);
2315 for (
const uint256& hash : vHashes | std::views::reverse) {
2316 peer.m_blocks_for_headers_relay.push_back(hash);
2328void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2332 const uint256 hash(block->GetHash());
2333 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2338 it != mapBlockSource.end() &&
2339 State(it->second.first)) {
2340 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2350 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2351 if (it != mapBlockSource.end()) {
2352 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2355 if (it != mapBlockSource.end())
2356 mapBlockSource.erase(it);
2364bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2369void PeerManagerImpl::SendPings()
2372 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2375std::vector<Wtxid> InvToSendBucket::TakeForProcessing(CTxMemPool& mempool)
2379 size_t n_to_take =
static_cast<size_t>(std::max<double>(count_bucket.
value() - count_floor, 0));
2381 std::vector<Wtxid> best;
2384 bool tokens_left =
true;
2385 for (
auto txiter : itervec) {
2386 auto& wtxid = txiter->GetTx().GetWitnessHash();
2388 best.push_back(wtxid);
2389 if (!decrement(txiter->GetTx().ComputeTotalSize())) {
2390 tokens_left =
false;
2393 backlog.push_back(wtxid);
2399 std::vector<Wtxid> dummy;
2401 dummy.swap(backlog);
2411 if (!backlog_bumped && now <= m_next_inv_bucket_check.load())
return;
2414 LOCK(m_inv_to_send_mutex);
2415 m_inbound_inv_bucket.increment(now);
2416 m_outbound_inv_bucket.increment(now);
2419 if (!m_next_inv_bucket_heartbeat.has_value()) {
2421 m_next_inv_bucket_heartbeat = now;
2424 if (m_next_inv_bucket_heartbeat.has_value() && now >= *m_next_inv_bucket_heartbeat) {
2425 LogDebug(
BCLog::NET,
"Transaction rate-limiting backlog inbound=%d itok=%.1f isz=%.1f outbound=%d otok=%.1f osz=%.1f",
2426 m_inbound_inv_bucket.backlog.size(),
2427 m_inbound_inv_bucket.count_bucket.value(),
2428 m_inbound_inv_bucket.size_bucket.value(),
2429 m_outbound_inv_bucket.backlog.size(),
2430 m_outbound_inv_bucket.count_bucket.value(),
2431 m_outbound_inv_bucket.size_bucket.value());
2432 if (m_inbound_inv_bucket.backlog.empty() && m_outbound_inv_bucket.backlog.empty()) {
2433 m_next_inv_bucket_heartbeat = std::nullopt;
2440 bool in_avail = m_inbound_inv_bucket.avail();
2441 bool out_avail = m_outbound_inv_bucket.avail();
2442 if (!in_avail && !out_avail)
return;
2444 std::vector<Wtxid> for_inbound;
2445 std::vector<Wtxid> for_outbound;
2449 if (in_avail) for_inbound = m_inbound_inv_bucket.TakeForProcessing(m_mempool);
2450 if (out_avail) for_outbound = m_outbound_inv_bucket.TakeForProcessing(m_mempool);
2453 if (!for_inbound.empty() || !for_outbound.empty()) {
2454 bool any_inbound_connected =
false;
2455 bool any_outbound_connected =
false;
2456 for (
const PeerRef& peer_ref : GetAllPeers()) {
2457 if (!peer_ref)
continue;
2458 Peer& peer{*peer_ref};
2459 auto tx_relay = peer.GetTxRelay();
2460 if (!tx_relay)
continue;
2462 LOCK(tx_relay->m_tx_inventory_mutex);
2468 if (tx_relay->m_next_inv_send_time == 0s)
continue;
2469 if (peer.m_is_inbound) {
2470 any_inbound_connected =
true;
2472 any_outbound_connected =
true;
2474 for (
auto& i : (peer.m_is_inbound ? for_inbound : for_outbound)) {
2475 tx_relay->m_tx_inventory_to_send.push_back(i);
2482 if (!any_inbound_connected) m_inbound_inv_bucket.backlog.clear();
2483 if (!any_outbound_connected) m_outbound_inv_bucket.backlog.clear();
2487void PeerManagerImpl::InitiateTxBroadcastToAll(
const Wtxid& wtxid)
2490 LOCK(m_inv_to_send_mutex);
2491 m_inbound_inv_bucket.backlog.push_back(wtxid);
2492 m_outbound_inv_bucket.backlog.push_back(wtxid);
2499 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2500 switch (m_tx_for_private_broadcast.
Add(tx)) {
2515void PeerManagerImpl::RelayAddress(
NodeId originator,
2516 const CAddress& addr,
2539 unsigned int nRelayNodes = (fReachable || (hasher.
Finalize() & 1)) ? 2 : 1;
2541 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2542 assert(nRelayNodes <= best.size());
2546 for (
auto& [
id, peer] : m_peer_map) {
2547 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2548 uint64_t hashKey =
CSipHasher(hasher).Write(
id).Finalize();
2549 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2550 if (hashKey > best[i].first) {
2551 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2552 best[i] = std::make_pair(hashKey, peer.get());
2559 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2560 PushAddress(*best[i].second, addr);
2564void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer,
const CInv& inv)
2574 std::shared_ptr<const CBlock> a_recent_block;
2575 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2577 LOCK(m_most_recent_block_mutex);
2578 a_recent_block = m_most_recent_block;
2579 a_recent_compact_block = m_most_recent_compact_block;
2582 bool need_activate_chain =
false;
2594 need_activate_chain =
true;
2598 if (need_activate_chain) {
2599 BlockValidationState state;
2600 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2605 const CBlockIndex* pindex{
nullptr};
2606 const CBlockIndex* tip{
nullptr};
2607 bool can_direct_fetch{
false};
2608 FlatFilePos block_pos{};
2615 if (!BlockRequestAllowed(*pindex)) {
2616 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2643 can_direct_fetch = CanDirectFetch();
2647 std::shared_ptr<const CBlock> pblock;
2648 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2649 pblock = a_recent_block;
2667 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2677 pblock = pblockRead;
2685 bool sendMerkleBlock =
false;
2686 CMerkleBlock merkleBlock;
2687 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2688 LOCK(tx_relay->m_bloom_filter_mutex);
2689 if (tx_relay->m_bloom_filter) {
2690 sendMerkleBlock =
true;
2691 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2694 if (sendMerkleBlock) {
2702 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2713 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2716 CBlockHeaderAndShortTxIDs cmpctblock{*pblock, m_rng.rand64()};
2726 LOCK(peer.m_block_inv_mutex);
2728 if (inv.
hash == peer.m_continuation_block) {
2732 std::vector<CInv> vInv;
2735 peer.m_continuation_block.SetNull();
2740CTransactionRef PeerManagerImpl::FindTxForGetData(
const Peer::TxRelay& tx_relay,
const GenTxid& gtxid)
2743 auto txinfo{std::visit(
2744 [&](
const auto&
id) {
2745 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2749 return std::move(txinfo.tx);
2754 LOCK(m_most_recent_block_mutex);
2755 if (m_most_recent_block_txs !=
nullptr) {
2756 auto it = m_most_recent_block_txs->find(gtxid);
2757 if (it != m_most_recent_block_txs->end())
return it->second;
2764void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2768 auto tx_relay = peer.GetTxRelay();
2770 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2771 std::vector<CInv> vNotFound;
2776 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2777 if (interruptMsgProc)
return;
2782 const CInv &inv = *it++;
2784 if (tx_relay ==
nullptr) {
2790 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2793 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2796 vNotFound.push_back(inv);
2802 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2803 const CInv &inv = *it++;
2805 ProcessGetBlockData(pfrom, peer, inv);
2814 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2816 if (!vNotFound.empty()) {
2835uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2837 uint32_t nFetchFlags = 0;
2838 if (CanServeWitnesses(peer)) {
2844void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, Peer& peer,
const CBlock& block,
const BlockTransactionsRequest&
req)
2846 BlockTransactions resp(
req);
2847 for (
size_t i = 0; i <
req.indexes.size(); i++) {
2848 if (
req.indexes[i] >= block.
vtx.size()) {
2849 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2852 resp.txn[i] = block.
vtx[
req.indexes[i]];
2856 uint32_t tx_requested_size{0};
2857 for (
const auto& tx : resp.txn) tx_requested_size += tx->ComputeTotalSize();
2863bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2867 Misbehaving(peer,
"header with invalid proof of work");
2872 if (!CheckHeadersAreContinuous(headers)) {
2873 Misbehaving(peer,
"non-continuous headers sequence");
2879arith_uint256 PeerManagerImpl::GetAntiDoSWorkThreshold()
2881 arith_uint256 near_chaintip_work = 0;
2898void PeerManagerImpl::HandleUnconnectingHeaders(CNode& pfrom, Peer& peer,
2899 const std::vector<CBlockHeader>& headers)
2902 const CBlockIndex* best_header{
WITH_LOCK(
cs_main,
return m_chainman.m_best_header)};
2903 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2904 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2906 headers[0].hashPrevBlock.ToString(),
2917bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2919 uint256 hashLastBlock;
2920 for (
const CBlockHeader& header : headers) {
2921 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2924 hashLastBlock = header.GetHash();
2929bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfrom, std::vector<CBlockHeader>& headers)
2931 if (peer.m_headers_sync) {
2932 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2934 if (result.success) peer.m_last_getheaders_timestamp = {};
2935 if (result.request_more) {
2936 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2938 Assume(!locator.vHave.empty());
2941 if (!locator.vHave.empty()) {
2944 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2947 locator.vHave.front().ToString(), pfrom.
GetId());
2951 if (peer.m_headers_sync->GetState() == HeadersSyncState::State::FINAL) {
2952 peer.m_headers_sync.reset(
nullptr);
2957 LOCK(m_headers_presync_mutex);
2958 m_headers_presync_stats.erase(pfrom.
GetId());
2961 HeadersPresyncStats stats;
2962 stats.first = peer.m_headers_sync->GetPresyncWork();
2963 if (peer.m_headers_sync->GetState() == HeadersSyncState::State::PRESYNC) {
2964 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2965 peer.m_headers_sync->GetPresyncTime()};
2969 LOCK(m_headers_presync_mutex);
2970 m_headers_presync_stats[pfrom.
GetId()] = stats;
2971 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2972 bool best_updated =
false;
2973 if (best_it == m_headers_presync_stats.end()) {
2977 const HeadersPresyncStats* stat_best{
nullptr};
2978 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2979 if (!stat_best || stat > *stat_best) {
2984 m_headers_presync_bestpeer = peer_best;
2985 best_updated = (peer_best == pfrom.
GetId());
2986 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2988 m_headers_presync_bestpeer = pfrom.
GetId();
2989 best_updated =
true;
2991 if (best_updated && stats.second.has_value()) {
2993 m_headers_presync_should_signal =
true;
2997 if (result.success) {
3000 headers.swap(result.pow_validated_headers);
3003 return result.success;
3011bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer, CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
3018 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
3022 if (total_work < minimum_chain_work) {
3026 if (headers.size() == m_opts.max_headers_result) {
3036 LOCK(peer.m_headers_sync_mutex);
3039 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
3040 }
catch (
const HeadersSyncState::SystemClockError& e) {
3045 const auto msg{
strprintf(
"Failure when attempting to initiate headers sync: %s", e.what())};
3046 std::cerr <<
msg << std::endl;
3054 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3068bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
3070 if (header ==
nullptr) {
3072 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
3080bool PeerManagerImpl::MaybeSendGetHeaders(CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
3088 peer.m_last_getheaders_timestamp = current_time;
3099void PeerManagerImpl::HeadersDirectFetchBlocks(CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
3102 CNodeState *nodestate =
State(pfrom.
GetId());
3105 std::vector<const CBlockIndex*> vToFetch;
3106 const CBlockIndex* pindexWalk{&last_header};
3113 vToFetch.push_back(pindexWalk);
3115 pindexWalk = pindexWalk->
pprev;
3127 std::vector<CInv> vGetData;
3129 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
3134 uint32_t nFetchFlags = GetFetchFlags(peer);
3136 BlockRequested(pfrom.
GetId(), *pindex);
3140 if (vGetData.size() > 1) {
3145 if (vGetData.size() > 0) {
3146 if (!m_opts.ignore_incoming_txs &&
3147 nodestate->m_provides_cmpctblocks &&
3148 vGetData.size() == 1 &&
3149 mapBlocksInFlight.size() == 1 &&
3165void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(CNode& pfrom,
3166 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
3169 CNodeState *nodestate =
State(pfrom.
GetId());
3178 nodestate->m_last_block_announcement =
GetTime();
3208 if (m_outbound_peers_with_protect_from_disconnect < MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT && nodestate->pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork && !nodestate->m_chain_sync.m_protect) {
3210 nodestate->m_chain_sync.m_protect =
true;
3211 ++m_outbound_peers_with_protect_from_disconnect;
3216void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
3217 std::vector<CBlockHeader>&& headers,
3218 bool via_compact_block)
3220 size_t nCount = headers.size();
3227 LOCK(peer.m_headers_sync_mutex);
3228 if (peer.m_headers_sync) {
3229 peer.m_headers_sync.reset(
nullptr);
3230 LOCK(m_headers_presync_mutex);
3231 m_headers_presync_stats.erase(pfrom.
GetId());
3235 peer.m_last_getheaders_timestamp = {};
3243 if (!CheckHeadersPoW(headers, peer)) {
3251 const CBlockIndex *pindexLast =
nullptr;
3258 bool already_validated_work =
false;
3261 bool have_headers_sync =
false;
3263 LOCK(peer.m_headers_sync_mutex);
3265 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3277 if (headers.empty()) {
3281 have_headers_sync = !!peer.m_headers_sync;
3286 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3288 if (!headers_connect_blockindex) {
3292 HandleUnconnectingHeaders(pfrom, peer, headers);
3299 peer.m_last_getheaders_timestamp = {};
3305 const CBlockIndex *last_received_header{
nullptr};
3309 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3316 already_validated_work =
true;
3322 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3323 *chain_start_header, headers)) {
3335 bool received_new_header{last_received_header ==
nullptr};
3338 BlockValidationState state;
3341 state, &pindexLast)};
3347 "If this happens with all peers, consider database corruption (that -reindex may fix) "
3348 "or a potential consensus incompatibility.",
3351 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3357 if (processed && received_new_header) {
3358 LogBlockHeader(*pindexLast, pfrom,
false);
3362 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3364 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3369 UpdatePeerStateForReceivedHeaders(pfrom, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3372 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3377std::optional<node::PackageToValidate> PeerManagerImpl::ProcessInvalidTx(
NodeId nodeid,
const CTransactionRef& ptx,
const TxValidationState& state,
3378 bool first_time_failure)
3384 PeerRef peer{GetPeerRef(nodeid)};
3387 ptx->GetHash().ToString(),
3388 ptx->GetWitnessHash().ToString(),
3392 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3394 if (add_extra_compact_tx && RecursiveDynamicUsage(*ptx) < 100000) {
3395 AddToCompactExtraTransactions(ptx);
3397 for (
const Txid& parent_txid : unique_parents) {
3398 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3401 return package_to_validate;
3404void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3410 m_txdownloadman.MempoolAcceptedTx(tx);
3414 tx->GetHash().ToString(),
3415 tx->GetWitnessHash().ToString(),
3418 InitiateTxBroadcastToAll(tx->GetWitnessHash());
3421 AddToCompactExtraTransactions(removedTx);
3425void PeerManagerImpl::ProcessPackageResult(
const node::PackageToValidate& package_to_validate,
const PackageMempoolAcceptResult& package_result)
3431 const auto&
package = package_to_validate.m_txns;
3432 const auto& senders = package_to_validate.
m_senders;
3435 m_txdownloadman.MempoolRejectedPackage(package);
3438 if (!
Assume(package.size() == 2))
return;
3442 auto package_iter = package.rbegin();
3443 auto senders_iter = senders.rbegin();
3444 while (package_iter != package.rend()) {
3445 const auto& tx = *package_iter;
3446 const NodeId nodeid = *senders_iter;
3447 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3451 const auto& tx_result = it_result->second;
3452 switch (tx_result.m_result_type) {
3455 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3465 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3483bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3488 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3490 const TxValidationState& state = result.
m_state;
3491 const Txid& orphanHash = porphanTx->GetHash();
3492 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3509 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3518bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& node, Peer& peer,
3520 const uint256& stop_hash, uint32_t max_height_diff,
3521 const CBlockIndex*& stop_index,
3522 BlockFilterIndex*& filter_index)
3524 const bool supported_filter_type =
3527 if (!supported_filter_type) {
3539 if (!stop_index || !BlockRequestAllowed(*stop_index)) {
3547 uint32_t stop_height = stop_index->
nHeight;
3548 if (start_height > stop_height) {
3550 "start height %d and stop height %d, %s",
3555 if (stop_height - start_height >= max_height_diff) {
3557 stop_height - start_height + 1, max_height_diff, node.
DisconnectMsg());
3563 if (!filter_index) {
3571void PeerManagerImpl::ProcessGetCFilters(CNode& node, Peer& peer, DataStream& vRecv)
3573 uint8_t filter_type_ser;
3574 uint32_t start_height;
3577 vRecv >> filter_type_ser >> start_height >> stop_hash;
3581 const CBlockIndex* stop_index;
3582 BlockFilterIndex* filter_index;
3583 if (!PrepareBlockFilterRequest(node, peer, filter_type, start_height, stop_hash,
3588 std::vector<BlockFilter> filters;
3590 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3595 for (
const auto& filter : filters) {
3600void PeerManagerImpl::ProcessGetCFHeaders(CNode& node, Peer& peer, DataStream& vRecv)
3602 uint8_t filter_type_ser;
3603 uint32_t start_height;
3606 vRecv >> filter_type_ser >> start_height >> stop_hash;
3610 const CBlockIndex* stop_index;
3611 BlockFilterIndex* filter_index;
3612 if (!PrepareBlockFilterRequest(node, peer, filter_type, start_height, stop_hash,
3617 uint256 prev_header;
3618 if (start_height > 0) {
3619 const CBlockIndex*
const prev_block =
3620 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3622 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3628 std::vector<uint256> filter_hashes;
3630 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3642void PeerManagerImpl::ProcessGetCFCheckPt(CNode& node, Peer& peer, DataStream& vRecv)
3644 uint8_t filter_type_ser;
3647 vRecv >> filter_type_ser >> stop_hash;
3651 const CBlockIndex* stop_index;
3652 BlockFilterIndex* filter_index;
3653 if (!PrepareBlockFilterRequest(node, peer, filter_type, 0, stop_hash,
3654 std::numeric_limits<uint32_t>::max(),
3655 stop_index, filter_index)) {
3662 const CBlockIndex* block_index = stop_index;
3663 for (
int i = headers.size() - 1; i >= 0; i--) {
3668 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3680void PeerManagerImpl::ProcessBlock(CNode& node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked)
3682 bool new_block{
false};
3683 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3690 RemoveBlockRequest(block->GetHash(), std::nullopt);
3693 mapBlockSource.erase(block->GetHash());
3697void PeerManagerImpl::ProcessCompactBlockTxns(CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3699 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3700 bool fBlockRead{
false};
3704 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3705 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3706 bool requested_block_from_this_peer{
false};
3709 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3711 while (range_flight.first != range_flight.second) {
3712 auto [node_id, block_it] = range_flight.first->second;
3713 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3714 requested_block_from_this_peer =
true;
3717 range_flight.first++;
3720 if (!requested_block_from_this_peer) {
3725 PartiallyDownloadedBlock& partialBlock = *range_flight.first->second.second->partialBlock;
3732 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3743 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3746 if (first_in_flight) {
3751 std::vector<CInv> invs;
3756 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3769 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3784void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3796 "Saw new %sheader hash=%s height=%d %s",
3797 via_compact_block ?
"cmpctblock " :
"",
3809void PeerManagerImpl::PushPrivateBroadcastTx(CNode& node)
3813 const auto opt_tx{m_tx_for_private_broadcast.
PickTxForSend(node.
GetId(), CService{node.addr})};
3822 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3825 MakeAndPushMessage(node,
NetMsgType::INV, std::vector<CInv>{{CInv{
MSG_TX, tx->GetHash().ToUint256()}}});
3828void PeerManagerImpl::ProcessMessage(Peer& peer, CNode& pfrom,
const std::string& msg_type, DataStream& vRecv,
3830 const std::atomic<bool>& interruptMsgProc)
3845 uint64_t nNonce = 1;
3848 std::string cleanSubVer;
3849 int starting_height = -1;
3852 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3867 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s",
3869 GetDesirableServiceFlags(nServices),
3882 if (!vRecv.
empty()) {
3890 if (!vRecv.
empty()) {
3891 std::string strSubVer;
3895 if (!vRecv.
empty()) {
3896 vRecv >> starting_height;
3916 PushNodeVersion(pfrom, peer);
3920 const int greatest_common_version = std::min(nVersion, pfrom.
AdvertisedVersion());
3925 peer.m_their_services = nServices;
3929 pfrom.cleanSubVer = cleanSubVer;
3940 (fRelay || (peer.m_our_services &
NODE_BLOOM))) {
3941 auto*
const tx_relay = peer.SetTxRelay();
3943 LOCK(tx_relay->m_bloom_filter_mutex);
3944 tx_relay->m_relay_txs = fRelay;
3950 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, %s%s",
3951 cleanSubVer.empty() ?
"<no user agent>" : cleanSubVer, pfrom.
nVersion,
3953 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3971 if (greatest_common_version >= 70016) {
3986 const auto* tx_relay = peer.GetTxRelay();
3987 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3989 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
4002 if (MaybeDisconnectForTxRelayCapacity(pfrom, msg_type, pfrom.
GetId()))
return;
4010 m_num_preferred_download_peers += state->fPreferredDownload;
4016 bool send_getaddr{
false};
4018 send_getaddr = SetupAddressRelay(pfrom, peer);
4028 peer.m_getaddr_sent =
true;
4056 m_outbound_time_offsets.
Add(peer.m_time_offset);
4061 if (greatest_common_version <= 70012) {
4062 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
4063 MakeAndPushMessage(pfrom,
"alert", finalAlert);
4086 auto new_peer_msg = [&]() {
4088 return strprintf(
"New %s peer connected: transport: %s, version: %d, %s%s",
4092 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
4100 LogInfo(
"%s", new_peer_msg());
4103 if (
auto tx_relay = peer.GetTxRelay()) {
4112 tx_relay->m_tx_inventory_mutex,
4113 return tx_relay->m_tx_inventory_to_send.empty() &&
4114 tx_relay->m_next_inv_send_time == 0s));
4124 PushPrivateBroadcastTx(pfrom);
4137 if (m_txreconciliation) {
4138 if (!peer.m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
4142 m_txreconciliation->ForgetPeer(pfrom.
GetId());
4148 const CNodeState* state =
State(pfrom.
GetId());
4149 m_txdownloadman.ConnectedPeer(pfrom.
GetId(), node::TxDownloadConnectionInfo {
4150 .m_preferred = state->fPreferredDownload,
4151 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
4152 .m_wtxid_relay = peer.m_wtxid_relay,
4161 peer.m_prefers_headers =
true;
4166 uint8_t sendcmpct_hb{0};
4167 uint64_t sendcmpct_version{0};
4168 vRecv >> sendcmpct_hb >> sendcmpct_version;
4172 if (sendcmpct_hb > 1) {
4173 Misbehaving(peer,
"invalid sendcmpct announce field");
4181 CNodeState* nodestate =
State(pfrom.
GetId());
4182 nodestate->m_provides_cmpctblocks =
true;
4183 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
4200 if (!peer.m_wtxid_relay) {
4201 peer.m_wtxid_relay =
true;
4202 m_wtxid_relay_peers++;
4221 peer.m_wants_addrv2 =
true;
4238 std::string feature_id;
4239 DataStream feature_data;
4242 std::vector<unsigned char> feature_data_vec;
4245 }
catch (
const std::exception&) {
4248 if (feature_id.size() < 4 || !vRecv.
empty()) {
4268 if (!m_txreconciliation) {
4269 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
4280 if (RejectIncomingTxs(pfrom)) {
4289 const auto* tx_relay = peer.GetTxRelay();
4290 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
4296 uint32_t peer_txreconcl_version;
4297 uint64_t remote_salt;
4298 vRecv >> peer_txreconcl_version >> remote_salt;
4301 peer_txreconcl_version, remote_salt);
4333 const auto ser_params{
4341 std::vector<CAddress> vAddr;
4342 vRecv >> ser_params(vAddr);
4343 ProcessAddrs(msg_type, pfrom, peer, std::move(vAddr), interruptMsgProc);
4348 std::vector<CInv> vInv;
4352 Misbehaving(peer,
strprintf(
"inv message size = %u", vInv.size()));
4356 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4357 std::unordered_set<uint256, SaltedUint256Hasher> seen_txids{0, m_txhash_hasher};
4358 std::unordered_set<uint256, SaltedUint256Hasher> seen_wtxids{0, m_txhash_hasher};
4363 uint256* best_block{
nullptr};
4365 for (CInv& inv : vInv) {
4366 if (interruptMsgProc)
return;
4371 if (peer.m_wtxid_relay) {
4378 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4381 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4389 best_block = &inv.
hash;
4392 if (reject_tx_invs) {
4398 auto& seen_hashes{inv.
IsMsgWtx() ? seen_wtxids : seen_txids};
4399 if (!seen_hashes.insert(inv.
hash).second)
continue;
4401 AddKnownTx(peer, inv.
hash);
4404 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4412 if (best_block !=
nullptr) {
4424 if (state.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4425 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer)) {
4427 m_chainman.m_best_header->nHeight, best_block->
ToString(),
4430 if (!state.fSyncStarted) {
4431 peer.m_inv_triggered_getheaders_before_sync =
true;
4435 m_last_block_inv_triggering_headers_sync = *best_block;
4444 std::vector<CInv> vInv;
4448 Misbehaving(peer,
strprintf(
"getdata message size = %u", vInv.size()));
4454 if (vInv.size() > 0) {
4459 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4460 if (!pushed_tx_opt) {
4471 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4475 peer.m_ping_queued =
true;
4486 LOCK(peer.m_getdata_requests_mutex);
4487 peer.m_getdata_requests.insert(peer.m_getdata_requests.end(), vInv.begin(), vInv.end());
4488 ProcessGetData(pfrom, peer, interruptMsgProc);
4495 CBlockLocator locator;
4497 vRecv >> locator >> hashStop;
4513 std::shared_ptr<const CBlock> a_recent_block;
4515 LOCK(m_most_recent_block_mutex);
4516 a_recent_block = m_most_recent_block;
4518 BlockValidationState state;
4519 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4534 for (; pindex; pindex = m_chainman.
ActiveChain().Next(*pindex))
4549 if (--nLimit <= 0) {
4553 WITH_LOCK(peer.m_block_inv_mutex, {peer.m_continuation_block = pindex->GetBlockHash();});
4561 BlockTransactionsRequest
req;
4565 if (
req.indexes.empty()) {
4573 for (
size_t i = 1; i <
req.indexes.size(); ++i) {
4577 std::shared_ptr<const CBlock> recent_block;
4579 LOCK(m_most_recent_block_mutex);
4580 if (m_most_recent_block_hash ==
req.blockhash)
4581 recent_block = m_most_recent_block;
4585 SendBlockTransactions(pfrom, peer, *recent_block,
req);
4589 FlatFilePos block_pos{};
4604 if (!block_pos.
IsNull()) {
4611 SendBlockTransactions(pfrom, peer, block,
req);
4624 WITH_LOCK(peer.m_getdata_requests_mutex, peer.m_getdata_requests.push_back(inv));
4630 CBlockLocator locator;
4632 vRecv >> locator >> hashStop;
4650 if (m_chainman.
ActiveTip() ==
nullptr ||
4652 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4659 CNodeState *nodestate =
State(pfrom.
GetId());
4660 const CBlockIndex* pindex =
nullptr;
4668 if (!BlockRequestAllowed(*pindex)) {
4669 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4682 std::vector<CBlock> vHeaders;
4683 int nLimit = m_opts.max_headers_result;
4685 for (; pindex; pindex = m_chainman.
ActiveChain().Next(*pindex))
4688 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4703 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4709 if (RejectIncomingTxs(pfrom)) {
4723 const Txid& txid = ptx->GetHash();
4724 const Wtxid& wtxid = ptx->GetWitnessHash();
4727 AddKnownTx(peer, hash);
4737 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4738 if (!should_validate) {
4743 if (!m_mempool.
exists(txid)) {
4744 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4747 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4749 InitiateTxBroadcastToAll(wtxid);
4753 if (package_to_validate) {
4756 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4757 ProcessPackageResult(package_to_validate.value(), package_result);
4763 Assume(!package_to_validate.has_value());
4766 const TxValidationState& state = result.
m_state;
4773 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4776 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4777 ProcessPackageResult(package_to_validate.value(), package_result);
4790 }
else if (m_opts.ignore_incoming_txs) {
4797 const CNodeState *nodestate =
State(pfrom.
GetId());
4798 if (!nodestate->m_provides_cmpctblocks) {
4804 CBlockHeaderAndShortTxIDs cmpctblock;
4805 vRecv >> cmpctblock;
4807 bool received_new_header =
false;
4817 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer);
4827 received_new_header =
true;
4831 const CBlockIndex *pindex =
nullptr;
4832 BlockValidationState state;
4835 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4842 if (received_new_header) {
4843 LogBlockHeader(*pindex, pfrom,
true);
4846 bool fProcessBLOCKTXN =
false;
4850 bool fRevertToHeaderProcessing =
false;
4854 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4855 bool fBlockReconstructed =
false;
4861 CNodeState *nodestate =
State(pfrom.
GetId());
4866 nodestate->m_last_block_announcement =
GetTime();
4872 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4873 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4874 bool requested_block_from_this_peer{
false};
4877 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4879 while (range_flight.first != range_flight.second) {
4880 if (range_flight.first->second.first == pfrom.
GetId()) {
4881 requested_block_from_this_peer =
true;
4884 range_flight.first++;
4894 if (requested_block_from_this_peer) {
4897 std::vector<CInv> vInv(1);
4905 if (!already_in_flight && !CanDirectFetch()) {
4913 requested_block_from_this_peer) {
4914 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4915 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4916 if (!(*queuedBlockIt)->partialBlock)
4925 PartiallyDownloadedBlock& partialBlock = *(*queuedBlockIt)->partialBlock;
4929 Misbehaving(peer,
"invalid compact block");
4932 if (first_in_flight) {
4934 std::vector<CInv> vInv(1);
4944 BlockTransactionsRequest
req;
4945 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4947 req.indexes.push_back(i);
4949 if (
req.indexes.empty()) {
4950 fProcessBLOCKTXN =
true;
4951 }
else if (first_in_flight) {
4958 IsBlockRequestedFromOutbound(blockhash) ||
4976 PartiallyDownloadedBlock tempBlock(&m_mempool);
4977 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4982 std::vector<CTransactionRef> dummy;
4984 status = tempBlock.FillBlock(*pblock, dummy,
4987 fBlockReconstructed =
true;
4991 if (requested_block_from_this_peer) {
4994 std::vector<CInv> vInv(1);
5000 fRevertToHeaderProcessing =
true;
5005 if (fProcessBLOCKTXN) {
5006 BlockTransactions txn;
5008 return ProcessCompactBlockTxns(pfrom, peer, txn);
5011 if (fRevertToHeaderProcessing) {
5017 return ProcessHeadersMessage(pfrom, peer, {cmpctblock.
header},
true);
5020 if (fBlockReconstructed) {
5025 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
5043 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
5057 BlockTransactions resp;
5060 return ProcessCompactBlockTxns(pfrom, peer, resp);
5071 std::vector<CBlockHeader> headers;
5075 if (nCount > m_opts.max_headers_result) {
5076 Misbehaving(peer,
strprintf(
"headers message size = %u", nCount));
5079 headers.resize(nCount);
5080 for (
unsigned int n = 0; n < nCount; n++) {
5081 vRecv >> headers[n];
5085 ProcessHeadersMessage(pfrom, peer, std::move(headers),
false);
5089 if (m_headers_presync_should_signal.exchange(
false)) {
5090 HeadersPresyncStats stats;
5092 LOCK(m_headers_presync_mutex);
5093 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
5094 if (it != m_headers_presync_stats.end()) stats = it->second;
5112 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
5123 Misbehaving(peer,
"mutated block");
5128 bool forceProcessing =
false;
5129 const uint256 hash(pblock->GetHash());
5130 bool min_pow_checked =
false;
5135 forceProcessing = IsBlockRequested(hash);
5136 RemoveBlockRequest(hash, pfrom.
GetId());
5140 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
5144 min_pow_checked =
true;
5147 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
5164 Assume(SetupAddressRelay(pfrom, peer));
5168 if (peer.m_getaddr_recvd) {
5172 peer.m_getaddr_recvd =
true;
5174 peer.m_addrs_to_send.clear();
5175 std::vector<CAddress> vAddr;
5181 for (
const CAddress &addr : vAddr) {
5182 PushAddress(peer, addr);
5210 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5211 LOCK(tx_relay->m_tx_inventory_mutex);
5212 tx_relay->m_send_mempool =
true;
5238 ProcessPong(pfrom, peer, time_received, vRecv);
5248 CBloomFilter filter;
5254 Misbehaving(peer,
"too-large bloom filter");
5255 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5257 LOCK(tx_relay->m_bloom_filter_mutex);
5258 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
5259 tx_relay->m_relay_txs =
true;
5263 MaybeDisconnectForTxRelayCapacity(pfrom, msg_type);
5274 std::vector<unsigned char> vData;
5282 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5283 LOCK(tx_relay->m_bloom_filter_mutex);
5284 if (tx_relay->m_bloom_filter) {
5285 tx_relay->m_bloom_filter->insert(vData);
5291 Misbehaving(peer,
"bad filteradd message");
5302 auto tx_relay = peer.GetTxRelay();
5303 if (!tx_relay)
return;
5306 LOCK(tx_relay->m_bloom_filter_mutex);
5307 tx_relay->m_bloom_filter =
nullptr;
5308 tx_relay->m_relay_txs =
true;
5312 MaybeDisconnectForTxRelayCapacity(pfrom, msg_type);
5318 vRecv >> newFeeFilter;
5320 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5321 tx_relay->m_fee_filter_received = newFeeFilter;
5329 ProcessGetCFilters(pfrom, peer, vRecv);
5334 ProcessGetCFHeaders(pfrom, peer, vRecv);
5339 ProcessGetCFCheckPt(pfrom, peer, vRecv);
5344 std::vector<CInv> vInv;
5346 std::vector<GenTxid> tx_invs;
5348 for (CInv &inv : vInv) {
5354 LOCK(m_tx_download_mutex);
5355 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5364bool PeerManagerImpl::MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer)
5367 LOCK(peer.m_misbehavior_mutex);
5370 if (!peer.m_should_discourage)
return false;
5372 peer.m_should_discourage =
false;
5377 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5383 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5409bool PeerManagerImpl::MaybeDisconnectForTxRelayCapacity(CNode& node,
const std::string& msg_type, std::optional<NodeId> protect_peer)
5414 LogDebug(
BCLog::NET,
"failed to find a tx-relaying eviction candidate - connection dropped after %s message, peer=%d\n", msg_type, node.
GetId());
5419bool PeerManagerImpl::ProcessMessages(CNode& node, std::atomic<bool>& interruptMsgProc)
5424 PeerRef maybe_peer{GetPeerRef(node.
GetId())};
5425 if (maybe_peer ==
nullptr)
return false;
5426 Peer& peer{*maybe_peer};
5430 if (!node.
IsInboundConn() && !peer.m_outbound_version_message_sent)
return false;
5433 LOCK(peer.m_getdata_requests_mutex);
5434 if (!peer.m_getdata_requests.empty()) {
5435 ProcessGetData(node, peer, interruptMsgProc);
5439 const bool processed_orphan = ProcessOrphanTx(peer);
5444 if (processed_orphan)
return true;
5449 LOCK(peer.m_getdata_requests_mutex);
5450 if (!peer.m_getdata_requests.empty())
return true;
5462 CNetMessage&
msg{poll_result->first};
5463 bool fMoreWork = poll_result->second;
5474 if (m_opts.capture_messages) {
5479 ProcessMessage(peer, node,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5480 if (interruptMsgProc)
return false;
5482 LOCK(peer.m_getdata_requests_mutex);
5483 if (!peer.m_getdata_requests.empty()) fMoreWork =
true;
5490 LOCK(m_tx_download_mutex);
5491 if (m_txdownloadman.HaveMoreWork(peer.m_id)) fMoreWork =
true;
5492 }
catch (
const std::exception& e) {
5501void PeerManagerImpl::ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5516 if (state.m_chain_sync.m_timeout != 0s) {
5517 state.m_chain_sync.m_timeout = 0
s;
5518 state.m_chain_sync.m_work_header =
nullptr;
5519 state.m_chain_sync.m_sent_getheaders =
false;
5521 }
else if (state.m_chain_sync.m_timeout == 0s || (state.m_chain_sync.m_work_header !=
nullptr && state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->
nChainWork >= state.m_chain_sync.m_work_header->
nChainWork)) {
5529 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5530 state.m_chain_sync.m_sent_getheaders =
false;
5531 }
else if (state.m_chain_sync.m_timeout > 0s && time_in_seconds > state.m_chain_sync.m_timeout) {
5535 if (state.m_chain_sync.m_sent_getheaders) {
5540 assert(state.m_chain_sync.m_work_header);
5545 MaybeSendGetHeaders(pto,
5548 LogDebug(
BCLog::NET,
"sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->
GetBlockHash().
ToString() :
"<none>", state.m_chain_sync.m_work_header->
GetBlockHash().
ToString());
5549 state.m_chain_sync.m_sent_getheaders =
true;
5570 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5574 if (pnode->
GetId() > youngest_peer.first) {
5575 next_youngest_peer = youngest_peer;
5576 youngest_peer.first = pnode->
GetId();
5580 NodeId to_disconnect = youngest_peer.first;
5581 if (youngest_peer.second > next_youngest_peer.second) {
5584 to_disconnect = next_youngest_peer.first;
5593 CNodeState *node_state =
State(pnode->
GetId());
5594 if (node_state ==
nullptr ||
5597 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5601 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5617 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5620 AssertLockHeld(::cs_main);
5624 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5625 CNodeState *state = State(pnode->GetId());
5626 if (state == nullptr) return;
5628 if (state->m_chain_sync.m_protect) return;
5631 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5632 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5633 worst_peer = pnode->GetId();
5634 oldest_block_announcement = state->m_last_block_announcement;
5637 if (worst_peer != -1) {
5648 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5652 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5669void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5676 EvictExtraOutboundPeers(current_time);
5678 if (now > m_stale_tip_check_time) {
5682 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5691 if (!m_initial_sync_finished && CanDirectFetch()) {
5693 m_initial_sync_finished =
true;
5700 peer.m_ping_nonce_sent &&
5710 bool pingSend =
false;
5712 if (peer.m_ping_queued) {
5717 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5726 }
while (nonce == 0);
5727 peer.m_ping_queued =
false;
5728 peer.m_ping_start = now;
5730 peer.m_ping_nonce_sent = nonce;
5734 peer.m_ping_nonce_sent = 0;
5740void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time)
5743 if (!peer.m_addr_relay_enabled)
return;
5745 LOCK(peer.m_addr_send_times_mutex);
5748 peer.m_next_local_addr_send < current_time) {
5755 if (peer.m_next_local_addr_send != 0us) {
5756 peer.m_addr_known->reset();
5759 CAddress local_addr{*local_service, peer.m_our_services,
Now<NodeSeconds>()};
5760 if (peer.m_next_local_addr_send == 0us) {
5764 if (IsAddrCompatible(peer, local_addr)) {
5765 std::vector<CAddress> self_announcement{local_addr};
5766 if (peer.m_wants_addrv2) {
5774 PushAddress(peer, local_addr);
5781 if (current_time <= peer.m_next_addr_send)
return;
5794 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5795 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5798 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5799 peer.m_addrs_to_send.end());
5802 if (peer.m_addrs_to_send.empty())
return;
5804 if (peer.m_wants_addrv2) {
5809 peer.m_addrs_to_send.clear();
5812 if (peer.m_addrs_to_send.capacity() > 40) {
5813 peer.m_addrs_to_send.shrink_to_fit();
5817void PeerManagerImpl::MaybeSendSendHeaders(CNode& node, Peer& peer)
5826 if (state.pindexBestKnownBlock !=
nullptr &&
5833 peer.m_sent_sendheaders =
true;
5838void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5840 if (m_opts.ignore_incoming_txs)
return;
5856 if (peer.m_fee_filter_sent == MAX_FILTER) {
5859 peer.m_next_send_feefilter = 0us;
5862 if (current_time > peer.m_next_send_feefilter) {
5863 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5866 if (filterToSend != peer.m_fee_filter_sent) {
5868 peer.m_fee_filter_sent = filterToSend;
5875 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5880bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5890void PeerManagerImpl::ProcessPong(CNode& pfrom, Peer& peer,
const NodeClock::time_point ping_end, DataStream& vRecv)
5893 const size_t nAvail{vRecv.
size()};
5894 bool bPingFinished =
false;
5895 std::string sProblem;
5897 if (nAvail >=
sizeof(nonce)) {
5901 if (peer.m_ping_nonce_sent != 0) {
5902 if (nonce == peer.m_ping_nonce_sent) {
5904 bPingFinished =
true;
5905 const auto ping_time = ping_end - peer.m_ping_start.load();
5906 if (ping_time.count() >= 0) {
5917 sProblem =
"Timing mishap";
5921 sProblem =
"Nonce mismatch";
5924 bPingFinished =
true;
5925 sProblem =
"Nonce zero";
5929 sProblem =
"Unsolicited pong without ping";
5933 bPingFinished =
true;
5934 sProblem =
"Short payload";
5937 if (!(sProblem.empty())) {
5941 peer.m_ping_nonce_sent,
5945 if (bPingFinished) {
5946 peer.m_ping_nonce_sent = 0;
5950bool PeerManagerImpl::SetupAddressRelay(
const CNode& node, Peer& peer)
5962 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5966 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5972void PeerManagerImpl::ProcessAddrs(std::string_view msg_type, CNode& pfrom, Peer& peer, std::vector<CAddress>&& vAddr,
const std::atomic<bool>& interruptMsgProc)
5977 if (!SetupAddressRelay(pfrom, peer)) {
5984 Misbehaving(peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
5989 std::vector<CAddress> vAddrOk;
5995 const auto time_diff{current_time - peer.m_addr_token_timestamp};
5999 peer.m_addr_token_timestamp = current_time;
6002 uint64_t num_proc = 0;
6003 uint64_t num_rate_limit = 0;
6004 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
6005 for (CAddress& addr : vAddr)
6007 if (interruptMsgProc)
6011 if (peer.m_addr_token_bucket < 1.0) {
6017 peer.m_addr_token_bucket -= 1.0;
6022 if (!MayHaveUsefulAddressDB(addr.
nServices) && !HasAllDesirableServiceFlags(addr.
nServices))
6026 addr.
nTime = std::chrono::time_point_cast<std::chrono::seconds>(current_time - 5 * 24h);
6028 AddAddressKnown(peer, addr);
6035 if (addr.
nTime > current_time - 10min && !peer.m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
6037 RelayAddress(pfrom.
GetId(), addr, reachable);
6041 vAddrOk.push_back(addr);
6044 peer.m_addr_processed += num_proc;
6045 peer.m_addr_rate_limited += num_rate_limit;
6046 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
6047 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
6049 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
6050 if (vAddr.size() < 1000) peer.m_getaddr_sent =
false;
6059bool PeerManagerImpl::SendMessages(CNode& node)
6064 PeerRef maybe_peer{GetPeerRef(node.
GetId())};
6065 if (!maybe_peer)
return false;
6066 Peer& peer{*maybe_peer};
6067 const Consensus::Params& consensusParams = m_chainparams.
GetConsensus();
6071 if (MaybeDiscourageAndDisconnect(node, peer))
return true;
6074 if (!node.
IsInboundConn() && !peer.m_outbound_version_message_sent) {
6075 PushNodeVersion(node, peer);
6076 peer.m_outbound_version_message_sent =
true;
6104 MaybeSendPing(node, peer, now);
6109 MaybeSendAddr(node, peer, current_time);
6111 MaybeSendSendHeaders(node, peer);
6113 ProcessInvBacklog(now);
6121 if (m_chainman.m_best_header ==
nullptr) {
6128 bool sync_blocks_and_headers_from_peer =
false;
6129 if (state.fPreferredDownload) {
6130 sync_blocks_and_headers_from_peer =
true;
6141 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
6142 sync_blocks_and_headers_from_peer =
true;
6148 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
6149 const CBlockIndex* pindexStart = m_chainman.m_best_header;
6157 if (pindexStart->
pprev)
6158 pindexStart = pindexStart->
pprev;
6159 if (MaybeSendGetHeaders(node,
GetLocator(pindexStart), peer)) {
6162 state.fSyncStarted =
true;
6186 LOCK(peer.m_block_inv_mutex);
6187 std::vector<CBlock> vHeaders;
6188 bool fRevertToInv = ((!peer.m_prefers_headers &&
6189 (!state.m_requested_hb_cmpctblocks || peer.m_blocks_for_headers_relay.size() > 1)) ||
6191 const CBlockIndex *pBestIndex =
nullptr;
6192 ProcessBlockAvailability(node.
GetId());
6194 if (!fRevertToInv) {
6195 bool fFoundStartingHeader =
false;
6199 for (
const uint256& hash : peer.m_blocks_for_headers_relay) {
6204 fRevertToInv =
true;
6207 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
6219 fRevertToInv =
true;
6222 pBestIndex = pindex;
6223 if (fFoundStartingHeader) {
6226 }
else if (PeerHasHeader(&state, pindex)) {
6228 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
6231 fFoundStartingHeader =
true;
6236 fRevertToInv =
true;
6241 if (!fRevertToInv && !vHeaders.empty()) {
6242 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
6246 vHeaders.front().GetHash().ToString(), node.
GetId());
6248 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
6250 LOCK(m_most_recent_block_mutex);
6251 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
6255 if (cached_cmpctblock_msg.has_value()) {
6256 PushMessage(node, std::move(cached_cmpctblock_msg.value()));
6261 CBlockHeaderAndShortTxIDs cmpctblock{block, m_rng.rand64()};
6264 state.pindexBestHeaderSent = pBestIndex;
6265 }
else if (peer.m_prefers_headers) {
6266 if (vHeaders.size() > 1) {
6269 vHeaders.front().GetHash().ToString(),
6270 vHeaders.back().GetHash().ToString(), node.
GetId());
6273 vHeaders.front().GetHash().ToString(), node.
GetId());
6276 state.pindexBestHeaderSent = pBestIndex;
6278 fRevertToInv =
true;
6284 if (!peer.m_blocks_for_headers_relay.empty()) {
6285 const uint256& hashToAnnounce = peer.m_blocks_for_headers_relay.back();
6298 if (!PeerHasHeader(&state, pindex)) {
6299 peer.m_blocks_for_inv_relay.push_back(hashToAnnounce);
6305 peer.m_blocks_for_headers_relay.clear();
6311 std::vector<CInv> vInv;
6313 LOCK(peer.m_block_inv_mutex);
6314 vInv.reserve(peer.m_blocks_for_inv_relay.size());
6317 for (
const uint256& hash : peer.m_blocks_for_inv_relay) {
6324 peer.m_blocks_for_inv_relay.clear();
6327 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
6328 LOCK(tx_relay->m_tx_inventory_mutex);
6331 if (tx_relay->m_next_inv_send_time < current_time) {
6332 fSendTrickle =
true;
6342 LOCK(tx_relay->m_bloom_filter_mutex);
6343 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
6347 if (fSendTrickle && tx_relay->m_send_mempool) {
6348 auto vtxinfo = m_mempool.
infoAll();
6353 tx_relay->m_send_mempool =
false;
6354 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6357 tx_relay->m_tx_inventory_to_send.clear();
6359 LOCK(tx_relay->m_bloom_filter_mutex);
6361 for (
const auto& txinfo : vtxinfo) {
6362 const Txid& txid{txinfo.tx->GetHash()};
6363 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
6364 const auto inv = peer.m_wtxid_relay ?
6369 if (txinfo.fee < filterrate.
GetFee(txinfo.vsize)) {
6372 if (tx_relay->m_bloom_filter) {
6373 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6375 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6376 vInv.push_back(inv);
6388 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6391 auto& invs = tx_relay->m_tx_inventory_to_send;
6392 std::vector<CTransactionRef> res;
6394 if (invs.size() == 0)
return res;
6397 if (invs.capacity() > 2 * invs.size()) invs.shrink_to_fit();
6401 res.reserve(txiters.size());
6402 for (
auto txiter : txiters) {
6403 if (txiter->GetFee() < filterrate.
GetFee(txiter->GetTxSize())) {
6406 res.push_back(txiter->GetSharedTx());
6409 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6413 LOCK(tx_relay->m_bloom_filter_mutex);
6414 vInv.reserve(std::min<size_t>(
MAX_INV_SZ, vInv.size() + inv_tx.size()));
6415 for (
auto& tx : inv_tx) {
6419 const auto inv = peer.m_wtxid_relay ?
6420 CInv{
MSG_WTX, tx->GetWitnessHash().ToUint256()} :
6421 CInv{
MSG_TX, tx->GetHash().ToUint256()};
6423 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
6426 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*tx))
continue;
6428 vInv.push_back(inv);
6433 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6441 auto stalling_timeout = m_block_stalling_timeout.load();
6442 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6451 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6461 if (state.vBlocksInFlight.size() > 0) {
6462 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6463 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6471 if (state.fSyncStarted && peer.m_headers_sync_timeout < std::chrono::microseconds::max()) {
6473 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6474 if (current_time > peer.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6491 state.fSyncStarted =
false;
6493 peer.m_headers_sync_timeout = 0us;
6499 peer.m_headers_sync_timeout = std::chrono::microseconds::max();
6510 std::vector<CInv> vGetData;
6512 std::vector<const CBlockIndex*> vToDownload;
6514 auto get_inflight_budget = [&state]() {
6521 FindNextBlocksToDownload(peer, get_inflight_budget(), vToDownload, staller);
6522 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
6523 if (historical_blocks && !IsLimitedPeer(peer)) {
6526 const CBlockIndex* from_tip =
LastCommonAncestor(historical_blocks->first, historical_blocks->second);
6527 TryDownloadingHistoricalBlocks(
6529 get_inflight_budget(),
6530 vToDownload, from_tip, historical_blocks->second);
6532 for (
const CBlockIndex *pindex : vToDownload) {
6533 uint32_t nFetchFlags = GetFetchFlags(peer);
6535 BlockRequested(node.
GetId(), *pindex);
6539 if (state.vBlocksInFlight.empty() && staller != -1) {
6540 if (
State(staller)->m_stalling_since == 0us) {
6541 State(staller)->m_stalling_since = current_time;
6551 LOCK(m_tx_download_mutex);
6552 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(node.
GetId(), current_time)) {
6561 if (!vGetData.empty())
6564 MaybeSendFeefilter(node, peer, current_time);
constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative).
std::string ToString(const T &t)
Locale-independent version of std::to_string.
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_HAVE_DATA
full block available in blk*.dat
arith_uint256 GetBlockProof(const CBlockIndex &block)
Compute how much work a block index entry corresponds to.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
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.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
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
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
static constexpr SerParams V1_NETWORK
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V2_NETWORK
size_t BlockTxCount() const
std::vector< CTransactionRef > vtx
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
bool IsWithinSizeConstraints() const
bool Contains(const CBlockIndex &index) const
Efficiently check whether a block is present in this chain.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex &index) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
const HeadersSyncParams & HeadersSync() const
const Consensus::Params & GetConsensus() const
void NumToOpenAdd(size_t n)
Increment the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
size_t NumToOpenSub(size_t n)
Decrement the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
bool GetNetworkActive() const
bool GetTryNewOutboundPeer() const
class CConnman::PrivateBroadcast m_private_broadcast
bool ShouldRunInactivityChecks(const CNode &node, NodeClock::time_point now) const
Return true if we should disconnect the peer for failing an inactivity check.
std::vector< CAddress > GetAddresses(CNode &requestor, size_t max_addresses, size_t max_pct)
Return addresses from the per-requestor cache.
void SetTryNewOutboundPeer(bool flag)
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
void StartExtraBlockRelayPeers()
void ForEachNode(const NodeFn &func) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
bool EvictTxPeerIfFull(std::optional< NodeId > protect_peer=std::nullopt) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
If we are at capacity for inbound tx-relay peers, attempt to evict one.
uint32_t GetMappedAS(const CNetAddr &addr) const
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return randomly selected addresses.
int GetExtraBlockRelayCount() const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
bool DisconnectNode(std::string_view node) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
Mutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
int GetExtraFullOutboundCount() const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
bool GetUseAddrmanOutgoing() const
bool CheckIncomingNonce(uint64_t nonce) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
CFeeRate()=default
Fee rate of 0 satoshis per 0 vB.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
CAmount GetFee(int32_t virtual_bytes) const
Return the fee in satoshis for the given vsize in vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
std::vector< std::pair< unsigned int, Txid > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Information about a peer.
bool IsFeelerConn() const
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
std::string LogPeer() const
Helper function to log the peer id, optionally including IP address.
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
const std::string m_addr_name
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
std::atomic< bool > m_bip152_highbandwidth_from
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
const NodeClock::time_point m_connected
Unix epoch time at peer connection.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
const uint64_t m_network_key
Network key used to prevent fingerprinting our node across networks.
std::atomic_bool fPauseSend
std::string DisconnectMsg() const
Helper function to log disconnects.
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.
void PongReceived(NodeClock::duration ping_time)
A ping-pong round trip has completed successfully. Update latest and minimum ping durations.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
bool IsPrivateBroadcastConn() const
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
const NetPermissionFlags m_permission_flags
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
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....
int AdvertisedVersion() const
Protocol version advertised in our VERSION message.
std::atomic_bool fDisconnect
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....
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher(uint64_t k0, uint64_t k1)
Construct a SipHash calculator initialized with 128-bit key (k0, k1).
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
TxMempoolInfo info_for_relay(const T &id, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
CFeeRate GetMinFee(size_t sizelimit) const
CTransactionRef get(const Txid &hash) const
Return a mempool transaction with a given hash.
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
bool exists(const Txid &txid) const
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
std::set< Txid > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
unsigned long size() const
void RemoveUnbroadcastTx(const Txid &txid, bool unchecked=false)
Removes a transaction from the unbroadcast set.
std::vector< txiter > ExtractBestByMiningScoreWithTopology(std::vector< Wtxid > &wtxids, size_t n_to_sort) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Look up wtxids in the mempool and (partially) sort by mining score.
void ClearBlockIndexCandidates() EXCLUSIVE_LOCKS_REQUIRED(void PopulateBlockIndexCandidates() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex * FindForkInGlobalIndex(const CBlockLocator &locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Populate the candidate set by calling TryAddBlockIndexCandidate on all valid block indices.
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
bool IsInitialBlockDownload() const noexcept
Check whether we are doing an initial block download (synchronizing from disk or network).
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Chainstate & ActiveChainstate() const
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool ProcessNewBlockHeaders(std::span< const CBlockHeader > headers, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const arith_uint256 & MinimumChainWork() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
void ReportHeadersPresync(int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
node::BlockManager m_blockman
void ignore(size_t num_ignore)
FastRandomContext(bool fDeterministic=false) noexcept
Construct a FastRandomContext with GetRandHash()-based entropy (or zero key if fDeterministic).
const uint256 & ToUint256() const LIFETIMEBOUND
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
PartiallyDownloadedBlock(CTxMemPool *poolIn)
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing, bool segwit_active)
bool IsTxAvailable(size_t index) const
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< Wtxid, CTransactionRef > > &extra_txn)
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
void NodeConfirmedReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Mark that the node has confirmed reception of the transaction we sent it by responding with PONG to o...
AddResult Add(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a transaction to the storage, or reset an exhausted transaction so it can be broadcast again.
std::vector< TxBroadcastInfo > GetBroadcastInfo() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get stats about all transactions currently being privately broadcast.
bool MarkResolved(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Mark a transaction as resolved because it was received back from the network or is no longer acceptab...
@ QueueFull
Rejected: the queue is already at MAX_TRANSACTIONS.
@ AlreadyPresent
The transaction was already present with send attempts remaining; no change.
@ Added
The transaction was newly added or reset after exhausting its send attempts.
bool HavePendingTransactions() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if there are transactions with send attempts remaining.
std::optional< size_t > Remove(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Forget a transaction.
void NodeDisconnected(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Mark a connection finished.
std::optional< CTransactionRef > PickTxForSend(const NodeId &will_send_to_nodeid, const CService &will_send_to_address) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Pick the transaction with the fewest send attempts, and confirmations, and oldest send/confirm times.
bool TryGrantRetry(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Grant one additional send attempt if the transaction is unresolved, all planned sends have been picke...
static constexpr size_t MAX_TRANSACTIONS
Maximum number of transactions tracked simultaneously.
std::optional< CTransactionRef > GetTxForNode(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transaction that was picked for sending to a given node by PickTxForSend().
std::vector< CTransactionRef > GetStale() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transactions that have not been broadcast recently and have send attempts remaining.
static constexpr size_t INITIAL_CONNECTION_COUNT
Number of connections to make for initial broadcast.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
void Add(std::chrono::seconds offset) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a new time offset sample.
bool WarnIfOutOfSync() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Raise warnings if the median time offset exceeds the warnings threshold.
std::chrono::seconds Median() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Compute and return the median of the collected time offset samples.
std::string GetDebugMessage() const
std::string ToString() const
constexpr bool IsNull() const
std::string ToString() const
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
CBlockFileInfo *GetBlockFileInfo(size_t n) EXCLUSIVE_LOCKS_REQUIRED(bool WriteBlockUndo(const CBlockUndo &blockundo, BlockValidationState &state, CBlockIndex &block) EXCLUSIVE_LOCKS_REQUIRED(FlatFilePos WriteBlock(const CBlock &block, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(void UpdateBlockInfo(const CBlock &block, unsigned int nHeight, const FlatFilePos &pos) EXCLUSIVE_LOCKS_REQUIRED(bool IsPruneMode() const
Get block file info entry for one block file.
bool LoadingBlocks() const
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t > > block_part=std::nullopt) const
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
Manages warning messages within a node.
std::string ToString() const
const uint256 & ToUint256() const LIFETIMEBOUND
constexpr uint256()=default
double value() const
Current token balance.
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
@ 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_UNKNOWN
transaction was not validated because package failed
@ 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
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
#define LogDebug(category,...)
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * FEATURE
BIP 434 Peer feature negotiation.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
bool ShouldDebugLog(Category category)
Return whether messages with specified category should be debug logged.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
constexpr unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
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_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr auto INVENTORY_BUCKET_CHECK_DELAY
Delay between checking inventory bucket and backlog.
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 auto INVENTORY_BUCKET_BACKLOG_HEARTBEAT
Delay between inventory bucket backlog heartbeat log entries.
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 AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
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 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 constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
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 size_t INVENTORY_BUCKET_BACKLOG_CAPACITY
Empty backlog target capacity.
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 constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
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 double OUTBOUND_INVENTORY_BUCKET_MULTIPLIER
Multiplier for the inventory bucket rate for outbounds.
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 PRIVATE_BROADCAST_MAX_CONNECTION_LIFETIME
Private broadcast connections must complete within this time.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
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 constexpr size_t INVENTORY_BUCKET_BACKLOG_HEARTBEAT_MIN
Minimum backlog to trigger heartbeat log entries.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
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.
constexpr unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
constexpr TransactionSerParams TX_NO_WITNESS
constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
constexpr size_t MAX_FEATUREDATA_LENGTH
constexpr uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
constexpr size_t MAX_FEATUREID_LENGTH
constexpr int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
constexpr int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
constexpr int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
constexpr int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
constexpr int WTXID_RELAY_VERSION
"wtxidrelay" message type for wtxid-based relay starts with this version
constexpr int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
constexpr int FEATURE_VERSION
"feature" message type for feature negotiation starts with this version
constexpr int SENDHEADERS_VERSION
"sendheaders" message type and announcing blocks with headers starts with this version
constexpr unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_VECTOR(obj, n)
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
std::vector< uint256 > vHave
NodeClock::duration m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
std::chrono::seconds time_offset
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
CSerializedNetMsg Copy() const
int64_t nPowTargetSpacing
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
const std::list< CTransactionRef > m_replaced_transactions
Mempool transactions replaced by the tx.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
static constexpr time_point epoch
PackageValidationState m_state
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
Information about chainstate that notifications are sent from.
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation).
std::vector< NodeId > m_senders
std::string ToString() const
#define AssertLockNotHeld(cs)
AnnotatedMixin< std::mutex > Mutex
Wrapped mutex: supports waiting but not recursive locking.
AnnotatedMixin< std::recursive_mutex > RecursiveMutex
Wrapped mutex: supports recursive locking, but no waiting TODO: We should move away from using the re...
#define WITH_LOCK(cs, code)
#define AssertLockHeld(cs)
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
#define TRACEPOINT(context,...)
#define TRACEPOINT_SEMAPHORE(context, event)
transaction_identifier< true > Wtxid
Wtxid commits to all transaction fields including the witness.
transaction_identifier< false > Txid
Txid commits to all transaction fields except the witness.
consteval auto _(util::TranslatedLiteral str)
ReconciliationRegisterResult
constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
constexpr auto TicksSinceEpoch(Timepoint t)
T Now()
Return the current time point cast to the given precision.
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
bool HasValidProofOfWork(std::span< const CBlockHeader > headers, const Consensus::Params &consensusParams)
Check that the proof of work on each blockheader matches the value in nBits.
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
@ UNVALIDATED
Blocks after an assumeutxo snapshot have been validated but the snapshot itself has not been validate...
constexpr unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...