74#include <initializer_list>
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);
276 std::atomic<uint64_t> m_ping_nonce_sent{0};
278 std::atomic<std::chrono::microseconds> m_ping_start{0us};
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};
308 std::set<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>;
443 uint256 hashLastUnknownBlock{};
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};
492 bool m_sent_getheaders{
false};
494 bool m_protect{
false};
497 ChainSyncTimeoutState m_chain_sync;
500 int64_t m_last_block_announcement{0};
529 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
546 void SetBestBlock(
int height,
std::chrono::seconds time)
override
548 m_best_height = height;
549 m_best_block_time = time;
556 void ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv, std::chrono::microseconds time_received,
557 const std::atomic<bool>& interruptMsgProc)
558 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
570 void ReattemptPrivateBroadcast(
CScheduler& scheduler);
582 void Misbehaving(Peer& peer,
const std::string& message);
593 bool via_compact_block,
const std::string& message =
"")
602 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
616 bool first_time_failure)
641 bool ProcessOrphanTx(Peer& peer)
651 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
653 bool via_compact_block)
657 bool CheckHeadersPoW(const
std::vector<
CBlockHeader>& headers, Peer& peer);
665 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
684 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
698 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
713 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
715 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
722 template <
typename... Args>
723 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
729 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
735 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
778 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
781 std::atomic<int> m_best_height{-1};
783 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
791 const Options m_opts;
793 bool RejectIncomingTxs(
const CNode& peer)
const;
801 mutable Mutex m_peer_mutex;
808 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
818 uint32_t GetFetchFlags(
const Peer& peer)
const;
820 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
837 std::atomic<int> m_wtxid_relay_peers{0};
855 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
856 std::chrono::seconds average_interval,
861 Mutex m_most_recent_block_mutex;
862 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
863 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
865 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
869 Mutex m_headers_presync_mutex;
877 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
879 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
883 std::atomic_bool m_headers_presync_should_signal{
false};
953 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
959 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
964 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
997 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
999 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1011 int64_t ApproximateBestBlockDepth() const;
1021 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1039 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1041 const
uint256& stop_hash, uint32_t max_height_diff,
1086 void ProcessAddrs(
std::string_view msg_type,
CNode& pfrom, Peer& peer,
std::vector<
CAddress>&& vAddr, const
std::atomic<
bool>& interruptMsgProc)
1092 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1098const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const
1100 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1101 if (it == m_node_states.end())
1108 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1116static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1121void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1123 assert(peer.m_addr_known);
1124 peer.m_addr_known->insert(addr.
GetKey());
1127void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1132 assert(peer.m_addr_known);
1133 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1135 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1137 peer.m_addrs_to_send.push_back(addr);
1142static void AddKnownTx(Peer& peer,
const uint256& hash)
1144 auto tx_relay = peer.GetTxRelay();
1145 if (!tx_relay)
return;
1147 LOCK(tx_relay->m_tx_inventory_mutex);
1148 tx_relay->m_tx_inventory_known_filter.insert(hash);
1152static bool CanServeBlocks(
const Peer& peer)
1159static bool IsLimitedPeer(
const Peer& peer)
1166static bool CanServeWitnesses(
const Peer& peer)
1171std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1172 std::chrono::seconds average_interval,
1173 uint64_t network_key)
1175 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1176 auto& timer{it->second};
1178 timer = now + m_rng.rand_exp_duration(average_interval);
1183bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1185 return mapBlocksInFlight.contains(hash);
1188bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1190 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1191 auto [nodeid, block_it] = range.first->second;
1192 PeerRef peer{GetPeerRef(nodeid)};
1193 if (peer && !peer->m_is_inbound)
return true;
1199void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1201 auto range = mapBlocksInFlight.equal_range(hash);
1202 if (range.first == range.second) {
1210 while (range.first != range.second) {
1211 const auto& [node_id, list_it]{range.first->second};
1213 if (from_peer && *from_peer != node_id) {
1220 if (state.vBlocksInFlight.begin() == list_it) {
1222 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1224 state.vBlocksInFlight.erase(list_it);
1226 if (state.vBlocksInFlight.empty()) {
1228 m_peers_downloading_from--;
1230 state.m_stalling_since = 0us;
1232 range.first = mapBlocksInFlight.erase(range.first);
1236bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1240 CNodeState *state =
State(nodeid);
1241 assert(state !=
nullptr);
1246 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1247 if (range.first->second.first == nodeid) {
1249 *pit = &range.first->second.second;
1256 RemoveBlockRequest(hash, nodeid);
1258 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1259 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1260 if (state->vBlocksInFlight.size() == 1) {
1262 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1263 m_peers_downloading_from++;
1265 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1267 *pit = &itInFlight->second.second;
1272void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1279 if (m_opts.ignore_incoming_txs)
return;
1281 CNodeState* nodestate =
State(nodeid);
1282 PeerRef peer{GetPeerRef(nodeid)};
1283 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1288 int num_outbound_hb_peers = 0;
1289 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1290 if (*it == nodeid) {
1291 lNodesAnnouncingHeaderAndIDs.erase(it);
1292 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1295 PeerRef peer_ref{GetPeerRef(*it)};
1296 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1298 if (peer && peer->m_is_inbound) {
1301 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1302 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1303 if (remove_peer && !remove_peer->m_is_inbound) {
1306 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1312 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1315 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1316 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1318 pnodeStop->m_bip152_highbandwidth_to = false;
1321 lNodesAnnouncingHeaderAndIDs.pop_front();
1326 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1331bool PeerManagerImpl::TipMayBeStale()
1335 if (m_last_tip_update.load() == 0
s) {
1336 m_last_tip_update = GetTime<std::chrono::seconds>();
1338 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1341int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1346bool PeerManagerImpl::CanDirectFetch()
1353 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1355 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1360void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1361 CNodeState *state =
State(nodeid);
1362 assert(state !=
nullptr);
1364 if (!state->hashLastUnknownBlock.IsNull()) {
1367 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1368 state->pindexBestKnownBlock = pindex;
1370 state->hashLastUnknownBlock.SetNull();
1375void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1376 CNodeState *state =
State(nodeid);
1377 assert(state !=
nullptr);
1379 ProcessBlockAvailability(nodeid);
1384 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1385 state->pindexBestKnownBlock = pindex;
1389 state->hashLastUnknownBlock = hash;
1394void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1399 vBlocks.reserve(vBlocks.size() +
count);
1400 CNodeState *state =
State(peer.m_id);
1401 assert(state !=
nullptr);
1404 ProcessBlockAvailability(peer.m_id);
1406 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1417 state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1418 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1427 if (state->pindexLastCommonBlock ==
nullptr ||
1428 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1429 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1430 state->pindexLastCommonBlock = fork_point;
1432 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1435 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1441 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1444void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1449 if (vBlocks.size() >=
count) {
1453 vBlocks.reserve(
count);
1456 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1473void 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)
1475 std::vector<const CBlockIndex*> vToFetch;
1476 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1477 bool is_limited_peer = IsLimitedPeer(peer);
1479 while (pindexWalk->
nHeight < nMaxHeight) {
1483 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1484 vToFetch.resize(nToFetch);
1485 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1486 vToFetch[nToFetch - 1] = pindexWalk;
1487 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1488 vToFetch[i - 1] = vToFetch[i]->
pprev;
1508 state->pindexLastCommonBlock = pindex;
1515 if (waitingfor == -1) {
1517 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1523 if (pindex->
nHeight > nWindowEnd) {
1525 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1527 if (nodeStaller) *nodeStaller = waitingfor;
1537 vBlocks.push_back(pindex);
1538 if (vBlocks.size() ==
count) {
1547void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1549 uint64_t my_services;
1551 uint64_t your_services;
1553 std::string my_user_agent;
1561 my_user_agent =
"/pynode:0.0.1/";
1563 my_tx_relay =
false;
1566 my_services = peer.m_our_services;
1571 my_height = m_best_height;
1572 my_tx_relay = !RejectIncomingTxs(pnode);
1591 BCLog::NET,
"send version message: version=%d, blocks=%d%s, txrelay=%d, peer=%d\n",
1594 my_tx_relay, pnode.
GetId());
1597void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1601 if (state) state->m_last_block_announcement = time_in_seconds;
1609 m_node_states.try_emplace(m_node_states.end(), nodeid);
1611 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1617 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1620 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1624void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1628 for (
const auto& txid : unbroadcast_txids) {
1631 if (tx !=
nullptr) {
1632 InitiateTxBroadcastToAll(txid, tx->GetWitnessHash());
1641 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1644void PeerManagerImpl::ReattemptPrivateBroadcast(
CScheduler& scheduler)
1648 size_t num_for_rebroadcast{0};
1649 const auto stale_txs = m_tx_for_private_broadcast.
GetStale();
1650 if (!stale_txs.empty()) {
1652 for (
const auto& stale_tx : stale_txs) {
1656 "Reattempting broadcast of stale txid=%s wtxid=%s",
1657 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString());
1658 ++num_for_rebroadcast;
1661 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString(),
1662 mempool_acceptable.m_state.ToString());
1663 m_tx_for_private_broadcast.
Remove(stale_tx);
1672 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, delta);
1675void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1686 PeerRef peer = RemovePeer(nodeid);
1688 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1689 assert(m_wtxid_relay_peers >= 0);
1691 CNodeState *state =
State(nodeid);
1692 assert(state !=
nullptr);
1694 if (state->fSyncStarted)
1697 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1698 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1699 while (range.first != range.second) {
1700 auto [node_id, list_it] = range.first->second;
1701 if (node_id != nodeid) {
1704 range.first = mapBlocksInFlight.erase(range.first);
1709 LOCK(m_tx_download_mutex);
1710 m_txdownloadman.DisconnectedPeer(nodeid);
1712 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1713 m_num_preferred_download_peers -= state->fPreferredDownload;
1714 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1715 assert(m_peers_downloading_from >= 0);
1716 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1717 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1719 m_node_states.erase(nodeid);
1721 if (m_node_states.empty()) {
1723 assert(mapBlocksInFlight.empty());
1724 assert(m_num_preferred_download_peers == 0);
1725 assert(m_peers_downloading_from == 0);
1726 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1727 assert(m_wtxid_relay_peers == 0);
1728 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1731 if (
node.fSuccessfullyConnected &&
1732 !
node.IsBlockOnlyConn() && !
node.IsPrivateBroadcastConn() && !
node.IsInboundConn()) {
1740 LOCK(m_headers_presync_mutex);
1741 m_headers_presync_stats.erase(nodeid);
1743 if (
node.IsPrivateBroadcastConn() &&
1752bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1755 return !(GetDesirableServiceFlags(services) & (~services));
1769PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1772 auto it = m_peer_map.find(
id);
1773 return it != m_peer_map.end() ? it->second :
nullptr;
1776PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1780 auto it = m_peer_map.find(
id);
1781 if (it != m_peer_map.end()) {
1782 ret = std::move(it->second);
1783 m_peer_map.erase(it);
1792 const CNodeState* state =
State(nodeid);
1793 if (state ==
nullptr)
1795 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1796 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1797 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1803 PeerRef peer = GetPeerRef(nodeid);
1804 if (peer ==
nullptr)
return false;
1812 auto ping_wait{0us};
1813 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1814 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1817 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1820 LOCK(tx_relay->m_tx_inventory_mutex);
1822 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1834 LOCK(peer->m_headers_sync_mutex);
1835 if (peer->m_headers_sync) {
1844std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1846 LOCK(m_tx_download_mutex);
1847 return m_txdownloadman.GetOrphanTransactions();
1854 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1858std::vector<PrivateBroadcast::TxBroadcastInfo> PeerManagerImpl::GetPrivateBroadcastInfo()
const
1863std::vector<CTransactionRef> PeerManagerImpl::AbortPrivateBroadcast(
const uint256&
id)
1866 std::vector<CTransactionRef> removed_txs;
1868 size_t connections_cancelled{0};
1869 for (
const auto& tx_info : snapshot) {
1871 if (tx->GetHash().ToUint256() !=
id && tx->GetWitnessHash().ToUint256() !=
id)
continue;
1872 if (
const auto peer_acks{m_tx_for_private_broadcast.
Remove(tx)}) {
1873 removed_txs.push_back(tx);
1884void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1886 if (m_opts.max_extra_txs <= 0)
1888 if (!vExtraTxnForCompact.size())
1889 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1890 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1891 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1894void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1896 LOCK(peer.m_misbehavior_mutex);
1898 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1899 peer.m_should_discourage =
true;
1908 bool via_compact_block,
const std::string& message)
1910 PeerRef peer{GetPeerRef(nodeid)};
1921 if (!via_compact_block) {
1922 if (peer) Misbehaving(*peer, message);
1930 if (peer && !via_compact_block && !peer->m_is_inbound) {
1931 if (peer) Misbehaving(*peer, message);
1938 if (peer) Misbehaving(*peer, message);
1942 if (peer) Misbehaving(*peer, message);
1947 if (message !=
"") {
1952bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex& block_index)
1966 PeerRef peer = GetPeerRef(peer_id);
1975 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1978 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
2001 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
2007 : m_rng{opts.deterministic_rng},
2009 m_chainparams(chainman.GetParams()),
2013 m_chainman(chainman),
2015 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
2016 m_warnings{warnings},
2021 if (opts.reconcile_txs) {
2026void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2037 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2039 if (m_opts.private_broadcast) {
2040 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2044void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2052 LOCK(m_tx_download_mutex);
2056 m_txdownloadman.ActiveTipChange();
2066void PeerManagerImpl::BlockConnected(
2068 const std::shared_ptr<const CBlock>& pblock,
2073 m_last_tip_update = GetTime<std::chrono::seconds>();
2076 auto stalling_timeout = m_block_stalling_timeout.load();
2080 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2089 LOCK(m_tx_download_mutex);
2090 m_txdownloadman.BlockConnected(pblock);
2094void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2096 LOCK(m_tx_download_mutex);
2097 m_txdownloadman.BlockDisconnected();
2104void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2106 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2110 if (pindex->
nHeight <= m_highest_fast_announce)
2112 m_highest_fast_announce = pindex->
nHeight;
2116 uint256 hashBlock(pblock->GetHash());
2117 const std::shared_future<CSerializedNetMsg> lazy_ser{
2121 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2122 for (
const auto& tx : pblock->vtx) {
2123 most_recent_block_txs->emplace(tx->GetHash(), tx);
2124 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2127 LOCK(m_most_recent_block_mutex);
2128 m_most_recent_block_hash = hashBlock;
2129 m_most_recent_block = pblock;
2130 m_most_recent_compact_block = pcmpctblock;
2131 m_most_recent_block_txs = std::move(most_recent_block_txs);
2139 ProcessBlockAvailability(pnode->
GetId());
2143 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2145 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2146 hashBlock.ToString(), pnode->
GetId());
2149 PushMessage(*pnode, ser_cmpctblock.Copy());
2150 state.pindexBestHeaderSent = pindex;
2159void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2161 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2164 if (fInitialDownload)
return;
2167 std::vector<uint256> vHashes;
2169 while (pindexToAnnounce != pindexFork) {
2171 pindexToAnnounce = pindexToAnnounce->
pprev;
2181 for (
auto& it : m_peer_map) {
2182 Peer& peer = *it.second;
2183 LOCK(peer.m_block_inv_mutex);
2184 for (
const uint256& hash : vHashes | std::views::reverse) {
2185 peer.m_blocks_for_headers_relay.push_back(hash);
2197void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2201 const uint256 hash(block->GetHash());
2202 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2207 it != mapBlockSource.end() &&
2208 State(it->second.first)) {
2209 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2219 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2220 if (it != mapBlockSource.end()) {
2221 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2224 if (it != mapBlockSource.end())
2225 mapBlockSource.erase(it);
2233bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2238void PeerManagerImpl::SendPings()
2241 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2244void PeerManagerImpl::InitiateTxBroadcastToAll(
const Txid& txid,
const Wtxid& wtxid)
2247 for(
auto& it : m_peer_map) {
2248 Peer& peer = *it.second;
2249 auto tx_relay = peer.GetTxRelay();
2250 if (!tx_relay)
continue;
2252 LOCK(tx_relay->m_tx_inventory_mutex);
2258 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2261 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2262 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2267void PeerManagerImpl::InitiateTxBroadcastPrivate(
const CTransactionRef& tx)
2269 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2270 if (m_tx_for_private_broadcast.
Add(tx)) {
2278void PeerManagerImpl::RelayAddress(
NodeId originator,
2294 const auto current_time{GetTime<std::chrono::seconds>()};
2302 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2304 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2305 assert(nRelayNodes <= best.size());
2309 for (
auto& [
id, peer] : m_peer_map) {
2310 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2312 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2313 if (hashKey > best[i].first) {
2314 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2315 best[i] = std::make_pair(hashKey, peer.get());
2322 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2323 PushAddress(*best[i].second, addr);
2327void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2329 std::shared_ptr<const CBlock> a_recent_block;
2330 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2332 LOCK(m_most_recent_block_mutex);
2333 a_recent_block = m_most_recent_block;
2334 a_recent_compact_block = m_most_recent_compact_block;
2337 bool need_activate_chain =
false;
2349 need_activate_chain =
true;
2353 if (need_activate_chain) {
2355 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2362 bool can_direct_fetch{
false};
2370 if (!BlockRequestAllowed(*pindex)) {
2371 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2398 can_direct_fetch = CanDirectFetch();
2402 std::shared_ptr<const CBlock> pblock;
2403 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2404 pblock = a_recent_block;
2422 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2432 pblock = pblockRead;
2440 bool sendMerkleBlock =
false;
2442 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2443 LOCK(tx_relay->m_bloom_filter_mutex);
2444 if (tx_relay->m_bloom_filter) {
2445 sendMerkleBlock =
true;
2446 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2449 if (sendMerkleBlock) {
2457 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2468 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2481 LOCK(peer.m_block_inv_mutex);
2483 if (inv.
hash == peer.m_continuation_block) {
2487 std::vector<CInv> vInv;
2488 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2490 peer.m_continuation_block.SetNull();
2498 auto txinfo{std::visit(
2499 [&](
const auto&
id) {
2500 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2504 return std::move(txinfo.tx);
2509 LOCK(m_most_recent_block_mutex);
2510 if (m_most_recent_block_txs !=
nullptr) {
2511 auto it = m_most_recent_block_txs->find(gtxid);
2512 if (it != m_most_recent_block_txs->end())
return it->second;
2519void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2523 auto tx_relay = peer.GetTxRelay();
2525 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2526 std::vector<CInv> vNotFound;
2531 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2532 if (interruptMsgProc)
return;
2537 const CInv &inv = *it++;
2539 if (tx_relay ==
nullptr) {
2545 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2548 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2551 vNotFound.push_back(inv);
2557 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2558 const CInv &inv = *it++;
2560 ProcessGetBlockData(pfrom, peer, inv);
2569 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2571 if (!vNotFound.empty()) {
2590uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2592 uint32_t nFetchFlags = 0;
2593 if (CanServeWitnesses(peer)) {
2602 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2604 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2611 uint32_t tx_requested_size{0};
2612 for (
const auto& tx : resp.txn) tx_requested_size += tx->ComputeTotalSize();
2618bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2622 Misbehaving(peer,
"header with invalid proof of work");
2627 if (!CheckHeadersAreContinuous(headers)) {
2628 Misbehaving(peer,
"non-continuous headers sequence");
2653void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2654 const std::vector<CBlockHeader>& headers)
2658 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2659 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2661 headers[0].hashPrevBlock.ToString(),
2662 best_header->nHeight,
2672bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2676 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2679 hashLastBlock = header.GetHash();
2684bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2686 if (peer.m_headers_sync) {
2687 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2689 if (result.success) peer.m_last_getheaders_timestamp = {};
2690 if (result.request_more) {
2691 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2693 Assume(!locator.vHave.empty());
2696 if (!locator.vHave.empty()) {
2699 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2702 locator.vHave.front().ToString(), pfrom.
GetId());
2707 peer.m_headers_sync.reset(
nullptr);
2712 LOCK(m_headers_presync_mutex);
2713 m_headers_presync_stats.erase(pfrom.
GetId());
2716 HeadersPresyncStats stats;
2717 stats.first = peer.m_headers_sync->GetPresyncWork();
2719 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2720 peer.m_headers_sync->GetPresyncTime()};
2724 LOCK(m_headers_presync_mutex);
2725 m_headers_presync_stats[pfrom.
GetId()] = stats;
2726 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2727 bool best_updated =
false;
2728 if (best_it == m_headers_presync_stats.end()) {
2732 const HeadersPresyncStats* stat_best{
nullptr};
2733 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2734 if (!stat_best || stat > *stat_best) {
2739 m_headers_presync_bestpeer = peer_best;
2740 best_updated = (peer_best == pfrom.
GetId());
2741 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2743 m_headers_presync_bestpeer = pfrom.
GetId();
2744 best_updated =
true;
2746 if (best_updated && stats.second.has_value()) {
2748 m_headers_presync_should_signal =
true;
2752 if (result.success) {
2755 headers.swap(result.pow_validated_headers);
2758 return result.success;
2766bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
2773 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2777 if (total_work < minimum_chain_work) {
2781 if (headers.size() == m_opts.max_headers_result) {
2791 LOCK(peer.m_headers_sync_mutex);
2793 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2798 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2812bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2814 if (header ==
nullptr) {
2816 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2824bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2832 peer.m_last_getheaders_timestamp = current_time;
2843void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2846 CNodeState *nodestate =
State(pfrom.
GetId());
2849 std::vector<const CBlockIndex*> vToFetch;
2857 vToFetch.push_back(pindexWalk);
2859 pindexWalk = pindexWalk->
pprev;
2870 std::vector<CInv> vGetData;
2872 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2877 uint32_t nFetchFlags = GetFetchFlags(peer);
2879 BlockRequested(pfrom.
GetId(), *pindex);
2883 if (vGetData.size() > 1) {
2888 if (vGetData.size() > 0) {
2889 if (!m_opts.ignore_incoming_txs &&
2890 nodestate->m_provides_cmpctblocks &&
2891 vGetData.size() == 1 &&
2892 mapBlocksInFlight.size() == 1 &&
2908void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2909 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2912 CNodeState *nodestate =
State(pfrom.
GetId());
2921 nodestate->m_last_block_announcement =
GetTime();
2929 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2951 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) {
2953 nodestate->m_chain_sync.m_protect =
true;
2954 ++m_outbound_peers_with_protect_from_disconnect;
2959void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2960 std::vector<CBlockHeader>&& headers,
2961 bool via_compact_block)
2963 size_t nCount = headers.size();
2970 LOCK(peer.m_headers_sync_mutex);
2971 if (peer.m_headers_sync) {
2972 peer.m_headers_sync.reset(
nullptr);
2973 LOCK(m_headers_presync_mutex);
2974 m_headers_presync_stats.erase(pfrom.
GetId());
2978 peer.m_last_getheaders_timestamp = {};
2986 if (!CheckHeadersPoW(headers, peer)) {
3001 bool already_validated_work =
false;
3004 bool have_headers_sync =
false;
3006 LOCK(peer.m_headers_sync_mutex);
3008 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3020 if (headers.empty()) {
3024 have_headers_sync = !!peer.m_headers_sync;
3029 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3031 if (!headers_connect_blockindex) {
3035 HandleUnconnectingHeaders(pfrom, peer, headers);
3042 peer.m_last_getheaders_timestamp = {};
3052 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3059 already_validated_work =
true;
3065 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3066 *chain_start_header, headers)) {
3078 bool received_new_header{last_received_header ==
nullptr};
3084 state, &pindexLast)};
3090 "If this happens with all peers, consider database corruption (that -reindex may fix) "
3091 "or a potential consensus incompatibility.",
3094 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3100 if (processed && received_new_header) {
3101 LogBlockHeader(*pindexLast, pfrom,
false);
3105 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3107 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3112 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3115 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3121 bool first_time_failure)
3127 PeerRef peer{GetPeerRef(nodeid)};
3130 ptx->GetHash().ToString(),
3131 ptx->GetWitnessHash().ToString(),
3135 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3138 AddToCompactExtraTransactions(ptx);
3140 for (
const Txid& parent_txid : unique_parents) {
3141 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3144 return package_to_validate;
3147void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3153 m_txdownloadman.MempoolAcceptedTx(tx);
3157 tx->GetHash().ToString(),
3158 tx->GetWitnessHash().ToString(),
3161 InitiateTxBroadcastToAll(tx->GetHash(), tx->GetWitnessHash());
3164 AddToCompactExtraTransactions(removedTx);
3174 const auto&
package = package_to_validate.m_txns;
3175 const auto& senders = package_to_validate.
m_senders;
3178 m_txdownloadman.MempoolRejectedPackage(package);
3181 if (!
Assume(package.size() == 2))
return;
3185 auto package_iter = package.rbegin();
3186 auto senders_iter = senders.rbegin();
3187 while (package_iter != package.rend()) {
3188 const auto& tx = *package_iter;
3189 const NodeId nodeid = *senders_iter;
3190 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3194 const auto& tx_result = it_result->second;
3195 switch (tx_result.m_result_type) {
3198 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3208 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3226bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3233 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3236 const Txid& orphanHash = porphanTx->GetHash();
3237 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3254 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3263bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3265 const uint256& stop_hash, uint32_t max_height_diff,
3269 const bool supported_filter_type =
3272 if (!supported_filter_type) {
3274 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg());
3275 node.fDisconnect =
true;
3284 if (!stop_index || !BlockRequestAllowed(*stop_index)) {
3287 node.fDisconnect =
true;
3292 uint32_t stop_height = stop_index->
nHeight;
3293 if (start_height > stop_height) {
3295 "start height %d and stop height %d, %s",
3296 start_height, stop_height,
node.DisconnectMsg());
3297 node.fDisconnect =
true;
3300 if (stop_height - start_height >= max_height_diff) {
3302 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg());
3303 node.fDisconnect =
true;
3308 if (!filter_index) {
3318 uint8_t filter_type_ser;
3319 uint32_t start_height;
3322 vRecv >> filter_type_ser >> start_height >> stop_hash;
3328 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3333 std::vector<BlockFilter> filters;
3335 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3340 for (
const auto& filter : filters) {
3347 uint8_t filter_type_ser;
3348 uint32_t start_height;
3351 vRecv >> filter_type_ser >> start_height >> stop_hash;
3357 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3363 if (start_height > 0) {
3365 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3367 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3373 std::vector<uint256> filter_hashes;
3375 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3389 uint8_t filter_type_ser;
3392 vRecv >> filter_type_ser >> stop_hash;
3398 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3399 std::numeric_limits<uint32_t>::max(),
3400 stop_index, filter_index)) {
3408 for (
int i = headers.size() - 1; i >= 0; i--) {
3413 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3427 bool new_block{
false};
3428 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3430 node.m_last_block_time = GetTime<std::chrono::seconds>();
3435 RemoveBlockRequest(block->GetHash(), std::nullopt);
3438 mapBlockSource.erase(block->GetHash());
3442void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3444 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3445 bool fBlockRead{
false};
3449 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3450 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3451 bool requested_block_from_this_peer{
false};
3454 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3456 while (range_flight.first != range_flight.second) {
3457 auto [node_id, block_it] = range_flight.first->second;
3458 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3459 requested_block_from_this_peer =
true;
3462 range_flight.first++;
3465 if (!requested_block_from_this_peer) {
3477 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3488 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3491 if (first_in_flight) {
3496 std::vector<CInv> invs;
3501 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3514 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3529void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3541 "Saw new %sheader hash=%s height=%d %s",
3542 via_compact_block ?
"cmpctblock " :
"",
3554void PeerManagerImpl::PushPrivateBroadcastTx(
CNode&
node)
3561 node.fDisconnect =
true;
3567 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3573void PeerManagerImpl::ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3574 const std::chrono::microseconds time_received,
3575 const std::atomic<bool>& interruptMsgProc)
3590 uint64_t nNonce = 1;
3593 std::string cleanSubVer;
3594 int starting_height = -1;
3597 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3612 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s",
3614 GetDesirableServiceFlags(nServices),
3627 if (!vRecv.
empty()) {
3635 if (!vRecv.
empty()) {
3636 std::string strSubVer;
3640 if (!vRecv.
empty()) {
3641 vRecv >> starting_height;
3661 PushNodeVersion(pfrom, peer);
3670 peer.m_their_services = nServices;
3674 pfrom.cleanSubVer = cleanSubVer;
3685 (fRelay || (peer.m_our_services &
NODE_BLOOM))) {
3686 auto*
const tx_relay = peer.SetTxRelay();
3688 LOCK(tx_relay->m_bloom_filter_mutex);
3689 tx_relay->m_relay_txs = fRelay;
3695 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, %s%s",
3696 cleanSubVer.empty() ?
"<no user agent>" : cleanSubVer, pfrom.
nVersion,
3698 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3716 if (greatest_common_version >= 70016) {
3731 const auto* tx_relay = peer.GetTxRelay();
3732 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3734 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3747 m_num_preferred_download_peers += state->fPreferredDownload;
3753 bool send_getaddr{
false};
3755 send_getaddr = SetupAddressRelay(pfrom, peer);
3765 peer.m_getaddr_sent =
true;
3789 peer.m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3793 m_outbound_time_offsets.Add(peer.m_time_offset);
3794 m_outbound_time_offsets.WarnIfOutOfSync();
3798 if (greatest_common_version <= 70012) {
3799 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3800 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3823 auto new_peer_msg = [&]() {
3825 return strprintf(
"New %s peer connected: transport: %s, version: %d, %s%s",
3829 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3837 LogInfo(
"%s", new_peer_msg());
3840 if (
auto tx_relay = peer.GetTxRelay()) {
3849 tx_relay->m_tx_inventory_mutex,
3850 return tx_relay->m_tx_inventory_to_send.empty() &&
3851 tx_relay->m_next_inv_send_time == 0
s));
3861 PushPrivateBroadcastTx(pfrom);
3874 if (m_txreconciliation) {
3875 if (!peer.m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3879 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3885 const CNodeState* state =
State(pfrom.
GetId());
3887 .m_preferred = state->fPreferredDownload,
3888 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3889 .m_wtxid_relay = peer.m_wtxid_relay,
3898 peer.m_prefers_headers =
true;
3903 bool sendcmpct_hb{
false};
3904 uint64_t sendcmpct_version{0};
3905 vRecv >> sendcmpct_hb >> sendcmpct_version;
3911 CNodeState* nodestate =
State(pfrom.
GetId());
3912 nodestate->m_provides_cmpctblocks =
true;
3913 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3930 if (!peer.m_wtxid_relay) {
3931 peer.m_wtxid_relay =
true;
3932 m_wtxid_relay_peers++;
3951 peer.m_wants_addrv2 =
true;
3959 if (!m_txreconciliation) {
3960 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3971 if (RejectIncomingTxs(pfrom)) {
3980 const auto* tx_relay = peer.GetTxRelay();
3981 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3987 uint32_t peer_txreconcl_version;
3988 uint64_t remote_salt;
3989 vRecv >> peer_txreconcl_version >> remote_salt;
3992 peer_txreconcl_version, remote_salt);
4024 const auto ser_params{
4032 std::vector<CAddress> vAddr;
4033 vRecv >> ser_params(vAddr);
4034 ProcessAddrs(msg_type, pfrom, peer, std::move(vAddr), interruptMsgProc);
4039 std::vector<CInv> vInv;
4043 Misbehaving(peer,
strprintf(
"inv message size = %u", vInv.size()));
4047 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4051 const auto current_time{GetTime<std::chrono::microseconds>()};
4054 for (
CInv& inv : vInv) {
4055 if (interruptMsgProc)
return;
4060 if (peer.m_wtxid_relay) {
4067 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4070 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4078 best_block = &inv.
hash;
4081 if (reject_tx_invs) {
4087 AddKnownTx(peer, inv.
hash);
4090 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4098 if (best_block !=
nullptr) {
4110 if (state.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4111 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer)) {
4113 m_chainman.m_best_header->nHeight, best_block->ToString(),
4116 if (!state.fSyncStarted) {
4117 peer.m_inv_triggered_getheaders_before_sync =
true;
4121 m_last_block_inv_triggering_headers_sync = *best_block;
4130 std::vector<CInv> vInv;
4134 Misbehaving(peer,
strprintf(
"getdata message size = %u", vInv.size()));
4140 if (vInv.size() > 0) {
4145 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4146 if (!pushed_tx_opt) {
4157 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4161 peer.m_ping_queued =
true;
4162 MaybeSendPing(pfrom, peer, GetTime<std::chrono::microseconds>());
4172 LOCK(peer.m_getdata_requests_mutex);
4173 peer.m_getdata_requests.insert(peer.m_getdata_requests.end(), vInv.begin(), vInv.end());
4174 ProcessGetData(pfrom, peer, interruptMsgProc);
4183 vRecv >> locator >> hashStop;
4199 std::shared_ptr<const CBlock> a_recent_block;
4201 LOCK(m_most_recent_block_mutex);
4202 a_recent_block = m_most_recent_block;
4205 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4220 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4235 if (--nLimit <= 0) {
4239 WITH_LOCK(peer.m_block_inv_mutex, {peer.m_continuation_block = pindex->GetBlockHash();});
4251 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4255 std::shared_ptr<const CBlock> recent_block;
4257 LOCK(m_most_recent_block_mutex);
4258 if (m_most_recent_block_hash == req.
blockhash)
4259 recent_block = m_most_recent_block;
4263 SendBlockTransactions(pfrom, peer, *recent_block, req);
4282 if (!block_pos.IsNull()) {
4289 SendBlockTransactions(pfrom, peer, block, req);
4302 WITH_LOCK(peer.m_getdata_requests_mutex, peer.m_getdata_requests.push_back(inv));
4310 vRecv >> locator >> hashStop;
4328 if (m_chainman.
ActiveTip() ==
nullptr ||
4330 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4337 CNodeState *nodestate =
State(pfrom.
GetId());
4346 if (!BlockRequestAllowed(*pindex)) {
4347 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4360 std::vector<CBlock> vHeaders;
4361 int nLimit = m_opts.max_headers_result;
4363 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4366 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4381 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4387 if (RejectIncomingTxs(pfrom)) {
4401 const Txid& txid = ptx->GetHash();
4402 const Wtxid& wtxid = ptx->GetWitnessHash();
4405 AddKnownTx(peer, hash);
4407 if (
const auto num_broadcasted{m_tx_for_private_broadcast.
Remove(ptx)}) {
4409 "network from %s; stopping private broadcast attempts",
4420 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4421 if (!should_validate) {
4426 if (!m_mempool.
exists(txid)) {
4427 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4430 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4432 InitiateTxBroadcastToAll(txid, wtxid);
4436 if (package_to_validate) {
4439 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4440 ProcessPackageResult(package_to_validate.value(), package_result);
4446 Assume(!package_to_validate.has_value());
4456 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4459 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4460 ProcessPackageResult(package_to_validate.value(), package_result);
4476 vRecv >> cmpctblock;
4478 bool received_new_header =
false;
4488 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer);
4498 received_new_header =
true;
4506 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4513 if (received_new_header) {
4514 LogBlockHeader(*pindex, pfrom,
true);
4517 bool fProcessBLOCKTXN =
false;
4521 bool fRevertToHeaderProcessing =
false;
4525 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4526 bool fBlockReconstructed =
false;
4532 CNodeState *nodestate =
State(pfrom.
GetId());
4537 nodestate->m_last_block_announcement =
GetTime();
4543 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4544 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4545 bool requested_block_from_this_peer{
false};
4548 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4550 while (range_flight.first != range_flight.second) {
4551 if (range_flight.first->second.first == pfrom.
GetId()) {
4552 requested_block_from_this_peer =
true;
4555 range_flight.first++;
4560 if (requested_block_from_this_peer) {
4563 std::vector<CInv> vInv(1);
4571 if (!already_in_flight && !CanDirectFetch()) {
4579 requested_block_from_this_peer) {
4580 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4581 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4582 if (!(*queuedBlockIt)->partialBlock)
4595 Misbehaving(peer,
"invalid compact block");
4598 if (first_in_flight) {
4600 std::vector<CInv> vInv(1);
4611 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4616 fProcessBLOCKTXN =
true;
4617 }
else if (first_in_flight) {
4624 IsBlockRequestedFromOutbound(blockhash) ||
4643 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4648 std::vector<CTransactionRef> dummy;
4650 status = tempBlock.FillBlock(*pblock, dummy,
4653 fBlockReconstructed =
true;
4657 if (requested_block_from_this_peer) {
4660 std::vector<CInv> vInv(1);
4666 fRevertToHeaderProcessing =
true;
4671 if (fProcessBLOCKTXN) {
4674 return ProcessCompactBlockTxns(pfrom, peer, txn);
4677 if (fRevertToHeaderProcessing) {
4683 return ProcessHeadersMessage(pfrom, peer, {cmpctblock.
header},
true);
4686 if (fBlockReconstructed) {
4691 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4709 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4726 return ProcessCompactBlockTxns(pfrom, peer, resp);
4737 std::vector<CBlockHeader> headers;
4741 if (nCount > m_opts.max_headers_result) {
4742 Misbehaving(peer,
strprintf(
"headers message size = %u", nCount));
4745 headers.resize(nCount);
4746 for (
unsigned int n = 0; n < nCount; n++) {
4747 vRecv >> headers[n];
4751 ProcessHeadersMessage(pfrom, peer, std::move(headers),
false);
4755 if (m_headers_presync_should_signal.exchange(
false)) {
4756 HeadersPresyncStats stats;
4758 LOCK(m_headers_presync_mutex);
4759 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4760 if (it != m_headers_presync_stats.end()) stats = it->second;
4778 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4789 Misbehaving(peer,
"mutated block");
4794 bool forceProcessing =
false;
4795 const uint256 hash(pblock->GetHash());
4796 bool min_pow_checked =
false;
4801 forceProcessing = IsBlockRequested(hash);
4802 RemoveBlockRequest(hash, pfrom.
GetId());
4806 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4810 min_pow_checked =
true;
4813 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4830 Assume(SetupAddressRelay(pfrom, peer));
4834 if (peer.m_getaddr_recvd) {
4838 peer.m_getaddr_recvd =
true;
4840 peer.m_addrs_to_send.clear();
4841 std::vector<CAddress> vAddr;
4847 for (
const CAddress &addr : vAddr) {
4848 PushAddress(peer, addr);
4876 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4877 LOCK(tx_relay->m_tx_inventory_mutex);
4878 tx_relay->m_send_mempool =
true;
4904 const auto ping_end = time_received;
4907 bool bPingFinished =
false;
4908 std::string sProblem;
4910 if (nAvail >=
sizeof(
nonce)) {
4914 if (peer.m_ping_nonce_sent != 0) {
4915 if (
nonce == peer.m_ping_nonce_sent) {
4917 bPingFinished =
true;
4918 const auto ping_time = ping_end - peer.m_ping_start.load();
4919 if (ping_time.count() >= 0) {
4930 sProblem =
"Timing mishap";
4934 sProblem =
"Nonce mismatch";
4937 bPingFinished =
true;
4938 sProblem =
"Nonce zero";
4942 sProblem =
"Unsolicited pong without ping";
4946 bPingFinished =
true;
4947 sProblem =
"Short payload";
4950 if (!(sProblem.empty())) {
4954 peer.m_ping_nonce_sent,
4958 if (bPingFinished) {
4959 peer.m_ping_nonce_sent = 0;
4976 Misbehaving(peer,
"too-large bloom filter");
4977 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4979 LOCK(tx_relay->m_bloom_filter_mutex);
4980 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4981 tx_relay->m_relay_txs =
true;
4995 std::vector<unsigned char> vData;
5003 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5004 LOCK(tx_relay->m_bloom_filter_mutex);
5005 if (tx_relay->m_bloom_filter) {
5006 tx_relay->m_bloom_filter->insert(vData);
5012 Misbehaving(peer,
"bad filteradd message");
5023 auto tx_relay = peer.GetTxRelay();
5024 if (!tx_relay)
return;
5027 LOCK(tx_relay->m_bloom_filter_mutex);
5028 tx_relay->m_bloom_filter =
nullptr;
5029 tx_relay->m_relay_txs =
true;
5038 vRecv >> newFeeFilter;
5040 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5041 tx_relay->m_fee_filter_received = newFeeFilter;
5049 ProcessGetCFilters(pfrom, peer, vRecv);
5054 ProcessGetCFHeaders(pfrom, peer, vRecv);
5059 ProcessGetCFCheckPt(pfrom, peer, vRecv);
5064 std::vector<CInv> vInv;
5066 std::vector<GenTxid> tx_invs;
5068 for (
CInv &inv : vInv) {
5074 LOCK(m_tx_download_mutex);
5075 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5084bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5087 LOCK(peer.m_misbehavior_mutex);
5090 if (!peer.m_should_discourage)
return false;
5092 peer.m_should_discourage =
false;
5097 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5103 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5123bool PeerManagerImpl::ProcessMessages(
CNode&
node, std::atomic<bool>& interruptMsgProc)
5128 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5129 if (maybe_peer ==
nullptr)
return false;
5130 Peer& peer{*maybe_peer};
5134 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent)
return false;
5137 LOCK(peer.m_getdata_requests_mutex);
5138 if (!peer.m_getdata_requests.empty()) {
5139 ProcessGetData(
node, peer, interruptMsgProc);
5143 const bool processed_orphan = ProcessOrphanTx(peer);
5145 if (
node.fDisconnect)
5148 if (processed_orphan)
return true;
5153 LOCK(peer.m_getdata_requests_mutex);
5154 if (!peer.m_getdata_requests.empty())
return true;
5158 if (
node.fPauseSend)
return false;
5160 auto poll_result{
node.PollMessage()};
5167 bool fMoreWork = poll_result->second;
5171 node.m_addr_name.c_str(),
5172 node.ConnectionTypeAsString().c_str(),
5178 if (m_opts.capture_messages) {
5183 ProcessMessage(peer,
node,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5184 if (interruptMsgProc)
return false;
5186 LOCK(peer.m_getdata_requests_mutex);
5187 if (!peer.m_getdata_requests.empty()) fMoreWork =
true;
5194 LOCK(m_tx_download_mutex);
5195 if (m_txdownloadman.HaveMoreWork(peer.m_id)) fMoreWork =
true;
5196 }
catch (
const std::exception& e) {
5205void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5218 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5220 if (state.m_chain_sync.m_timeout != 0
s) {
5221 state.m_chain_sync.m_timeout = 0
s;
5222 state.m_chain_sync.m_work_header =
nullptr;
5223 state.m_chain_sync.m_sent_getheaders =
false;
5225 }
else if (state.m_chain_sync.m_timeout == 0
s || (state.m_chain_sync.m_work_header !=
nullptr && state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= state.m_chain_sync.m_work_header->nChainWork)) {
5233 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5234 state.m_chain_sync.m_sent_getheaders =
false;
5235 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5239 if (state.m_chain_sync.m_sent_getheaders) {
5241 LogInfo(
"Outbound peer has old chain, best known block = %s, %s", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg());
5244 assert(state.m_chain_sync.m_work_header);
5249 MaybeSendGetHeaders(pto,
5250 GetLocator(state.m_chain_sync.m_work_header->pprev),
5252 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());
5253 state.m_chain_sync.m_sent_getheaders =
true;
5265void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5274 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5278 if (pnode->
GetId() > youngest_peer.first) {
5279 next_youngest_peer = youngest_peer;
5280 youngest_peer.first = pnode->GetId();
5281 youngest_peer.second = pnode->m_last_block_time;
5284 NodeId to_disconnect = youngest_peer.first;
5285 if (youngest_peer.second > next_youngest_peer.second) {
5288 to_disconnect = next_youngest_peer.first;
5297 CNodeState *node_state =
State(pnode->
GetId());
5298 if (node_state ==
nullptr ||
5301 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5305 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5321 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5324 AssertLockHeld(::cs_main);
5328 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5329 CNodeState *state = State(pnode->GetId());
5330 if (state == nullptr) return;
5332 if (state->m_chain_sync.m_protect) return;
5335 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5336 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5337 worst_peer = pnode->GetId();
5338 oldest_block_announcement = state->m_last_block_announcement;
5341 if (worst_peer != -1) {
5352 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5356 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5373void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5377 auto now{GetTime<std::chrono::seconds>()};
5379 EvictExtraOutboundPeers(now);
5381 if (now > m_stale_tip_check_time) {
5385 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5394 if (!m_initial_sync_finished && CanDirectFetch()) {
5396 m_initial_sync_finished =
true;
5400void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5403 peer.m_ping_nonce_sent &&
5413 bool pingSend =
false;
5415 if (peer.m_ping_queued) {
5420 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5429 }
while (
nonce == 0);
5430 peer.m_ping_queued =
false;
5431 peer.m_ping_start = now;
5433 peer.m_ping_nonce_sent =
nonce;
5437 peer.m_ping_nonce_sent = 0;
5443void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5446 if (!peer.m_addr_relay_enabled)
return;
5448 LOCK(peer.m_addr_send_times_mutex);
5451 peer.m_next_local_addr_send < current_time) {
5458 if (peer.m_next_local_addr_send != 0us) {
5459 peer.m_addr_known->reset();
5462 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5463 if (peer.m_next_local_addr_send == 0us) {
5467 if (IsAddrCompatible(peer, local_addr)) {
5468 std::vector<CAddress> self_announcement{local_addr};
5469 if (peer.m_wants_addrv2) {
5477 PushAddress(peer, local_addr);
5484 if (current_time <= peer.m_next_addr_send)
return;
5497 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5498 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5501 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5502 peer.m_addrs_to_send.end());
5505 if (peer.m_addrs_to_send.empty())
return;
5507 if (peer.m_wants_addrv2) {
5512 peer.m_addrs_to_send.clear();
5515 if (peer.m_addrs_to_send.capacity() > 40) {
5516 peer.m_addrs_to_send.shrink_to_fit();
5520void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5528 CNodeState &state = *
State(
node.GetId());
5529 if (state.pindexBestKnownBlock !=
nullptr &&
5536 peer.m_sent_sendheaders =
true;
5541void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5543 if (m_opts.ignore_incoming_txs)
return;
5559 if (peer.m_fee_filter_sent == MAX_FILTER) {
5562 peer.m_next_send_feefilter = 0us;
5565 if (current_time > peer.m_next_send_feefilter) {
5566 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5569 if (filterToSend != peer.m_fee_filter_sent) {
5571 peer.m_fee_filter_sent = filterToSend;
5578 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5584class CompareInvMempoolOrder
5588 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5590 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5599bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5609bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5614 if (
node.IsBlockOnlyConn())
return false;
5616 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5620 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5626void PeerManagerImpl::ProcessAddrs(std::string_view msg_type,
CNode& pfrom, Peer& peer, std::vector<CAddress>&& vAddr,
const std::atomic<bool>& interruptMsgProc)
5631 if (!SetupAddressRelay(pfrom, peer)) {
5638 Misbehaving(peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
5643 std::vector<CAddress> vAddrOk;
5649 const auto time_diff{current_time - peer.m_addr_token_timestamp};
5653 peer.m_addr_token_timestamp = current_time;
5656 uint64_t num_proc = 0;
5657 uint64_t num_rate_limit = 0;
5658 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
5661 if (interruptMsgProc)
5665 if (peer.m_addr_token_bucket < 1.0) {
5671 peer.m_addr_token_bucket -= 1.0;
5680 addr.
nTime = std::chrono::time_point_cast<std::chrono::seconds>(current_time - 5 * 24h);
5682 AddAddressKnown(peer, addr);
5689 if (addr.
nTime > current_time - 10min && !peer.m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
5691 RelayAddress(pfrom.
GetId(), addr, reachable);
5695 vAddrOk.push_back(addr);
5698 peer.m_addr_processed += num_proc;
5699 peer.m_addr_rate_limited += num_rate_limit;
5700 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
5701 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
5703 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
5704 if (vAddr.size() < 1000) peer.m_getaddr_sent =
false;
5713bool PeerManagerImpl::SendMessages(
CNode&
node)
5718 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5719 if (!maybe_peer)
return false;
5720 Peer& peer{*maybe_peer};
5725 if (MaybeDiscourageAndDisconnect(
node, peer))
return true;
5728 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent) {
5729 PushNodeVersion(
node, peer);
5730 peer.m_outbound_version_message_sent =
true;
5734 if (!
node.fSuccessfullyConnected ||
node.fDisconnect)
5737 const auto current_time{GetTime<std::chrono::microseconds>()};
5742 if (
node.IsPrivateBroadcastConn()) {
5746 node.fDisconnect =
true;
5753 node.fDisconnect =
true;
5757 MaybeSendPing(
node, peer, current_time);
5760 if (
node.fDisconnect)
return true;
5762 MaybeSendAddr(
node, peer, current_time);
5764 MaybeSendSendHeaders(
node, peer);
5769 CNodeState &state = *
State(
node.GetId());
5772 if (m_chainman.m_best_header ==
nullptr) {
5779 bool sync_blocks_and_headers_from_peer =
false;
5780 if (state.fPreferredDownload) {
5781 sync_blocks_and_headers_from_peer =
true;
5782 }
else if (CanServeBlocks(peer) && !
node.IsAddrFetchConn()) {
5792 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5793 sync_blocks_and_headers_from_peer =
true;
5799 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5800 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5808 if (pindexStart->
pprev)
5809 pindexStart = pindexStart->
pprev;
5813 state.fSyncStarted =
true;
5837 LOCK(peer.m_block_inv_mutex);
5838 std::vector<CBlock> vHeaders;
5839 bool fRevertToInv = ((!peer.m_prefers_headers &&
5840 (!state.m_requested_hb_cmpctblocks || peer.m_blocks_for_headers_relay.size() > 1)) ||
5843 ProcessBlockAvailability(
node.GetId());
5845 if (!fRevertToInv) {
5846 bool fFoundStartingHeader =
false;
5850 for (
const uint256& hash : peer.m_blocks_for_headers_relay) {
5855 fRevertToInv =
true;
5858 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5870 fRevertToInv =
true;
5873 pBestIndex = pindex;
5874 if (fFoundStartingHeader) {
5877 }
else if (PeerHasHeader(&state, pindex)) {
5879 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5882 fFoundStartingHeader =
true;
5887 fRevertToInv =
true;
5892 if (!fRevertToInv && !vHeaders.empty()) {
5893 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5897 vHeaders.front().GetHash().ToString(),
node.GetId());
5899 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5901 LOCK(m_most_recent_block_mutex);
5902 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5906 if (cached_cmpctblock_msg.has_value()) {
5907 PushMessage(
node, std::move(cached_cmpctblock_msg.value()));
5915 state.pindexBestHeaderSent = pBestIndex;
5916 }
else if (peer.m_prefers_headers) {
5917 if (vHeaders.size() > 1) {
5920 vHeaders.front().GetHash().ToString(),
5921 vHeaders.back().GetHash().ToString(),
node.GetId());
5924 vHeaders.front().GetHash().ToString(),
node.GetId());
5927 state.pindexBestHeaderSent = pBestIndex;
5929 fRevertToInv =
true;
5935 if (!peer.m_blocks_for_headers_relay.empty()) {
5936 const uint256& hashToAnnounce = peer.m_blocks_for_headers_relay.back();
5949 if (!PeerHasHeader(&state, pindex)) {
5950 peer.m_blocks_for_inv_relay.push_back(hashToAnnounce);
5956 peer.m_blocks_for_headers_relay.clear();
5962 std::vector<CInv> vInv;
5964 LOCK(peer.m_block_inv_mutex);
5968 for (
const uint256& hash : peer.m_blocks_for_inv_relay) {
5975 peer.m_blocks_for_inv_relay.clear();
5978 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5979 LOCK(tx_relay->m_tx_inventory_mutex);
5982 if (tx_relay->m_next_inv_send_time < current_time) {
5983 fSendTrickle =
true;
5984 if (
node.IsInboundConn()) {
5993 LOCK(tx_relay->m_bloom_filter_mutex);
5994 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5998 if (fSendTrickle && tx_relay->m_send_mempool) {
5999 auto vtxinfo = m_mempool.
infoAll();
6000 tx_relay->m_send_mempool =
false;
6001 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6003 LOCK(tx_relay->m_bloom_filter_mutex);
6005 for (
const auto& txinfo : vtxinfo) {
6006 const Txid& txid{txinfo.tx->GetHash()};
6007 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
6008 const auto inv = peer.m_wtxid_relay ?
6011 tx_relay->m_tx_inventory_to_send.erase(wtxid);
6014 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6017 if (tx_relay->m_bloom_filter) {
6018 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6020 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6021 vInv.push_back(inv);
6032 std::vector<std::set<Wtxid>::iterator> vInvTx;
6033 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
6034 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
6035 vInvTx.push_back(it);
6037 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6040 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
6041 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6044 unsigned int nRelayedTransactions = 0;
6045 LOCK(tx_relay->m_bloom_filter_mutex);
6048 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
6050 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6051 std::set<Wtxid>::iterator it = vInvTx.back();
6055 tx_relay->m_tx_inventory_to_send.erase(it);
6057 auto txinfo = m_mempool.
info(wtxid);
6064 const auto inv = peer.m_wtxid_relay ?
6066 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
6068 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
6072 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6075 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6077 vInv.push_back(inv);
6078 nRelayedTransactions++;
6083 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6088 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6095 auto stalling_timeout = m_block_stalling_timeout.load();
6096 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6100 LogInfo(
"Peer is stalling block download, %s",
node.DisconnectMsg());
6101 node.fDisconnect =
true;
6105 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6115 if (state.vBlocksInFlight.size() > 0) {
6116 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6117 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6119 LogInfo(
"Timeout downloading block %s, %s", queuedBlock.pindex->GetBlockHash().ToString(),
node.DisconnectMsg());
6120 node.fDisconnect =
true;
6125 if (state.fSyncStarted && peer.m_headers_sync_timeout < std::chrono::microseconds::max()) {
6127 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6128 if (current_time > peer.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6135 LogInfo(
"Timeout downloading headers, %s",
node.DisconnectMsg());
6136 node.fDisconnect =
true;
6139 LogInfo(
"Timeout downloading headers from noban peer, not %s",
node.DisconnectMsg());
6145 state.fSyncStarted =
false;
6147 peer.m_headers_sync_timeout = 0us;
6153 peer.m_headers_sync_timeout = std::chrono::microseconds::max();
6159 ConsiderEviction(
node, peer, GetTime<std::chrono::seconds>());
6164 std::vector<CInv> vGetData;
6166 std::vector<const CBlockIndex*> vToDownload;
6168 auto get_inflight_budget = [&state]() {
6175 FindNextBlocksToDownload(peer, get_inflight_budget(), vToDownload, staller);
6176 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
6177 if (historical_blocks && !IsLimitedPeer(peer)) {
6181 TryDownloadingHistoricalBlocks(
6183 get_inflight_budget(),
6184 vToDownload, from_tip, historical_blocks->second);
6187 uint32_t nFetchFlags = GetFetchFlags(peer);
6189 BlockRequested(
node.GetId(), *pindex);
6193 if (state.vBlocksInFlight.empty() && staller != -1) {
6194 if (
State(staller)->m_stalling_since == 0us) {
6195 State(staller)->m_stalling_since = current_time;
6205 LOCK(m_tx_download_mutex);
6206 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(
node.GetId(), current_time)) {
6215 if (!vGetData.empty())
6218 MaybeSendFeefilter(
node, peer, current_time);
static 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)
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.
static 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_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous.
@ 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)
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< CTransactionRef > txn
std::vector< uint16_t > indexes
A CService with information about it as peer.
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
The block chain is a tree shaped structure starting with the genesis block at the root,...
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
unsigned int nTx
Number of transactions in this block.
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(
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
An in-memory indexed chain of blocks.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
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...
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::microseconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetTryNewOutboundPeer() const
class CConnman::PrivateBroadcast m_private_broadcast
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)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
bool DisconnectNode(std::string_view node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return randomly selected addresses.
bool CheckIncomingNonce(uint64_t nonce)
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
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.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
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
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
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
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.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
std::atomic_bool fPauseSend
std::string DisconnectMsg() const
Helper function to log disconnects.
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 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....
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....
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
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.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
General SipHash-2-4 implementation.
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
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 ...
bool CompareMiningScoreWithTopology(const Wtxid &hasha, const Wtxid &hashb) const
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
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
TxMempoolInfo info(const T &id) 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.
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void BlockChecked(const std::shared_ptr< const CBlock > &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void ActiveTipChange(const CBlockIndex &new_tip, bool is_ibd)
Notifies listeners any time the block chain tip changes, synchronously.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected Provides the block that was disconnected.
virtual void BlockConnected(const kernel::ChainstateRole &role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
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
Alternatives to CurrentChainstate() used by older code to query latest chainstate information without...
SnapshotCompletionResult MaybeValidateSnapshot(Chainstate &validated_cs, Chainstate &unvalidated_cs) EXCLUSIVE_LOCKS_REQUIRED(Chainstate & CurrentChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Try to validate an assumeutxo snapshot by using a validated historical chainstate targeted at the sna...
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
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Double ended buffer combining vector and stream-like interfaces.
void ignore(size_t num_ignore)
uint64_t rand64() noexcept
Generate a random 64-bit integer.
const uint256 & ToUint256() const LIFETIMEBOUND
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual bool ProcessMessages(CNode &node, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
virtual bool SendMessages(CNode &node) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
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)
virtual util::Expected< void, std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
virtual std::vector< node::TxOrphanage::OrphanInfo > GetOrphanTransactions()=0
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
virtual void UnitTestMisbehaving(NodeId peer_id)=0
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests....
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
Store a list of transactions to be broadcast privately.
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...
std::vector< TxBroadcastInfo > GetBroadcastInfo() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get stats about all transactions currently being privately broadcast.
bool HavePendingTransactions() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if there are transactions that need to be broadcast.
bool DidNodeConfirmReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if the node has confirmed reception of the transaction.
std::optional< size_t > Remove(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Forget a transaction.
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.
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().
bool Add(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a transaction to the storage.
std::vector< CTransactionRef > GetStale() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transactions that have not been broadcast recently.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
std::string GetDebugMessage() const
std::string ToString() const
256-bit unsigned big integer.
constexpr bool IsNull() const
std::string ToString() const
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
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.
bool IsPruneMode() const
Whether running in -prune mode.
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
Manages warning messages within a node.
std::string ToString() const
const uint256 & ToUint256() const LIFETIMEBOUND
The util::Expected class provides a standard way for low-level functions to return either error value...
The util::Unexpected class represents an unexpected value stored in util::Expected.
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
static size_t RecursiveDynamicUsage(const CScript &script)
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.
is a home for simple enum and struct type definitions that can be used internally by functions in the...
#define LogDebug(category,...)
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
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 * 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...
static 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...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static 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 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...
TRACEPOINT_SEMAPHORE(net, inbound_message)
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 uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
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 size_t NUM_PRIVATE_BROADCAST_PER_TX
For private broadcast, send a transaction to this many 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 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 unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static 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 unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static 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.
const 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
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" message type for wtxid-based relay starts with this version
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" message type and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#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.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds 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
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
@ DIFFERENT_WITNESS
Valid, transaction was already in the mempool.
@ INVALID
Fully validated, valid.
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
Validation result for package mempool acceptance.
PackageValidationState m_state
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
std::chrono::seconds median_outbound_time_offset
Information about chainstate that notifications are sent from.
bool historical
Whether this is a historical chainstate downloading old blocks to validate an assumeutxo snapshot,...
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)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
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,...)
consteval auto _(util::TranslatedLiteral str)
ReconciliationRegisterResult
static 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 int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
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.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...
@ UNVALIDATED
Blocks after an assumeutxo snapshot have been validated but the snapshot itself has not been validate...