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,
_] : snapshot) {
1870 if (tx->GetHash().ToUint256() !=
id && tx->GetWitnessHash().ToUint256() !=
id)
continue;
1871 if (
const auto peer_acks{m_tx_for_private_broadcast.
Remove(tx)}) {
1872 removed_txs.push_back(tx);
1883void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1885 if (m_opts.max_extra_txs <= 0)
1887 if (!vExtraTxnForCompact.size())
1888 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1889 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1890 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1893void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1895 LOCK(peer.m_misbehavior_mutex);
1897 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1898 peer.m_should_discourage =
true;
1907 bool via_compact_block,
const std::string& message)
1909 PeerRef peer{GetPeerRef(nodeid)};
1920 if (!via_compact_block) {
1921 if (peer) Misbehaving(*peer, message);
1929 if (peer && !via_compact_block && !peer->m_is_inbound) {
1930 if (peer) Misbehaving(*peer, message);
1937 if (peer) Misbehaving(*peer, message);
1941 if (peer) Misbehaving(*peer, message);
1946 if (message !=
"") {
1951bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex& block_index)
1965 PeerRef peer = GetPeerRef(peer_id);
1974 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1977 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
2000 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
2006 : m_rng{opts.deterministic_rng},
2008 m_chainparams(chainman.GetParams()),
2012 m_chainman(chainman),
2014 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
2015 m_warnings{warnings},
2020 if (opts.reconcile_txs) {
2025void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2036 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2038 if (m_opts.private_broadcast) {
2039 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2043void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2051 LOCK(m_tx_download_mutex);
2055 m_txdownloadman.ActiveTipChange();
2065void PeerManagerImpl::BlockConnected(
2067 const std::shared_ptr<const CBlock>& pblock,
2072 m_last_tip_update = GetTime<std::chrono::seconds>();
2075 auto stalling_timeout = m_block_stalling_timeout.load();
2079 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2088 LOCK(m_tx_download_mutex);
2089 m_txdownloadman.BlockConnected(pblock);
2093void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2095 LOCK(m_tx_download_mutex);
2096 m_txdownloadman.BlockDisconnected();
2103void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2105 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2109 if (pindex->
nHeight <= m_highest_fast_announce)
2111 m_highest_fast_announce = pindex->
nHeight;
2115 uint256 hashBlock(pblock->GetHash());
2116 const std::shared_future<CSerializedNetMsg> lazy_ser{
2120 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2121 for (
const auto& tx : pblock->vtx) {
2122 most_recent_block_txs->emplace(tx->GetHash(), tx);
2123 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2126 LOCK(m_most_recent_block_mutex);
2127 m_most_recent_block_hash = hashBlock;
2128 m_most_recent_block = pblock;
2129 m_most_recent_compact_block = pcmpctblock;
2130 m_most_recent_block_txs = std::move(most_recent_block_txs);
2138 ProcessBlockAvailability(pnode->
GetId());
2142 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2144 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2145 hashBlock.ToString(), pnode->
GetId());
2148 PushMessage(*pnode, ser_cmpctblock.Copy());
2149 state.pindexBestHeaderSent = pindex;
2158void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2160 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2163 if (fInitialDownload)
return;
2166 std::vector<uint256> vHashes;
2168 while (pindexToAnnounce != pindexFork) {
2170 pindexToAnnounce = pindexToAnnounce->
pprev;
2180 for (
auto& it : m_peer_map) {
2181 Peer& peer = *it.second;
2182 LOCK(peer.m_block_inv_mutex);
2183 for (
const uint256& hash : vHashes | std::views::reverse) {
2184 peer.m_blocks_for_headers_relay.push_back(hash);
2196void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2200 const uint256 hash(block->GetHash());
2201 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2206 it != mapBlockSource.end() &&
2207 State(it->second.first)) {
2208 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2218 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2219 if (it != mapBlockSource.end()) {
2220 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2223 if (it != mapBlockSource.end())
2224 mapBlockSource.erase(it);
2232bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2237void PeerManagerImpl::SendPings()
2240 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2243void PeerManagerImpl::InitiateTxBroadcastToAll(
const Txid& txid,
const Wtxid& wtxid)
2246 for(
auto& it : m_peer_map) {
2247 Peer& peer = *it.second;
2248 auto tx_relay = peer.GetTxRelay();
2249 if (!tx_relay)
continue;
2251 LOCK(tx_relay->m_tx_inventory_mutex);
2257 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2260 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2261 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2266void PeerManagerImpl::InitiateTxBroadcastPrivate(
const CTransactionRef& tx)
2268 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2269 if (m_tx_for_private_broadcast.
Add(tx)) {
2277void PeerManagerImpl::RelayAddress(
NodeId originator,
2293 const auto current_time{GetTime<std::chrono::seconds>()};
2301 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2303 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2304 assert(nRelayNodes <= best.size());
2308 for (
auto& [
id, peer] : m_peer_map) {
2309 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2311 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2312 if (hashKey > best[i].first) {
2313 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2314 best[i] = std::make_pair(hashKey, peer.get());
2321 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2322 PushAddress(*best[i].second, addr);
2326void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2328 std::shared_ptr<const CBlock> a_recent_block;
2329 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2331 LOCK(m_most_recent_block_mutex);
2332 a_recent_block = m_most_recent_block;
2333 a_recent_compact_block = m_most_recent_compact_block;
2336 bool need_activate_chain =
false;
2348 need_activate_chain =
true;
2352 if (need_activate_chain) {
2354 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2361 bool can_direct_fetch{
false};
2369 if (!BlockRequestAllowed(*pindex)) {
2370 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2397 can_direct_fetch = CanDirectFetch();
2401 std::shared_ptr<const CBlock> pblock;
2402 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2403 pblock = a_recent_block;
2421 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2431 pblock = pblockRead;
2439 bool sendMerkleBlock =
false;
2441 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2442 LOCK(tx_relay->m_bloom_filter_mutex);
2443 if (tx_relay->m_bloom_filter) {
2444 sendMerkleBlock =
true;
2445 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2448 if (sendMerkleBlock) {
2456 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2467 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2480 LOCK(peer.m_block_inv_mutex);
2482 if (inv.
hash == peer.m_continuation_block) {
2486 std::vector<CInv> vInv;
2487 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2489 peer.m_continuation_block.SetNull();
2497 auto txinfo{std::visit(
2498 [&](
const auto&
id) {
2499 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2503 return std::move(txinfo.tx);
2508 LOCK(m_most_recent_block_mutex);
2509 if (m_most_recent_block_txs !=
nullptr) {
2510 auto it = m_most_recent_block_txs->find(gtxid);
2511 if (it != m_most_recent_block_txs->end())
return it->second;
2518void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2522 auto tx_relay = peer.GetTxRelay();
2524 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2525 std::vector<CInv> vNotFound;
2530 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2531 if (interruptMsgProc)
return;
2536 const CInv &inv = *it++;
2538 if (tx_relay ==
nullptr) {
2544 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2547 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2550 vNotFound.push_back(inv);
2556 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2557 const CInv &inv = *it++;
2559 ProcessGetBlockData(pfrom, peer, inv);
2568 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2570 if (!vNotFound.empty()) {
2589uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2591 uint32_t nFetchFlags = 0;
2592 if (CanServeWitnesses(peer)) {
2601 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2603 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2610 uint32_t tx_requested_size{0};
2611 for (
const auto& tx : resp.txn) tx_requested_size += tx->ComputeTotalSize();
2617bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2621 Misbehaving(peer,
"header with invalid proof of work");
2626 if (!CheckHeadersAreContinuous(headers)) {
2627 Misbehaving(peer,
"non-continuous headers sequence");
2652void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2653 const std::vector<CBlockHeader>& headers)
2657 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2658 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2660 headers[0].hashPrevBlock.ToString(),
2661 best_header->nHeight,
2671bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2675 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2678 hashLastBlock = header.GetHash();
2683bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2685 if (peer.m_headers_sync) {
2686 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2688 if (result.success) peer.m_last_getheaders_timestamp = {};
2689 if (result.request_more) {
2690 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2692 Assume(!locator.vHave.empty());
2695 if (!locator.vHave.empty()) {
2698 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2701 locator.vHave.front().ToString(), pfrom.
GetId());
2706 peer.m_headers_sync.reset(
nullptr);
2711 LOCK(m_headers_presync_mutex);
2712 m_headers_presync_stats.erase(pfrom.
GetId());
2715 HeadersPresyncStats stats;
2716 stats.first = peer.m_headers_sync->GetPresyncWork();
2718 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2719 peer.m_headers_sync->GetPresyncTime()};
2723 LOCK(m_headers_presync_mutex);
2724 m_headers_presync_stats[pfrom.
GetId()] = stats;
2725 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2726 bool best_updated =
false;
2727 if (best_it == m_headers_presync_stats.end()) {
2731 const HeadersPresyncStats* stat_best{
nullptr};
2732 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2733 if (!stat_best || stat > *stat_best) {
2738 m_headers_presync_bestpeer = peer_best;
2739 best_updated = (peer_best == pfrom.
GetId());
2740 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2742 m_headers_presync_bestpeer = pfrom.
GetId();
2743 best_updated =
true;
2745 if (best_updated && stats.second.has_value()) {
2747 m_headers_presync_should_signal =
true;
2751 if (result.success) {
2754 headers.swap(result.pow_validated_headers);
2757 return result.success;
2765bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
2772 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2776 if (total_work < minimum_chain_work) {
2780 if (headers.size() == m_opts.max_headers_result) {
2790 LOCK(peer.m_headers_sync_mutex);
2792 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2797 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2811bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2813 if (header ==
nullptr) {
2815 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2823bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2831 peer.m_last_getheaders_timestamp = current_time;
2842void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2845 CNodeState *nodestate =
State(pfrom.
GetId());
2848 std::vector<const CBlockIndex*> vToFetch;
2856 vToFetch.push_back(pindexWalk);
2858 pindexWalk = pindexWalk->
pprev;
2869 std::vector<CInv> vGetData;
2871 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2876 uint32_t nFetchFlags = GetFetchFlags(peer);
2878 BlockRequested(pfrom.
GetId(), *pindex);
2882 if (vGetData.size() > 1) {
2887 if (vGetData.size() > 0) {
2888 if (!m_opts.ignore_incoming_txs &&
2889 nodestate->m_provides_cmpctblocks &&
2890 vGetData.size() == 1 &&
2891 mapBlocksInFlight.size() == 1 &&
2907void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2908 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2911 CNodeState *nodestate =
State(pfrom.
GetId());
2920 nodestate->m_last_block_announcement =
GetTime();
2928 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2950 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) {
2952 nodestate->m_chain_sync.m_protect =
true;
2953 ++m_outbound_peers_with_protect_from_disconnect;
2958void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2959 std::vector<CBlockHeader>&& headers,
2960 bool via_compact_block)
2962 size_t nCount = headers.size();
2969 LOCK(peer.m_headers_sync_mutex);
2970 if (peer.m_headers_sync) {
2971 peer.m_headers_sync.reset(
nullptr);
2972 LOCK(m_headers_presync_mutex);
2973 m_headers_presync_stats.erase(pfrom.
GetId());
2977 peer.m_last_getheaders_timestamp = {};
2985 if (!CheckHeadersPoW(headers, peer)) {
3000 bool already_validated_work =
false;
3003 bool have_headers_sync =
false;
3005 LOCK(peer.m_headers_sync_mutex);
3007 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3019 if (headers.empty()) {
3023 have_headers_sync = !!peer.m_headers_sync;
3028 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3030 if (!headers_connect_blockindex) {
3034 HandleUnconnectingHeaders(pfrom, peer, headers);
3041 peer.m_last_getheaders_timestamp = {};
3051 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3058 already_validated_work =
true;
3064 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3065 *chain_start_header, headers)) {
3077 bool received_new_header{last_received_header ==
nullptr};
3083 state, &pindexLast)};
3089 "If this happens with all peers, consider database corruption (that -reindex may fix) "
3090 "or a potential consensus incompatibility.",
3093 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3099 if (processed && received_new_header) {
3100 LogBlockHeader(*pindexLast, pfrom,
false);
3104 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3106 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3111 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3114 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3120 bool first_time_failure)
3126 PeerRef peer{GetPeerRef(nodeid)};
3129 ptx->GetHash().ToString(),
3130 ptx->GetWitnessHash().ToString(),
3134 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3137 AddToCompactExtraTransactions(ptx);
3139 for (
const Txid& parent_txid : unique_parents) {
3140 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3143 return package_to_validate;
3146void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3152 m_txdownloadman.MempoolAcceptedTx(tx);
3156 tx->GetHash().ToString(),
3157 tx->GetWitnessHash().ToString(),
3160 InitiateTxBroadcastToAll(tx->GetHash(), tx->GetWitnessHash());
3163 AddToCompactExtraTransactions(removedTx);
3173 const auto&
package = package_to_validate.m_txns;
3174 const auto& senders = package_to_validate.
m_senders;
3177 m_txdownloadman.MempoolRejectedPackage(package);
3180 if (!
Assume(package.size() == 2))
return;
3184 auto package_iter = package.rbegin();
3185 auto senders_iter = senders.rbegin();
3186 while (package_iter != package.rend()) {
3187 const auto& tx = *package_iter;
3188 const NodeId nodeid = *senders_iter;
3189 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3193 const auto& tx_result = it_result->second;
3194 switch (tx_result.m_result_type) {
3197 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3207 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3225bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3232 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3235 const Txid& orphanHash = porphanTx->GetHash();
3236 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3253 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3262bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3264 const uint256& stop_hash, uint32_t max_height_diff,
3268 const bool supported_filter_type =
3271 if (!supported_filter_type) {
3273 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg());
3274 node.fDisconnect =
true;
3283 if (!stop_index || !BlockRequestAllowed(*stop_index)) {
3286 node.fDisconnect =
true;
3291 uint32_t stop_height = stop_index->
nHeight;
3292 if (start_height > stop_height) {
3294 "start height %d and stop height %d, %s",
3295 start_height, stop_height,
node.DisconnectMsg());
3296 node.fDisconnect =
true;
3299 if (stop_height - start_height >= max_height_diff) {
3301 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg());
3302 node.fDisconnect =
true;
3307 if (!filter_index) {
3317 uint8_t filter_type_ser;
3318 uint32_t start_height;
3321 vRecv >> filter_type_ser >> start_height >> stop_hash;
3327 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3332 std::vector<BlockFilter> filters;
3334 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3339 for (
const auto& filter : filters) {
3346 uint8_t filter_type_ser;
3347 uint32_t start_height;
3350 vRecv >> filter_type_ser >> start_height >> stop_hash;
3356 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3362 if (start_height > 0) {
3364 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3366 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3372 std::vector<uint256> filter_hashes;
3374 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3388 uint8_t filter_type_ser;
3391 vRecv >> filter_type_ser >> stop_hash;
3397 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3398 std::numeric_limits<uint32_t>::max(),
3399 stop_index, filter_index)) {
3407 for (
int i = headers.size() - 1; i >= 0; i--) {
3412 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3426 bool new_block{
false};
3427 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3429 node.m_last_block_time = GetTime<std::chrono::seconds>();
3434 RemoveBlockRequest(block->GetHash(), std::nullopt);
3437 mapBlockSource.erase(block->GetHash());
3441void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3443 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3444 bool fBlockRead{
false};
3448 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3449 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3450 bool requested_block_from_this_peer{
false};
3453 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3455 while (range_flight.first != range_flight.second) {
3456 auto [node_id, block_it] = range_flight.first->second;
3457 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3458 requested_block_from_this_peer =
true;
3461 range_flight.first++;
3464 if (!requested_block_from_this_peer) {
3476 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3487 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3490 if (first_in_flight) {
3495 std::vector<CInv> invs;
3500 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3513 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3528void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3540 "Saw new %sheader hash=%s height=%d %s",
3541 via_compact_block ?
"cmpctblock " :
"",
3553void PeerManagerImpl::PushPrivateBroadcastTx(
CNode&
node)
3560 node.fDisconnect =
true;
3566 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3572void PeerManagerImpl::ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3573 const std::chrono::microseconds time_received,
3574 const std::atomic<bool>& interruptMsgProc)
3589 uint64_t nNonce = 1;
3592 std::string cleanSubVer;
3593 int starting_height = -1;
3596 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3611 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s",
3613 GetDesirableServiceFlags(nServices),
3626 if (!vRecv.
empty()) {
3634 if (!vRecv.
empty()) {
3635 std::string strSubVer;
3639 if (!vRecv.
empty()) {
3640 vRecv >> starting_height;
3660 PushNodeVersion(pfrom, peer);
3669 peer.m_their_services = nServices;
3673 pfrom.cleanSubVer = cleanSubVer;
3684 (fRelay || (peer.m_our_services &
NODE_BLOOM))) {
3685 auto*
const tx_relay = peer.SetTxRelay();
3687 LOCK(tx_relay->m_bloom_filter_mutex);
3688 tx_relay->m_relay_txs = fRelay;
3694 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, %s%s",
3695 cleanSubVer.empty() ?
"<no user agent>" : cleanSubVer, pfrom.
nVersion,
3697 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3715 if (greatest_common_version >= 70016) {
3730 const auto* tx_relay = peer.GetTxRelay();
3731 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3733 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3746 m_num_preferred_download_peers += state->fPreferredDownload;
3752 bool send_getaddr{
false};
3754 send_getaddr = SetupAddressRelay(pfrom, peer);
3764 peer.m_getaddr_sent =
true;
3788 peer.m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3792 m_outbound_time_offsets.Add(peer.m_time_offset);
3793 m_outbound_time_offsets.WarnIfOutOfSync();
3797 if (greatest_common_version <= 70012) {
3798 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3799 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3822 auto new_peer_msg = [&]() {
3824 return strprintf(
"New %s peer connected: transport: %s, version: %d, %s%s",
3828 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3836 LogInfo(
"%s", new_peer_msg());
3839 if (
auto tx_relay = peer.GetTxRelay()) {
3848 tx_relay->m_tx_inventory_mutex,
3849 return tx_relay->m_tx_inventory_to_send.empty() &&
3850 tx_relay->m_next_inv_send_time == 0
s));
3860 PushPrivateBroadcastTx(pfrom);
3873 if (m_txreconciliation) {
3874 if (!peer.m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3878 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3884 const CNodeState* state =
State(pfrom.
GetId());
3886 .m_preferred = state->fPreferredDownload,
3887 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3888 .m_wtxid_relay = peer.m_wtxid_relay,
3897 peer.m_prefers_headers =
true;
3902 bool sendcmpct_hb{
false};
3903 uint64_t sendcmpct_version{0};
3904 vRecv >> sendcmpct_hb >> sendcmpct_version;
3910 CNodeState* nodestate =
State(pfrom.
GetId());
3911 nodestate->m_provides_cmpctblocks =
true;
3912 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3929 if (!peer.m_wtxid_relay) {
3930 peer.m_wtxid_relay =
true;
3931 m_wtxid_relay_peers++;
3950 peer.m_wants_addrv2 =
true;
3958 if (!m_txreconciliation) {
3959 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3970 if (RejectIncomingTxs(pfrom)) {
3979 const auto* tx_relay = peer.GetTxRelay();
3980 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3986 uint32_t peer_txreconcl_version;
3987 uint64_t remote_salt;
3988 vRecv >> peer_txreconcl_version >> remote_salt;
3991 peer_txreconcl_version, remote_salt);
4023 const auto ser_params{
4031 std::vector<CAddress> vAddr;
4032 vRecv >> ser_params(vAddr);
4033 ProcessAddrs(msg_type, pfrom, peer, std::move(vAddr), interruptMsgProc);
4038 std::vector<CInv> vInv;
4042 Misbehaving(peer,
strprintf(
"inv message size = %u", vInv.size()));
4046 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4050 const auto current_time{GetTime<std::chrono::microseconds>()};
4053 for (
CInv& inv : vInv) {
4054 if (interruptMsgProc)
return;
4059 if (peer.m_wtxid_relay) {
4066 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4069 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4077 best_block = &inv.
hash;
4080 if (reject_tx_invs) {
4086 AddKnownTx(peer, inv.
hash);
4089 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4097 if (best_block !=
nullptr) {
4109 if (state.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4110 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer)) {
4112 m_chainman.m_best_header->nHeight, best_block->ToString(),
4115 if (!state.fSyncStarted) {
4116 peer.m_inv_triggered_getheaders_before_sync =
true;
4120 m_last_block_inv_triggering_headers_sync = *best_block;
4129 std::vector<CInv> vInv;
4133 Misbehaving(peer,
strprintf(
"getdata message size = %u", vInv.size()));
4139 if (vInv.size() > 0) {
4144 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4145 if (!pushed_tx_opt) {
4156 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4160 peer.m_ping_queued =
true;
4161 MaybeSendPing(pfrom, peer, GetTime<std::chrono::microseconds>());
4171 LOCK(peer.m_getdata_requests_mutex);
4172 peer.m_getdata_requests.insert(peer.m_getdata_requests.end(), vInv.begin(), vInv.end());
4173 ProcessGetData(pfrom, peer, interruptMsgProc);
4182 vRecv >> locator >> hashStop;
4198 std::shared_ptr<const CBlock> a_recent_block;
4200 LOCK(m_most_recent_block_mutex);
4201 a_recent_block = m_most_recent_block;
4204 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4219 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4234 if (--nLimit <= 0) {
4238 WITH_LOCK(peer.m_block_inv_mutex, {peer.m_continuation_block = pindex->GetBlockHash();});
4250 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4254 std::shared_ptr<const CBlock> recent_block;
4256 LOCK(m_most_recent_block_mutex);
4257 if (m_most_recent_block_hash == req.
blockhash)
4258 recent_block = m_most_recent_block;
4262 SendBlockTransactions(pfrom, peer, *recent_block, req);
4281 if (!block_pos.IsNull()) {
4288 SendBlockTransactions(pfrom, peer, block, req);
4301 WITH_LOCK(peer.m_getdata_requests_mutex, peer.m_getdata_requests.push_back(inv));
4309 vRecv >> locator >> hashStop;
4327 if (m_chainman.
ActiveTip() ==
nullptr ||
4329 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4336 CNodeState *nodestate =
State(pfrom.
GetId());
4345 if (!BlockRequestAllowed(*pindex)) {
4346 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4359 std::vector<CBlock> vHeaders;
4360 int nLimit = m_opts.max_headers_result;
4362 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4365 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4380 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4386 if (RejectIncomingTxs(pfrom)) {
4400 const Txid& txid = ptx->GetHash();
4401 const Wtxid& wtxid = ptx->GetWitnessHash();
4404 AddKnownTx(peer, hash);
4406 if (
const auto num_broadcasted{m_tx_for_private_broadcast.
Remove(ptx)}) {
4408 "network from %s; stopping private broadcast attempts",
4419 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4420 if (!should_validate) {
4425 if (!m_mempool.
exists(txid)) {
4426 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4429 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4431 InitiateTxBroadcastToAll(txid, wtxid);
4435 if (package_to_validate) {
4438 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4439 ProcessPackageResult(package_to_validate.value(), package_result);
4445 Assume(!package_to_validate.has_value());
4455 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4458 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4459 ProcessPackageResult(package_to_validate.value(), package_result);
4475 vRecv >> cmpctblock;
4477 bool received_new_header =
false;
4487 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer);
4497 received_new_header =
true;
4505 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4512 if (received_new_header) {
4513 LogBlockHeader(*pindex, pfrom,
true);
4516 bool fProcessBLOCKTXN =
false;
4520 bool fRevertToHeaderProcessing =
false;
4524 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4525 bool fBlockReconstructed =
false;
4531 CNodeState *nodestate =
State(pfrom.
GetId());
4536 nodestate->m_last_block_announcement =
GetTime();
4542 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4543 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4544 bool requested_block_from_this_peer{
false};
4547 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4549 while (range_flight.first != range_flight.second) {
4550 if (range_flight.first->second.first == pfrom.
GetId()) {
4551 requested_block_from_this_peer =
true;
4554 range_flight.first++;
4559 if (requested_block_from_this_peer) {
4562 std::vector<CInv> vInv(1);
4570 if (!already_in_flight && !CanDirectFetch()) {
4578 requested_block_from_this_peer) {
4579 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4580 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4581 if (!(*queuedBlockIt)->partialBlock)
4594 Misbehaving(peer,
"invalid compact block");
4597 if (first_in_flight) {
4599 std::vector<CInv> vInv(1);
4610 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4615 fProcessBLOCKTXN =
true;
4616 }
else if (first_in_flight) {
4623 IsBlockRequestedFromOutbound(blockhash) ||
4642 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4647 std::vector<CTransactionRef> dummy;
4649 status = tempBlock.FillBlock(*pblock, dummy,
4652 fBlockReconstructed =
true;
4656 if (requested_block_from_this_peer) {
4659 std::vector<CInv> vInv(1);
4665 fRevertToHeaderProcessing =
true;
4670 if (fProcessBLOCKTXN) {
4673 return ProcessCompactBlockTxns(pfrom, peer, txn);
4676 if (fRevertToHeaderProcessing) {
4682 return ProcessHeadersMessage(pfrom, peer, {cmpctblock.
header},
true);
4685 if (fBlockReconstructed) {
4690 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4708 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4725 return ProcessCompactBlockTxns(pfrom, peer, resp);
4736 std::vector<CBlockHeader> headers;
4740 if (nCount > m_opts.max_headers_result) {
4741 Misbehaving(peer,
strprintf(
"headers message size = %u", nCount));
4744 headers.resize(nCount);
4745 for (
unsigned int n = 0; n < nCount; n++) {
4746 vRecv >> headers[n];
4750 ProcessHeadersMessage(pfrom, peer, std::move(headers),
false);
4754 if (m_headers_presync_should_signal.exchange(
false)) {
4755 HeadersPresyncStats stats;
4757 LOCK(m_headers_presync_mutex);
4758 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4759 if (it != m_headers_presync_stats.end()) stats = it->second;
4777 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4788 Misbehaving(peer,
"mutated block");
4793 bool forceProcessing =
false;
4794 const uint256 hash(pblock->GetHash());
4795 bool min_pow_checked =
false;
4800 forceProcessing = IsBlockRequested(hash);
4801 RemoveBlockRequest(hash, pfrom.
GetId());
4805 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4809 min_pow_checked =
true;
4812 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4829 Assume(SetupAddressRelay(pfrom, peer));
4833 if (peer.m_getaddr_recvd) {
4837 peer.m_getaddr_recvd =
true;
4839 peer.m_addrs_to_send.clear();
4840 std::vector<CAddress> vAddr;
4846 for (
const CAddress &addr : vAddr) {
4847 PushAddress(peer, addr);
4875 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4876 LOCK(tx_relay->m_tx_inventory_mutex);
4877 tx_relay->m_send_mempool =
true;
4903 const auto ping_end = time_received;
4906 bool bPingFinished =
false;
4907 std::string sProblem;
4909 if (nAvail >=
sizeof(
nonce)) {
4913 if (peer.m_ping_nonce_sent != 0) {
4914 if (
nonce == peer.m_ping_nonce_sent) {
4916 bPingFinished =
true;
4917 const auto ping_time = ping_end - peer.m_ping_start.load();
4918 if (ping_time.count() >= 0) {
4929 sProblem =
"Timing mishap";
4933 sProblem =
"Nonce mismatch";
4936 bPingFinished =
true;
4937 sProblem =
"Nonce zero";
4941 sProblem =
"Unsolicited pong without ping";
4945 bPingFinished =
true;
4946 sProblem =
"Short payload";
4949 if (!(sProblem.empty())) {
4953 peer.m_ping_nonce_sent,
4957 if (bPingFinished) {
4958 peer.m_ping_nonce_sent = 0;
4975 Misbehaving(peer,
"too-large bloom filter");
4976 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4978 LOCK(tx_relay->m_bloom_filter_mutex);
4979 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4980 tx_relay->m_relay_txs =
true;
4994 std::vector<unsigned char> vData;
5002 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5003 LOCK(tx_relay->m_bloom_filter_mutex);
5004 if (tx_relay->m_bloom_filter) {
5005 tx_relay->m_bloom_filter->insert(vData);
5011 Misbehaving(peer,
"bad filteradd message");
5022 auto tx_relay = peer.GetTxRelay();
5023 if (!tx_relay)
return;
5026 LOCK(tx_relay->m_bloom_filter_mutex);
5027 tx_relay->m_bloom_filter =
nullptr;
5028 tx_relay->m_relay_txs =
true;
5037 vRecv >> newFeeFilter;
5039 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5040 tx_relay->m_fee_filter_received = newFeeFilter;
5048 ProcessGetCFilters(pfrom, peer, vRecv);
5053 ProcessGetCFHeaders(pfrom, peer, vRecv);
5058 ProcessGetCFCheckPt(pfrom, peer, vRecv);
5063 std::vector<CInv> vInv;
5065 std::vector<GenTxid> tx_invs;
5067 for (
CInv &inv : vInv) {
5073 LOCK(m_tx_download_mutex);
5074 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5083bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5086 LOCK(peer.m_misbehavior_mutex);
5089 if (!peer.m_should_discourage)
return false;
5091 peer.m_should_discourage =
false;
5096 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5102 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5122bool PeerManagerImpl::ProcessMessages(
CNode&
node, std::atomic<bool>& interruptMsgProc)
5127 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5128 if (maybe_peer ==
nullptr)
return false;
5129 Peer& peer{*maybe_peer};
5133 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent)
return false;
5136 LOCK(peer.m_getdata_requests_mutex);
5137 if (!peer.m_getdata_requests.empty()) {
5138 ProcessGetData(
node, peer, interruptMsgProc);
5142 const bool processed_orphan = ProcessOrphanTx(peer);
5144 if (
node.fDisconnect)
5147 if (processed_orphan)
return true;
5152 LOCK(peer.m_getdata_requests_mutex);
5153 if (!peer.m_getdata_requests.empty())
return true;
5157 if (
node.fPauseSend)
return false;
5159 auto poll_result{
node.PollMessage()};
5166 bool fMoreWork = poll_result->second;
5170 node.m_addr_name.c_str(),
5171 node.ConnectionTypeAsString().c_str(),
5177 if (m_opts.capture_messages) {
5182 ProcessMessage(peer,
node,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5183 if (interruptMsgProc)
return false;
5185 LOCK(peer.m_getdata_requests_mutex);
5186 if (!peer.m_getdata_requests.empty()) fMoreWork =
true;
5193 LOCK(m_tx_download_mutex);
5194 if (m_txdownloadman.HaveMoreWork(peer.m_id)) fMoreWork =
true;
5195 }
catch (
const std::exception& e) {
5204void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5217 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5219 if (state.m_chain_sync.m_timeout != 0
s) {
5220 state.m_chain_sync.m_timeout = 0
s;
5221 state.m_chain_sync.m_work_header =
nullptr;
5222 state.m_chain_sync.m_sent_getheaders =
false;
5224 }
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)) {
5232 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5233 state.m_chain_sync.m_sent_getheaders =
false;
5234 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5238 if (state.m_chain_sync.m_sent_getheaders) {
5240 LogInfo(
"Outbound peer has old chain, best known block = %s, %s", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg());
5243 assert(state.m_chain_sync.m_work_header);
5248 MaybeSendGetHeaders(pto,
5249 GetLocator(state.m_chain_sync.m_work_header->pprev),
5251 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());
5252 state.m_chain_sync.m_sent_getheaders =
true;
5264void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5273 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5277 if (pnode->
GetId() > youngest_peer.first) {
5278 next_youngest_peer = youngest_peer;
5279 youngest_peer.first = pnode->GetId();
5280 youngest_peer.second = pnode->m_last_block_time;
5283 NodeId to_disconnect = youngest_peer.first;
5284 if (youngest_peer.second > next_youngest_peer.second) {
5287 to_disconnect = next_youngest_peer.first;
5296 CNodeState *node_state =
State(pnode->
GetId());
5297 if (node_state ==
nullptr ||
5300 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5304 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5320 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5323 AssertLockHeld(::cs_main);
5327 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5328 CNodeState *state = State(pnode->GetId());
5329 if (state == nullptr) return;
5331 if (state->m_chain_sync.m_protect) return;
5334 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5335 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5336 worst_peer = pnode->GetId();
5337 oldest_block_announcement = state->m_last_block_announcement;
5340 if (worst_peer != -1) {
5351 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5355 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5372void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5376 auto now{GetTime<std::chrono::seconds>()};
5378 EvictExtraOutboundPeers(now);
5380 if (now > m_stale_tip_check_time) {
5384 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5393 if (!m_initial_sync_finished && CanDirectFetch()) {
5395 m_initial_sync_finished =
true;
5399void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5402 peer.m_ping_nonce_sent &&
5412 bool pingSend =
false;
5414 if (peer.m_ping_queued) {
5419 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5428 }
while (
nonce == 0);
5429 peer.m_ping_queued =
false;
5430 peer.m_ping_start = now;
5432 peer.m_ping_nonce_sent =
nonce;
5436 peer.m_ping_nonce_sent = 0;
5442void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5445 if (!peer.m_addr_relay_enabled)
return;
5447 LOCK(peer.m_addr_send_times_mutex);
5450 peer.m_next_local_addr_send < current_time) {
5457 if (peer.m_next_local_addr_send != 0us) {
5458 peer.m_addr_known->reset();
5461 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5462 if (peer.m_next_local_addr_send == 0us) {
5466 if (IsAddrCompatible(peer, local_addr)) {
5467 std::vector<CAddress> self_announcement{local_addr};
5468 if (peer.m_wants_addrv2) {
5476 PushAddress(peer, local_addr);
5483 if (current_time <= peer.m_next_addr_send)
return;
5496 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5497 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5500 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5501 peer.m_addrs_to_send.end());
5504 if (peer.m_addrs_to_send.empty())
return;
5506 if (peer.m_wants_addrv2) {
5511 peer.m_addrs_to_send.clear();
5514 if (peer.m_addrs_to_send.capacity() > 40) {
5515 peer.m_addrs_to_send.shrink_to_fit();
5519void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5527 CNodeState &state = *
State(
node.GetId());
5528 if (state.pindexBestKnownBlock !=
nullptr &&
5535 peer.m_sent_sendheaders =
true;
5540void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5542 if (m_opts.ignore_incoming_txs)
return;
5558 if (peer.m_fee_filter_sent == MAX_FILTER) {
5561 peer.m_next_send_feefilter = 0us;
5564 if (current_time > peer.m_next_send_feefilter) {
5565 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5568 if (filterToSend != peer.m_fee_filter_sent) {
5570 peer.m_fee_filter_sent = filterToSend;
5577 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5583class CompareInvMempoolOrder
5587 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5589 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5598bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5608bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5613 if (
node.IsBlockOnlyConn())
return false;
5615 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5619 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5625void PeerManagerImpl::ProcessAddrs(std::string_view msg_type,
CNode& pfrom, Peer& peer, std::vector<CAddress>&& vAddr,
const std::atomic<bool>& interruptMsgProc)
5630 if (!SetupAddressRelay(pfrom, peer)) {
5637 Misbehaving(peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
5642 std::vector<CAddress> vAddrOk;
5648 const auto time_diff{current_time - peer.m_addr_token_timestamp};
5652 peer.m_addr_token_timestamp = current_time;
5655 uint64_t num_proc = 0;
5656 uint64_t num_rate_limit = 0;
5657 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
5660 if (interruptMsgProc)
5664 if (peer.m_addr_token_bucket < 1.0) {
5670 peer.m_addr_token_bucket -= 1.0;
5679 addr.
nTime = std::chrono::time_point_cast<std::chrono::seconds>(current_time - 5 * 24h);
5681 AddAddressKnown(peer, addr);
5688 if (addr.
nTime > current_time - 10min && !peer.m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
5690 RelayAddress(pfrom.
GetId(), addr, reachable);
5694 vAddrOk.push_back(addr);
5697 peer.m_addr_processed += num_proc;
5698 peer.m_addr_rate_limited += num_rate_limit;
5699 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
5700 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
5702 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
5703 if (vAddr.size() < 1000) peer.m_getaddr_sent =
false;
5712bool PeerManagerImpl::SendMessages(
CNode&
node)
5717 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5718 if (!maybe_peer)
return false;
5719 Peer& peer{*maybe_peer};
5724 if (MaybeDiscourageAndDisconnect(
node, peer))
return true;
5727 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent) {
5728 PushNodeVersion(
node, peer);
5729 peer.m_outbound_version_message_sent =
true;
5733 if (!
node.fSuccessfullyConnected ||
node.fDisconnect)
5736 const auto current_time{GetTime<std::chrono::microseconds>()};
5741 if (
node.IsPrivateBroadcastConn()) {
5745 node.fDisconnect =
true;
5752 node.fDisconnect =
true;
5756 MaybeSendPing(
node, peer, current_time);
5759 if (
node.fDisconnect)
return true;
5761 MaybeSendAddr(
node, peer, current_time);
5763 MaybeSendSendHeaders(
node, peer);
5768 CNodeState &state = *
State(
node.GetId());
5771 if (m_chainman.m_best_header ==
nullptr) {
5778 bool sync_blocks_and_headers_from_peer =
false;
5779 if (state.fPreferredDownload) {
5780 sync_blocks_and_headers_from_peer =
true;
5781 }
else if (CanServeBlocks(peer) && !
node.IsAddrFetchConn()) {
5791 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5792 sync_blocks_and_headers_from_peer =
true;
5798 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5799 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5807 if (pindexStart->
pprev)
5808 pindexStart = pindexStart->
pprev;
5812 state.fSyncStarted =
true;
5836 LOCK(peer.m_block_inv_mutex);
5837 std::vector<CBlock> vHeaders;
5838 bool fRevertToInv = ((!peer.m_prefers_headers &&
5839 (!state.m_requested_hb_cmpctblocks || peer.m_blocks_for_headers_relay.size() > 1)) ||
5842 ProcessBlockAvailability(
node.GetId());
5844 if (!fRevertToInv) {
5845 bool fFoundStartingHeader =
false;
5849 for (
const uint256& hash : peer.m_blocks_for_headers_relay) {
5854 fRevertToInv =
true;
5857 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5869 fRevertToInv =
true;
5872 pBestIndex = pindex;
5873 if (fFoundStartingHeader) {
5876 }
else if (PeerHasHeader(&state, pindex)) {
5878 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5881 fFoundStartingHeader =
true;
5886 fRevertToInv =
true;
5891 if (!fRevertToInv && !vHeaders.empty()) {
5892 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5896 vHeaders.front().GetHash().ToString(),
node.GetId());
5898 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5900 LOCK(m_most_recent_block_mutex);
5901 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5905 if (cached_cmpctblock_msg.has_value()) {
5906 PushMessage(
node, std::move(cached_cmpctblock_msg.value()));
5914 state.pindexBestHeaderSent = pBestIndex;
5915 }
else if (peer.m_prefers_headers) {
5916 if (vHeaders.size() > 1) {
5919 vHeaders.front().GetHash().ToString(),
5920 vHeaders.back().GetHash().ToString(),
node.GetId());
5923 vHeaders.front().GetHash().ToString(),
node.GetId());
5926 state.pindexBestHeaderSent = pBestIndex;
5928 fRevertToInv =
true;
5934 if (!peer.m_blocks_for_headers_relay.empty()) {
5935 const uint256& hashToAnnounce = peer.m_blocks_for_headers_relay.back();
5948 if (!PeerHasHeader(&state, pindex)) {
5949 peer.m_blocks_for_inv_relay.push_back(hashToAnnounce);
5955 peer.m_blocks_for_headers_relay.clear();
5961 std::vector<CInv> vInv;
5963 LOCK(peer.m_block_inv_mutex);
5967 for (
const uint256& hash : peer.m_blocks_for_inv_relay) {
5974 peer.m_blocks_for_inv_relay.clear();
5977 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5978 LOCK(tx_relay->m_tx_inventory_mutex);
5981 if (tx_relay->m_next_inv_send_time < current_time) {
5982 fSendTrickle =
true;
5983 if (
node.IsInboundConn()) {
5992 LOCK(tx_relay->m_bloom_filter_mutex);
5993 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5997 if (fSendTrickle && tx_relay->m_send_mempool) {
5998 auto vtxinfo = m_mempool.
infoAll();
5999 tx_relay->m_send_mempool =
false;
6000 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6002 LOCK(tx_relay->m_bloom_filter_mutex);
6004 for (
const auto& txinfo : vtxinfo) {
6005 const Txid& txid{txinfo.tx->GetHash()};
6006 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
6007 const auto inv = peer.m_wtxid_relay ?
6010 tx_relay->m_tx_inventory_to_send.erase(wtxid);
6013 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6016 if (tx_relay->m_bloom_filter) {
6017 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6019 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6020 vInv.push_back(inv);
6031 std::vector<std::set<Wtxid>::iterator> vInvTx;
6032 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
6033 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
6034 vInvTx.push_back(it);
6036 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6039 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
6040 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6043 unsigned int nRelayedTransactions = 0;
6044 LOCK(tx_relay->m_bloom_filter_mutex);
6047 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
6049 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6050 std::set<Wtxid>::iterator it = vInvTx.back();
6054 tx_relay->m_tx_inventory_to_send.erase(it);
6056 auto txinfo = m_mempool.
info(wtxid);
6063 const auto inv = peer.m_wtxid_relay ?
6065 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
6067 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
6071 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6074 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6076 vInv.push_back(inv);
6077 nRelayedTransactions++;
6082 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6087 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6094 auto stalling_timeout = m_block_stalling_timeout.load();
6095 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6099 LogInfo(
"Peer is stalling block download, %s",
node.DisconnectMsg());
6100 node.fDisconnect =
true;
6104 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6114 if (state.vBlocksInFlight.size() > 0) {
6115 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6116 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6118 LogInfo(
"Timeout downloading block %s, %s", queuedBlock.pindex->GetBlockHash().ToString(),
node.DisconnectMsg());
6119 node.fDisconnect =
true;
6124 if (state.fSyncStarted && peer.m_headers_sync_timeout < std::chrono::microseconds::max()) {
6126 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6127 if (current_time > peer.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6134 LogInfo(
"Timeout downloading headers, %s",
node.DisconnectMsg());
6135 node.fDisconnect =
true;
6138 LogInfo(
"Timeout downloading headers from noban peer, not %s",
node.DisconnectMsg());
6144 state.fSyncStarted =
false;
6146 peer.m_headers_sync_timeout = 0us;
6152 peer.m_headers_sync_timeout = std::chrono::microseconds::max();
6158 ConsiderEviction(
node, peer, GetTime<std::chrono::seconds>());
6163 std::vector<CInv> vGetData;
6165 std::vector<const CBlockIndex*> vToDownload;
6167 auto get_inflight_budget = [&state]() {
6174 FindNextBlocksToDownload(peer, get_inflight_budget(), vToDownload, staller);
6175 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
6176 if (historical_blocks && !IsLimitedPeer(peer)) {
6180 TryDownloadingHistoricalBlocks(
6182 get_inflight_budget(),
6183 vToDownload, from_tip, historical_blocks->second);
6186 uint32_t nFetchFlags = GetFetchFlags(peer);
6188 BlockRequested(
node.GetId(), *pindex);
6192 if (state.vBlocksInFlight.empty() && staller != -1) {
6193 if (
State(staller)->m_stalling_since == 0us) {
6194 State(staller)->m_stalling_since = current_time;
6204 LOCK(m_tx_download_mutex);
6205 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(
node.GetId(), current_time)) {
6214 if (!vGetData.empty())
6217 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...