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,
1089 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1095const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const
1097 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1098 if (it == m_node_states.end())
1105 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1113static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1118void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1120 assert(peer.m_addr_known);
1121 peer.m_addr_known->insert(addr.
GetKey());
1124void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1129 assert(peer.m_addr_known);
1130 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1132 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1134 peer.m_addrs_to_send.push_back(addr);
1139static void AddKnownTx(Peer& peer,
const uint256& hash)
1141 auto tx_relay = peer.GetTxRelay();
1142 if (!tx_relay)
return;
1144 LOCK(tx_relay->m_tx_inventory_mutex);
1145 tx_relay->m_tx_inventory_known_filter.insert(hash);
1149static bool CanServeBlocks(
const Peer& peer)
1156static bool IsLimitedPeer(
const Peer& peer)
1163static bool CanServeWitnesses(
const Peer& peer)
1168std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1169 std::chrono::seconds average_interval,
1170 uint64_t network_key)
1172 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1173 auto& timer{it->second};
1175 timer = now + m_rng.rand_exp_duration(average_interval);
1180bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1182 return mapBlocksInFlight.contains(hash);
1185bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1187 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1188 auto [nodeid, block_it] = range.first->second;
1189 PeerRef peer{GetPeerRef(nodeid)};
1190 if (peer && !peer->m_is_inbound)
return true;
1196void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1198 auto range = mapBlocksInFlight.equal_range(hash);
1199 if (range.first == range.second) {
1207 while (range.first != range.second) {
1208 const auto& [node_id, list_it]{range.first->second};
1210 if (from_peer && *from_peer != node_id) {
1217 if (state.vBlocksInFlight.begin() == list_it) {
1219 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1221 state.vBlocksInFlight.erase(list_it);
1223 if (state.vBlocksInFlight.empty()) {
1225 m_peers_downloading_from--;
1227 state.m_stalling_since = 0us;
1229 range.first = mapBlocksInFlight.erase(range.first);
1233bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1237 CNodeState *state =
State(nodeid);
1238 assert(state !=
nullptr);
1243 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1244 if (range.first->second.first == nodeid) {
1246 *pit = &range.first->second.second;
1253 RemoveBlockRequest(hash, nodeid);
1255 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1256 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1257 if (state->vBlocksInFlight.size() == 1) {
1259 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1260 m_peers_downloading_from++;
1262 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1264 *pit = &itInFlight->second.second;
1269void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1276 if (m_opts.ignore_incoming_txs)
return;
1278 CNodeState* nodestate =
State(nodeid);
1279 PeerRef peer{GetPeerRef(nodeid)};
1280 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1285 int num_outbound_hb_peers = 0;
1286 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1287 if (*it == nodeid) {
1288 lNodesAnnouncingHeaderAndIDs.erase(it);
1289 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1292 PeerRef peer_ref{GetPeerRef(*it)};
1293 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1295 if (peer && peer->m_is_inbound) {
1298 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1299 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1300 if (remove_peer && !remove_peer->m_is_inbound) {
1303 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1309 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1312 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1313 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1315 pnodeStop->m_bip152_highbandwidth_to = false;
1318 lNodesAnnouncingHeaderAndIDs.pop_front();
1323 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1328bool PeerManagerImpl::TipMayBeStale()
1332 if (m_last_tip_update.load() == 0
s) {
1333 m_last_tip_update = GetTime<std::chrono::seconds>();
1335 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1338int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1343bool PeerManagerImpl::CanDirectFetch()
1350 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1352 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1357void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1358 CNodeState *state =
State(nodeid);
1359 assert(state !=
nullptr);
1361 if (!state->hashLastUnknownBlock.IsNull()) {
1364 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1365 state->pindexBestKnownBlock = pindex;
1367 state->hashLastUnknownBlock.SetNull();
1372void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1373 CNodeState *state =
State(nodeid);
1374 assert(state !=
nullptr);
1376 ProcessBlockAvailability(nodeid);
1381 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1382 state->pindexBestKnownBlock = pindex;
1386 state->hashLastUnknownBlock = hash;
1391void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1396 vBlocks.reserve(vBlocks.size() +
count);
1397 CNodeState *state =
State(peer.m_id);
1398 assert(state !=
nullptr);
1401 ProcessBlockAvailability(peer.m_id);
1403 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1414 state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1415 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1424 if (state->pindexLastCommonBlock ==
nullptr ||
1425 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1426 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1427 state->pindexLastCommonBlock = fork_point;
1429 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1432 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1438 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1441void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1446 if (vBlocks.size() >=
count) {
1450 vBlocks.reserve(
count);
1453 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1470void 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)
1472 std::vector<const CBlockIndex*> vToFetch;
1473 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1474 bool is_limited_peer = IsLimitedPeer(peer);
1476 while (pindexWalk->
nHeight < nMaxHeight) {
1480 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1481 vToFetch.resize(nToFetch);
1482 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1483 vToFetch[nToFetch - 1] = pindexWalk;
1484 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1485 vToFetch[i - 1] = vToFetch[i]->
pprev;
1505 state->pindexLastCommonBlock = pindex;
1512 if (waitingfor == -1) {
1514 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1520 if (pindex->
nHeight > nWindowEnd) {
1522 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1524 if (nodeStaller) *nodeStaller = waitingfor;
1534 vBlocks.push_back(pindex);
1535 if (vBlocks.size() ==
count) {
1544void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1546 uint64_t my_services;
1548 uint64_t your_services;
1550 std::string my_user_agent;
1558 my_user_agent =
"/pynode:0.0.1/";
1560 my_tx_relay =
false;
1563 my_services = peer.m_our_services;
1568 my_height = m_best_height;
1569 my_tx_relay = !RejectIncomingTxs(pnode);
1588 BCLog::NET,
"send version message: version=%d, blocks=%d%s, txrelay=%d, peer=%d\n",
1591 my_tx_relay, pnode.
GetId());
1594void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1598 if (state) state->m_last_block_announcement = time_in_seconds;
1606 m_node_states.try_emplace(m_node_states.end(), nodeid);
1608 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1614 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1617 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1621void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1625 for (
const auto& txid : unbroadcast_txids) {
1628 if (tx !=
nullptr) {
1629 InitiateTxBroadcastToAll(txid, tx->GetWitnessHash());
1638 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1641void PeerManagerImpl::ReattemptPrivateBroadcast(
CScheduler& scheduler)
1645 size_t num_for_rebroadcast{0};
1646 const auto stale_txs = m_tx_for_private_broadcast.
GetStale();
1647 if (!stale_txs.empty()) {
1649 for (
const auto& stale_tx : stale_txs) {
1653 "Reattempting broadcast of stale txid=%s wtxid=%s",
1654 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString());
1655 ++num_for_rebroadcast;
1658 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString(),
1659 mempool_acceptable.m_state.ToString());
1660 m_tx_for_private_broadcast.
Remove(stale_tx);
1669 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, delta);
1672void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1683 PeerRef peer = RemovePeer(nodeid);
1685 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1686 assert(m_wtxid_relay_peers >= 0);
1688 CNodeState *state =
State(nodeid);
1689 assert(state !=
nullptr);
1691 if (state->fSyncStarted)
1694 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1695 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1696 while (range.first != range.second) {
1697 auto [node_id, list_it] = range.first->second;
1698 if (node_id != nodeid) {
1701 range.first = mapBlocksInFlight.erase(range.first);
1706 LOCK(m_tx_download_mutex);
1707 m_txdownloadman.DisconnectedPeer(nodeid);
1709 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1710 m_num_preferred_download_peers -= state->fPreferredDownload;
1711 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1712 assert(m_peers_downloading_from >= 0);
1713 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1714 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1716 m_node_states.erase(nodeid);
1718 if (m_node_states.empty()) {
1720 assert(mapBlocksInFlight.empty());
1721 assert(m_num_preferred_download_peers == 0);
1722 assert(m_peers_downloading_from == 0);
1723 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1724 assert(m_wtxid_relay_peers == 0);
1725 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1728 if (
node.fSuccessfullyConnected &&
1729 !
node.IsBlockOnlyConn() && !
node.IsPrivateBroadcastConn() && !
node.IsInboundConn()) {
1737 LOCK(m_headers_presync_mutex);
1738 m_headers_presync_stats.erase(nodeid);
1740 if (
node.IsPrivateBroadcastConn() &&
1749bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1752 return !(GetDesirableServiceFlags(services) & (~services));
1766PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1769 auto it = m_peer_map.find(
id);
1770 return it != m_peer_map.end() ? it->second :
nullptr;
1773PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1777 auto it = m_peer_map.find(
id);
1778 if (it != m_peer_map.end()) {
1779 ret = std::move(it->second);
1780 m_peer_map.erase(it);
1789 const CNodeState* state =
State(nodeid);
1790 if (state ==
nullptr)
1792 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1793 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1794 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1800 PeerRef peer = GetPeerRef(nodeid);
1801 if (peer ==
nullptr)
return false;
1809 auto ping_wait{0us};
1810 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1811 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1814 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1817 LOCK(tx_relay->m_tx_inventory_mutex);
1819 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1831 LOCK(peer->m_headers_sync_mutex);
1832 if (peer->m_headers_sync) {
1841std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1843 LOCK(m_tx_download_mutex);
1844 return m_txdownloadman.GetOrphanTransactions();
1851 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1855std::vector<PrivateBroadcast::TxBroadcastInfo> PeerManagerImpl::GetPrivateBroadcastInfo()
const
1860std::vector<CTransactionRef> PeerManagerImpl::AbortPrivateBroadcast(
const uint256&
id)
1863 std::vector<CTransactionRef> removed_txs;
1865 size_t connections_cancelled{0};
1866 for (
const auto& [tx,
_] : snapshot) {
1867 if (tx->GetHash().ToUint256() !=
id && tx->GetWitnessHash().ToUint256() !=
id)
continue;
1868 if (
const auto peer_acks{m_tx_for_private_broadcast.
Remove(tx)}) {
1869 removed_txs.push_back(tx);
1880void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1882 if (m_opts.max_extra_txs <= 0)
1884 if (!vExtraTxnForCompact.size())
1885 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1886 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1887 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1890void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1892 LOCK(peer.m_misbehavior_mutex);
1894 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1895 peer.m_should_discourage =
true;
1904 bool via_compact_block,
const std::string& message)
1906 PeerRef peer{GetPeerRef(nodeid)};
1917 if (!via_compact_block) {
1918 if (peer) Misbehaving(*peer, message);
1926 if (peer && !via_compact_block && !peer->m_is_inbound) {
1927 if (peer) Misbehaving(*peer, message);
1934 if (peer) Misbehaving(*peer, message);
1938 if (peer) Misbehaving(*peer, message);
1943 if (message !=
"") {
1948bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex& block_index)
1962 PeerRef peer = GetPeerRef(peer_id);
1971 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1974 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
1997 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
2003 : m_rng{opts.deterministic_rng},
2005 m_chainparams(chainman.GetParams()),
2009 m_chainman(chainman),
2011 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
2012 m_warnings{warnings},
2017 if (opts.reconcile_txs) {
2022void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2033 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2035 if (m_opts.private_broadcast) {
2036 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2040void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2048 LOCK(m_tx_download_mutex);
2052 m_txdownloadman.ActiveTipChange();
2062void PeerManagerImpl::BlockConnected(
2064 const std::shared_ptr<const CBlock>& pblock,
2069 m_last_tip_update = GetTime<std::chrono::seconds>();
2072 auto stalling_timeout = m_block_stalling_timeout.load();
2076 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2085 LOCK(m_tx_download_mutex);
2086 m_txdownloadman.BlockConnected(pblock);
2090void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2092 LOCK(m_tx_download_mutex);
2093 m_txdownloadman.BlockDisconnected();
2100void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2102 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2106 if (pindex->
nHeight <= m_highest_fast_announce)
2108 m_highest_fast_announce = pindex->
nHeight;
2112 uint256 hashBlock(pblock->GetHash());
2113 const std::shared_future<CSerializedNetMsg> lazy_ser{
2117 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2118 for (
const auto& tx : pblock->vtx) {
2119 most_recent_block_txs->emplace(tx->GetHash(), tx);
2120 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2123 LOCK(m_most_recent_block_mutex);
2124 m_most_recent_block_hash = hashBlock;
2125 m_most_recent_block = pblock;
2126 m_most_recent_compact_block = pcmpctblock;
2127 m_most_recent_block_txs = std::move(most_recent_block_txs);
2135 ProcessBlockAvailability(pnode->
GetId());
2139 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2141 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2142 hashBlock.ToString(), pnode->
GetId());
2145 PushMessage(*pnode, ser_cmpctblock.Copy());
2146 state.pindexBestHeaderSent = pindex;
2155void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2157 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2160 if (fInitialDownload)
return;
2163 std::vector<uint256> vHashes;
2165 while (pindexToAnnounce != pindexFork) {
2167 pindexToAnnounce = pindexToAnnounce->
pprev;
2177 for (
auto& it : m_peer_map) {
2178 Peer& peer = *it.second;
2179 LOCK(peer.m_block_inv_mutex);
2180 for (
const uint256& hash : vHashes | std::views::reverse) {
2181 peer.m_blocks_for_headers_relay.push_back(hash);
2193void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2197 const uint256 hash(block->GetHash());
2198 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2203 it != mapBlockSource.end() &&
2204 State(it->second.first)) {
2205 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2215 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2216 if (it != mapBlockSource.end()) {
2217 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2220 if (it != mapBlockSource.end())
2221 mapBlockSource.erase(it);
2229bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2234void PeerManagerImpl::SendPings()
2237 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2240void PeerManagerImpl::InitiateTxBroadcastToAll(
const Txid& txid,
const Wtxid& wtxid)
2243 for(
auto& it : m_peer_map) {
2244 Peer& peer = *it.second;
2245 auto tx_relay = peer.GetTxRelay();
2246 if (!tx_relay)
continue;
2248 LOCK(tx_relay->m_tx_inventory_mutex);
2254 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2257 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2258 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2263void PeerManagerImpl::InitiateTxBroadcastPrivate(
const CTransactionRef& tx)
2265 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2266 if (m_tx_for_private_broadcast.
Add(tx)) {
2274void PeerManagerImpl::RelayAddress(
NodeId originator,
2290 const auto current_time{GetTime<std::chrono::seconds>()};
2298 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2300 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2301 assert(nRelayNodes <= best.size());
2305 for (
auto& [
id, peer] : m_peer_map) {
2306 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2308 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2309 if (hashKey > best[i].first) {
2310 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2311 best[i] = std::make_pair(hashKey, peer.get());
2318 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2319 PushAddress(*best[i].second, addr);
2323void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2325 std::shared_ptr<const CBlock> a_recent_block;
2326 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2328 LOCK(m_most_recent_block_mutex);
2329 a_recent_block = m_most_recent_block;
2330 a_recent_compact_block = m_most_recent_compact_block;
2333 bool need_activate_chain =
false;
2345 need_activate_chain =
true;
2349 if (need_activate_chain) {
2351 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2358 bool can_direct_fetch{
false};
2366 if (!BlockRequestAllowed(*pindex)) {
2367 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2394 can_direct_fetch = CanDirectFetch();
2398 std::shared_ptr<const CBlock> pblock;
2399 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2400 pblock = a_recent_block;
2418 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2428 pblock = pblockRead;
2436 bool sendMerkleBlock =
false;
2438 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2439 LOCK(tx_relay->m_bloom_filter_mutex);
2440 if (tx_relay->m_bloom_filter) {
2441 sendMerkleBlock =
true;
2442 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2445 if (sendMerkleBlock) {
2453 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2464 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2477 LOCK(peer.m_block_inv_mutex);
2479 if (inv.
hash == peer.m_continuation_block) {
2483 std::vector<CInv> vInv;
2484 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2486 peer.m_continuation_block.SetNull();
2494 auto txinfo{std::visit(
2495 [&](
const auto&
id) {
2496 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2500 return std::move(txinfo.tx);
2505 LOCK(m_most_recent_block_mutex);
2506 if (m_most_recent_block_txs !=
nullptr) {
2507 auto it = m_most_recent_block_txs->find(gtxid);
2508 if (it != m_most_recent_block_txs->end())
return it->second;
2515void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2519 auto tx_relay = peer.GetTxRelay();
2521 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2522 std::vector<CInv> vNotFound;
2527 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2528 if (interruptMsgProc)
return;
2533 const CInv &inv = *it++;
2535 if (tx_relay ==
nullptr) {
2541 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2544 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2547 vNotFound.push_back(inv);
2553 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2554 const CInv &inv = *it++;
2556 ProcessGetBlockData(pfrom, peer, inv);
2565 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2567 if (!vNotFound.empty()) {
2586uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2588 uint32_t nFetchFlags = 0;
2589 if (CanServeWitnesses(peer)) {
2598 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2600 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2607 uint32_t tx_requested_size{0};
2608 for (
const auto& tx : resp.txn) tx_requested_size += tx->ComputeTotalSize();
2614bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2618 Misbehaving(peer,
"header with invalid proof of work");
2623 if (!CheckHeadersAreContinuous(headers)) {
2624 Misbehaving(peer,
"non-continuous headers sequence");
2649void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2650 const std::vector<CBlockHeader>& headers)
2654 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2655 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2657 headers[0].hashPrevBlock.ToString(),
2658 best_header->nHeight,
2668bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2672 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2675 hashLastBlock = header.GetHash();
2680bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2682 if (peer.m_headers_sync) {
2683 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2685 if (result.success) peer.m_last_getheaders_timestamp = {};
2686 if (result.request_more) {
2687 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2689 Assume(!locator.vHave.empty());
2692 if (!locator.vHave.empty()) {
2695 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2698 locator.vHave.front().ToString(), pfrom.
GetId());
2703 peer.m_headers_sync.reset(
nullptr);
2708 LOCK(m_headers_presync_mutex);
2709 m_headers_presync_stats.erase(pfrom.
GetId());
2712 HeadersPresyncStats stats;
2713 stats.first = peer.m_headers_sync->GetPresyncWork();
2715 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2716 peer.m_headers_sync->GetPresyncTime()};
2720 LOCK(m_headers_presync_mutex);
2721 m_headers_presync_stats[pfrom.
GetId()] = stats;
2722 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2723 bool best_updated =
false;
2724 if (best_it == m_headers_presync_stats.end()) {
2728 const HeadersPresyncStats* stat_best{
nullptr};
2729 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2730 if (!stat_best || stat > *stat_best) {
2735 m_headers_presync_bestpeer = peer_best;
2736 best_updated = (peer_best == pfrom.
GetId());
2737 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2739 m_headers_presync_bestpeer = pfrom.
GetId();
2740 best_updated =
true;
2742 if (best_updated && stats.second.has_value()) {
2744 m_headers_presync_should_signal =
true;
2748 if (result.success) {
2751 headers.swap(result.pow_validated_headers);
2754 return result.success;
2762bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
2769 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2773 if (total_work < minimum_chain_work) {
2777 if (headers.size() == m_opts.max_headers_result) {
2787 LOCK(peer.m_headers_sync_mutex);
2789 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2794 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2808bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2810 if (header ==
nullptr) {
2812 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2820bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2828 peer.m_last_getheaders_timestamp = current_time;
2839void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2842 CNodeState *nodestate =
State(pfrom.
GetId());
2845 std::vector<const CBlockIndex*> vToFetch;
2853 vToFetch.push_back(pindexWalk);
2855 pindexWalk = pindexWalk->
pprev;
2866 std::vector<CInv> vGetData;
2868 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2873 uint32_t nFetchFlags = GetFetchFlags(peer);
2875 BlockRequested(pfrom.
GetId(), *pindex);
2879 if (vGetData.size() > 1) {
2884 if (vGetData.size() > 0) {
2885 if (!m_opts.ignore_incoming_txs &&
2886 nodestate->m_provides_cmpctblocks &&
2887 vGetData.size() == 1 &&
2888 mapBlocksInFlight.size() == 1 &&
2904void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2905 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2908 CNodeState *nodestate =
State(pfrom.
GetId());
2917 nodestate->m_last_block_announcement =
GetTime();
2925 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2947 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) {
2949 nodestate->m_chain_sync.m_protect =
true;
2950 ++m_outbound_peers_with_protect_from_disconnect;
2955void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2956 std::vector<CBlockHeader>&& headers,
2957 bool via_compact_block)
2959 size_t nCount = headers.size();
2966 LOCK(peer.m_headers_sync_mutex);
2967 if (peer.m_headers_sync) {
2968 peer.m_headers_sync.reset(
nullptr);
2969 LOCK(m_headers_presync_mutex);
2970 m_headers_presync_stats.erase(pfrom.
GetId());
2974 peer.m_last_getheaders_timestamp = {};
2982 if (!CheckHeadersPoW(headers, peer)) {
2997 bool already_validated_work =
false;
3000 bool have_headers_sync =
false;
3002 LOCK(peer.m_headers_sync_mutex);
3004 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3016 if (headers.empty()) {
3020 have_headers_sync = !!peer.m_headers_sync;
3025 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3027 if (!headers_connect_blockindex) {
3031 HandleUnconnectingHeaders(pfrom, peer, headers);
3038 peer.m_last_getheaders_timestamp = {};
3048 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3055 already_validated_work =
true;
3061 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3062 *chain_start_header, headers)) {
3074 bool received_new_header{last_received_header ==
nullptr};
3080 state, &pindexLast)};
3086 "If this happens with all peers, consider database corruption (that -reindex may fix) "
3087 "or a potential consensus incompatibility.",
3090 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3096 if (processed && received_new_header) {
3097 LogBlockHeader(*pindexLast, pfrom,
false);
3101 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3103 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3108 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3111 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3117 bool first_time_failure)
3123 PeerRef peer{GetPeerRef(nodeid)};
3126 ptx->GetHash().ToString(),
3127 ptx->GetWitnessHash().ToString(),
3131 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3134 AddToCompactExtraTransactions(ptx);
3136 for (
const Txid& parent_txid : unique_parents) {
3137 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3140 return package_to_validate;
3143void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3149 m_txdownloadman.MempoolAcceptedTx(tx);
3153 tx->GetHash().ToString(),
3154 tx->GetWitnessHash().ToString(),
3157 InitiateTxBroadcastToAll(tx->GetHash(), tx->GetWitnessHash());
3160 AddToCompactExtraTransactions(removedTx);
3170 const auto&
package = package_to_validate.m_txns;
3171 const auto& senders = package_to_validate.
m_senders;
3174 m_txdownloadman.MempoolRejectedPackage(package);
3177 if (!
Assume(package.size() == 2))
return;
3181 auto package_iter = package.rbegin();
3182 auto senders_iter = senders.rbegin();
3183 while (package_iter != package.rend()) {
3184 const auto& tx = *package_iter;
3185 const NodeId nodeid = *senders_iter;
3186 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3190 const auto& tx_result = it_result->second;
3191 switch (tx_result.m_result_type) {
3194 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3204 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3222bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3229 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3232 const Txid& orphanHash = porphanTx->GetHash();
3233 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3250 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3259bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3261 const uint256& stop_hash, uint32_t max_height_diff,
3265 const bool supported_filter_type =
3268 if (!supported_filter_type) {
3270 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg());
3271 node.fDisconnect =
true;
3280 if (!stop_index || !BlockRequestAllowed(*stop_index)) {
3283 node.fDisconnect =
true;
3288 uint32_t stop_height = stop_index->
nHeight;
3289 if (start_height > stop_height) {
3291 "start height %d and stop height %d, %s",
3292 start_height, stop_height,
node.DisconnectMsg());
3293 node.fDisconnect =
true;
3296 if (stop_height - start_height >= max_height_diff) {
3298 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg());
3299 node.fDisconnect =
true;
3304 if (!filter_index) {
3314 uint8_t filter_type_ser;
3315 uint32_t start_height;
3318 vRecv >> filter_type_ser >> start_height >> stop_hash;
3324 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3329 std::vector<BlockFilter> filters;
3331 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3336 for (
const auto& filter : filters) {
3343 uint8_t filter_type_ser;
3344 uint32_t start_height;
3347 vRecv >> filter_type_ser >> start_height >> stop_hash;
3353 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3359 if (start_height > 0) {
3361 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3363 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3369 std::vector<uint256> filter_hashes;
3371 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3385 uint8_t filter_type_ser;
3388 vRecv >> filter_type_ser >> stop_hash;
3394 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3395 std::numeric_limits<uint32_t>::max(),
3396 stop_index, filter_index)) {
3404 for (
int i = headers.size() - 1; i >= 0; i--) {
3409 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3423 bool new_block{
false};
3424 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3426 node.m_last_block_time = GetTime<std::chrono::seconds>();
3431 RemoveBlockRequest(block->GetHash(), std::nullopt);
3434 mapBlockSource.erase(block->GetHash());
3438void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3440 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3441 bool fBlockRead{
false};
3445 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3446 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3447 bool requested_block_from_this_peer{
false};
3450 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3452 while (range_flight.first != range_flight.second) {
3453 auto [node_id, block_it] = range_flight.first->second;
3454 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3455 requested_block_from_this_peer =
true;
3458 range_flight.first++;
3461 if (!requested_block_from_this_peer) {
3473 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3484 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3487 if (first_in_flight) {
3492 std::vector<CInv> invs;
3497 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3510 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3525void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3537 "Saw new %sheader hash=%s height=%d %s",
3538 via_compact_block ?
"cmpctblock " :
"",
3550void PeerManagerImpl::PushPrivateBroadcastTx(
CNode&
node)
3557 node.fDisconnect =
true;
3563 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3569void PeerManagerImpl::ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3570 const std::chrono::microseconds time_received,
3571 const std::atomic<bool>& interruptMsgProc)
3586 uint64_t nNonce = 1;
3589 std::string cleanSubVer;
3590 int starting_height = -1;
3593 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3608 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s",
3610 GetDesirableServiceFlags(nServices),
3623 if (!vRecv.
empty()) {
3631 if (!vRecv.
empty()) {
3632 std::string strSubVer;
3636 if (!vRecv.
empty()) {
3637 vRecv >> starting_height;
3657 PushNodeVersion(pfrom, peer);
3666 peer.m_their_services = nServices;
3670 pfrom.cleanSubVer = cleanSubVer;
3681 (fRelay || (peer.m_our_services &
NODE_BLOOM))) {
3682 auto*
const tx_relay = peer.SetTxRelay();
3684 LOCK(tx_relay->m_bloom_filter_mutex);
3685 tx_relay->m_relay_txs = fRelay;
3691 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, %s%s",
3692 cleanSubVer.empty() ?
"<no user agent>" : cleanSubVer, pfrom.
nVersion,
3694 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3712 if (greatest_common_version >= 70016) {
3727 const auto* tx_relay = peer.GetTxRelay();
3728 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3730 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3743 m_num_preferred_download_peers += state->fPreferredDownload;
3749 bool send_getaddr{
false};
3751 send_getaddr = SetupAddressRelay(pfrom, peer);
3761 peer.m_getaddr_sent =
true;
3785 peer.m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3789 m_outbound_time_offsets.Add(peer.m_time_offset);
3790 m_outbound_time_offsets.WarnIfOutOfSync();
3794 if (greatest_common_version <= 70012) {
3795 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3796 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3819 auto new_peer_msg = [&]() {
3821 return strprintf(
"New %s peer connected: transport: %s, version: %d, %s%s",
3825 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3833 LogInfo(
"%s", new_peer_msg());
3836 if (
auto tx_relay = peer.GetTxRelay()) {
3845 tx_relay->m_tx_inventory_mutex,
3846 return tx_relay->m_tx_inventory_to_send.empty() &&
3847 tx_relay->m_next_inv_send_time == 0
s));
3857 PushPrivateBroadcastTx(pfrom);
3870 if (m_txreconciliation) {
3871 if (!peer.m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3875 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3881 const CNodeState* state =
State(pfrom.
GetId());
3883 .m_preferred = state->fPreferredDownload,
3884 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3885 .m_wtxid_relay = peer.m_wtxid_relay,
3894 peer.m_prefers_headers =
true;
3899 bool sendcmpct_hb{
false};
3900 uint64_t sendcmpct_version{0};
3901 vRecv >> sendcmpct_hb >> sendcmpct_version;
3907 CNodeState* nodestate =
State(pfrom.
GetId());
3908 nodestate->m_provides_cmpctblocks =
true;
3909 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3926 if (!peer.m_wtxid_relay) {
3927 peer.m_wtxid_relay =
true;
3928 m_wtxid_relay_peers++;
3947 peer.m_wants_addrv2 =
true;
3955 if (!m_txreconciliation) {
3956 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3967 if (RejectIncomingTxs(pfrom)) {
3976 const auto* tx_relay = peer.GetTxRelay();
3977 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3983 uint32_t peer_txreconcl_version;
3984 uint64_t remote_salt;
3985 vRecv >> peer_txreconcl_version >> remote_salt;
3988 peer_txreconcl_version, remote_salt);
4020 const auto ser_params{
4028 std::vector<CAddress> vAddr;
4030 vRecv >> ser_params(vAddr);
4032 if (!SetupAddressRelay(pfrom, peer)) {
4039 Misbehaving(peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
4044 std::vector<CAddress> vAddrOk;
4045 const auto current_a_time{Now<NodeSeconds>()};
4048 const auto current_time{GetTime<std::chrono::microseconds>()};
4051 const auto time_diff = std::max(current_time - peer.m_addr_token_timestamp, 0us);
4055 peer.m_addr_token_timestamp = current_time;
4058 uint64_t num_proc = 0;
4059 uint64_t num_rate_limit = 0;
4060 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
4063 if (interruptMsgProc)
4067 if (peer.m_addr_token_bucket < 1.0) {
4073 peer.m_addr_token_bucket -= 1.0;
4082 addr.
nTime = current_a_time - 5 * 24h;
4084 AddAddressKnown(peer, addr);
4091 if (addr.
nTime > current_a_time - 10min && !peer.m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
4093 RelayAddress(pfrom.
GetId(), addr, reachable);
4097 vAddrOk.push_back(addr);
4100 peer.m_addr_processed += num_proc;
4101 peer.m_addr_rate_limited += num_rate_limit;
4102 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
4103 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
4105 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
4106 if (vAddr.size() < 1000) peer.m_getaddr_sent =
false;
4117 std::vector<CInv> vInv;
4121 Misbehaving(peer,
strprintf(
"inv message size = %u", vInv.size()));
4125 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4129 const auto current_time{GetTime<std::chrono::microseconds>()};
4132 for (
CInv& inv : vInv) {
4133 if (interruptMsgProc)
return;
4138 if (peer.m_wtxid_relay) {
4145 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4148 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4156 best_block = &inv.
hash;
4159 if (reject_tx_invs) {
4165 AddKnownTx(peer, inv.
hash);
4168 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4176 if (best_block !=
nullptr) {
4188 if (state.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4189 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer)) {
4191 m_chainman.m_best_header->nHeight, best_block->ToString(),
4194 if (!state.fSyncStarted) {
4195 peer.m_inv_triggered_getheaders_before_sync =
true;
4199 m_last_block_inv_triggering_headers_sync = *best_block;
4208 std::vector<CInv> vInv;
4212 Misbehaving(peer,
strprintf(
"getdata message size = %u", vInv.size()));
4218 if (vInv.size() > 0) {
4223 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4224 if (!pushed_tx_opt) {
4235 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4239 peer.m_ping_queued =
true;
4240 MaybeSendPing(pfrom, peer, GetTime<std::chrono::microseconds>());
4250 LOCK(peer.m_getdata_requests_mutex);
4251 peer.m_getdata_requests.insert(peer.m_getdata_requests.end(), vInv.begin(), vInv.end());
4252 ProcessGetData(pfrom, peer, interruptMsgProc);
4261 vRecv >> locator >> hashStop;
4277 std::shared_ptr<const CBlock> a_recent_block;
4279 LOCK(m_most_recent_block_mutex);
4280 a_recent_block = m_most_recent_block;
4283 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4298 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4313 if (--nLimit <= 0) {
4317 WITH_LOCK(peer.m_block_inv_mutex, {peer.m_continuation_block = pindex->GetBlockHash();});
4329 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4333 std::shared_ptr<const CBlock> recent_block;
4335 LOCK(m_most_recent_block_mutex);
4336 if (m_most_recent_block_hash == req.
blockhash)
4337 recent_block = m_most_recent_block;
4341 SendBlockTransactions(pfrom, peer, *recent_block, req);
4360 if (!block_pos.IsNull()) {
4367 SendBlockTransactions(pfrom, peer, block, req);
4380 WITH_LOCK(peer.m_getdata_requests_mutex, peer.m_getdata_requests.push_back(inv));
4388 vRecv >> locator >> hashStop;
4406 if (m_chainman.
ActiveTip() ==
nullptr ||
4408 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4415 CNodeState *nodestate =
State(pfrom.
GetId());
4424 if (!BlockRequestAllowed(*pindex)) {
4425 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4438 std::vector<CBlock> vHeaders;
4439 int nLimit = m_opts.max_headers_result;
4441 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4444 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4459 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4465 if (RejectIncomingTxs(pfrom)) {
4479 const Txid& txid = ptx->GetHash();
4480 const Wtxid& wtxid = ptx->GetWitnessHash();
4483 AddKnownTx(peer, hash);
4485 if (
const auto num_broadcasted{m_tx_for_private_broadcast.
Remove(ptx)}) {
4487 "network from %s; stopping private broadcast attempts",
4498 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4499 if (!should_validate) {
4504 if (!m_mempool.
exists(txid)) {
4505 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4508 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4510 InitiateTxBroadcastToAll(txid, wtxid);
4514 if (package_to_validate) {
4517 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4518 ProcessPackageResult(package_to_validate.value(), package_result);
4524 Assume(!package_to_validate.has_value());
4534 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4537 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4538 ProcessPackageResult(package_to_validate.value(), package_result);
4554 vRecv >> cmpctblock;
4556 bool received_new_header =
false;
4566 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer);
4576 received_new_header =
true;
4584 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4591 if (received_new_header) {
4592 LogBlockHeader(*pindex, pfrom,
true);
4595 bool fProcessBLOCKTXN =
false;
4599 bool fRevertToHeaderProcessing =
false;
4603 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4604 bool fBlockReconstructed =
false;
4610 CNodeState *nodestate =
State(pfrom.
GetId());
4615 nodestate->m_last_block_announcement =
GetTime();
4621 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4622 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4623 bool requested_block_from_this_peer{
false};
4626 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4628 while (range_flight.first != range_flight.second) {
4629 if (range_flight.first->second.first == pfrom.
GetId()) {
4630 requested_block_from_this_peer =
true;
4633 range_flight.first++;
4638 if (requested_block_from_this_peer) {
4641 std::vector<CInv> vInv(1);
4649 if (!already_in_flight && !CanDirectFetch()) {
4657 requested_block_from_this_peer) {
4658 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4659 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4660 if (!(*queuedBlockIt)->partialBlock)
4673 Misbehaving(peer,
"invalid compact block");
4676 if (first_in_flight) {
4678 std::vector<CInv> vInv(1);
4689 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4694 fProcessBLOCKTXN =
true;
4695 }
else if (first_in_flight) {
4702 IsBlockRequestedFromOutbound(blockhash) ||
4721 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4726 std::vector<CTransactionRef> dummy;
4728 status = tempBlock.FillBlock(*pblock, dummy,
4731 fBlockReconstructed =
true;
4735 if (requested_block_from_this_peer) {
4738 std::vector<CInv> vInv(1);
4744 fRevertToHeaderProcessing =
true;
4749 if (fProcessBLOCKTXN) {
4752 return ProcessCompactBlockTxns(pfrom, peer, txn);
4755 if (fRevertToHeaderProcessing) {
4761 return ProcessHeadersMessage(pfrom, peer, {cmpctblock.
header},
true);
4764 if (fBlockReconstructed) {
4769 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4787 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4804 return ProcessCompactBlockTxns(pfrom, peer, resp);
4815 std::vector<CBlockHeader> headers;
4819 if (nCount > m_opts.max_headers_result) {
4820 Misbehaving(peer,
strprintf(
"headers message size = %u", nCount));
4823 headers.resize(nCount);
4824 for (
unsigned int n = 0; n < nCount; n++) {
4825 vRecv >> headers[n];
4829 ProcessHeadersMessage(pfrom, peer, std::move(headers),
false);
4833 if (m_headers_presync_should_signal.exchange(
false)) {
4834 HeadersPresyncStats stats;
4836 LOCK(m_headers_presync_mutex);
4837 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4838 if (it != m_headers_presync_stats.end()) stats = it->second;
4856 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4867 Misbehaving(peer,
"mutated block");
4872 bool forceProcessing =
false;
4873 const uint256 hash(pblock->GetHash());
4874 bool min_pow_checked =
false;
4879 forceProcessing = IsBlockRequested(hash);
4880 RemoveBlockRequest(hash, pfrom.
GetId());
4884 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4888 min_pow_checked =
true;
4891 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4908 Assume(SetupAddressRelay(pfrom, peer));
4912 if (peer.m_getaddr_recvd) {
4916 peer.m_getaddr_recvd =
true;
4918 peer.m_addrs_to_send.clear();
4919 std::vector<CAddress> vAddr;
4925 for (
const CAddress &addr : vAddr) {
4926 PushAddress(peer, addr);
4954 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4955 LOCK(tx_relay->m_tx_inventory_mutex);
4956 tx_relay->m_send_mempool =
true;
4982 const auto ping_end = time_received;
4985 bool bPingFinished =
false;
4986 std::string sProblem;
4988 if (nAvail >=
sizeof(
nonce)) {
4992 if (peer.m_ping_nonce_sent != 0) {
4993 if (
nonce == peer.m_ping_nonce_sent) {
4995 bPingFinished =
true;
4996 const auto ping_time = ping_end - peer.m_ping_start.load();
4997 if (ping_time.count() >= 0) {
5008 sProblem =
"Timing mishap";
5012 sProblem =
"Nonce mismatch";
5015 bPingFinished =
true;
5016 sProblem =
"Nonce zero";
5020 sProblem =
"Unsolicited pong without ping";
5024 bPingFinished =
true;
5025 sProblem =
"Short payload";
5028 if (!(sProblem.empty())) {
5032 peer.m_ping_nonce_sent,
5036 if (bPingFinished) {
5037 peer.m_ping_nonce_sent = 0;
5054 Misbehaving(peer,
"too-large bloom filter");
5055 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5057 LOCK(tx_relay->m_bloom_filter_mutex);
5058 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
5059 tx_relay->m_relay_txs =
true;
5073 std::vector<unsigned char> vData;
5081 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5082 LOCK(tx_relay->m_bloom_filter_mutex);
5083 if (tx_relay->m_bloom_filter) {
5084 tx_relay->m_bloom_filter->insert(vData);
5090 Misbehaving(peer,
"bad filteradd message");
5101 auto tx_relay = peer.GetTxRelay();
5102 if (!tx_relay)
return;
5105 LOCK(tx_relay->m_bloom_filter_mutex);
5106 tx_relay->m_bloom_filter =
nullptr;
5107 tx_relay->m_relay_txs =
true;
5116 vRecv >> newFeeFilter;
5118 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5119 tx_relay->m_fee_filter_received = newFeeFilter;
5127 ProcessGetCFilters(pfrom, peer, vRecv);
5132 ProcessGetCFHeaders(pfrom, peer, vRecv);
5137 ProcessGetCFCheckPt(pfrom, peer, vRecv);
5142 std::vector<CInv> vInv;
5144 std::vector<GenTxid> tx_invs;
5146 for (
CInv &inv : vInv) {
5152 LOCK(m_tx_download_mutex);
5153 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5162bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5165 LOCK(peer.m_misbehavior_mutex);
5168 if (!peer.m_should_discourage)
return false;
5170 peer.m_should_discourage =
false;
5175 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5181 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5201bool PeerManagerImpl::ProcessMessages(
CNode&
node, std::atomic<bool>& interruptMsgProc)
5206 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5207 if (maybe_peer ==
nullptr)
return false;
5208 Peer& peer{*maybe_peer};
5212 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent)
return false;
5215 LOCK(peer.m_getdata_requests_mutex);
5216 if (!peer.m_getdata_requests.empty()) {
5217 ProcessGetData(
node, peer, interruptMsgProc);
5221 const bool processed_orphan = ProcessOrphanTx(peer);
5223 if (
node.fDisconnect)
5226 if (processed_orphan)
return true;
5231 LOCK(peer.m_getdata_requests_mutex);
5232 if (!peer.m_getdata_requests.empty())
return true;
5236 if (
node.fPauseSend)
return false;
5238 auto poll_result{
node.PollMessage()};
5245 bool fMoreWork = poll_result->second;
5249 node.m_addr_name.c_str(),
5250 node.ConnectionTypeAsString().c_str(),
5256 if (m_opts.capture_messages) {
5261 ProcessMessage(peer,
node,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5262 if (interruptMsgProc)
return false;
5264 LOCK(peer.m_getdata_requests_mutex);
5265 if (!peer.m_getdata_requests.empty()) fMoreWork =
true;
5272 LOCK(m_tx_download_mutex);
5273 if (m_txdownloadman.HaveMoreWork(peer.m_id)) fMoreWork =
true;
5274 }
catch (
const std::exception& e) {
5283void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5296 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5298 if (state.m_chain_sync.m_timeout != 0
s) {
5299 state.m_chain_sync.m_timeout = 0
s;
5300 state.m_chain_sync.m_work_header =
nullptr;
5301 state.m_chain_sync.m_sent_getheaders =
false;
5303 }
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)) {
5311 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5312 state.m_chain_sync.m_sent_getheaders =
false;
5313 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5317 if (state.m_chain_sync.m_sent_getheaders) {
5319 LogInfo(
"Outbound peer has old chain, best known block = %s, %s", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg());
5322 assert(state.m_chain_sync.m_work_header);
5327 MaybeSendGetHeaders(pto,
5328 GetLocator(state.m_chain_sync.m_work_header->pprev),
5330 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());
5331 state.m_chain_sync.m_sent_getheaders =
true;
5343void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5352 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5356 if (pnode->
GetId() > youngest_peer.first) {
5357 next_youngest_peer = youngest_peer;
5358 youngest_peer.first = pnode->GetId();
5359 youngest_peer.second = pnode->m_last_block_time;
5362 NodeId to_disconnect = youngest_peer.first;
5363 if (youngest_peer.second > next_youngest_peer.second) {
5366 to_disconnect = next_youngest_peer.first;
5375 CNodeState *node_state =
State(pnode->
GetId());
5376 if (node_state ==
nullptr ||
5379 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5383 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5399 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5402 AssertLockHeld(::cs_main);
5406 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5407 CNodeState *state = State(pnode->GetId());
5408 if (state == nullptr) return;
5410 if (state->m_chain_sync.m_protect) return;
5413 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5414 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5415 worst_peer = pnode->GetId();
5416 oldest_block_announcement = state->m_last_block_announcement;
5419 if (worst_peer != -1) {
5430 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5434 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5451void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5455 auto now{GetTime<std::chrono::seconds>()};
5457 EvictExtraOutboundPeers(now);
5459 if (now > m_stale_tip_check_time) {
5463 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5472 if (!m_initial_sync_finished && CanDirectFetch()) {
5474 m_initial_sync_finished =
true;
5478void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5481 peer.m_ping_nonce_sent &&
5491 bool pingSend =
false;
5493 if (peer.m_ping_queued) {
5498 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5507 }
while (
nonce == 0);
5508 peer.m_ping_queued =
false;
5509 peer.m_ping_start = now;
5511 peer.m_ping_nonce_sent =
nonce;
5515 peer.m_ping_nonce_sent = 0;
5521void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5524 if (!peer.m_addr_relay_enabled)
return;
5526 LOCK(peer.m_addr_send_times_mutex);
5529 peer.m_next_local_addr_send < current_time) {
5536 if (peer.m_next_local_addr_send != 0us) {
5537 peer.m_addr_known->reset();
5540 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5541 if (peer.m_next_local_addr_send == 0us) {
5545 if (IsAddrCompatible(peer, local_addr)) {
5546 std::vector<CAddress> self_announcement{local_addr};
5547 if (peer.m_wants_addrv2) {
5555 PushAddress(peer, local_addr);
5562 if (current_time <= peer.m_next_addr_send)
return;
5575 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5576 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5579 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5580 peer.m_addrs_to_send.end());
5583 if (peer.m_addrs_to_send.empty())
return;
5585 if (peer.m_wants_addrv2) {
5590 peer.m_addrs_to_send.clear();
5593 if (peer.m_addrs_to_send.capacity() > 40) {
5594 peer.m_addrs_to_send.shrink_to_fit();
5598void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5606 CNodeState &state = *
State(
node.GetId());
5607 if (state.pindexBestKnownBlock !=
nullptr &&
5614 peer.m_sent_sendheaders =
true;
5619void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5621 if (m_opts.ignore_incoming_txs)
return;
5637 if (peer.m_fee_filter_sent == MAX_FILTER) {
5640 peer.m_next_send_feefilter = 0us;
5643 if (current_time > peer.m_next_send_feefilter) {
5644 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5647 if (filterToSend != peer.m_fee_filter_sent) {
5649 peer.m_fee_filter_sent = filterToSend;
5656 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5662class CompareInvMempoolOrder
5666 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5668 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5677bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5687bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5692 if (
node.IsBlockOnlyConn())
return false;
5694 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5698 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5704bool PeerManagerImpl::SendMessages(
CNode&
node)
5709 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5710 if (!maybe_peer)
return false;
5711 Peer& peer{*maybe_peer};
5716 if (MaybeDiscourageAndDisconnect(
node, peer))
return true;
5719 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent) {
5720 PushNodeVersion(
node, peer);
5721 peer.m_outbound_version_message_sent =
true;
5725 if (!
node.fSuccessfullyConnected ||
node.fDisconnect)
5728 const auto current_time{GetTime<std::chrono::microseconds>()};
5733 if (
node.IsPrivateBroadcastConn()) {
5737 node.fDisconnect =
true;
5744 node.fDisconnect =
true;
5748 MaybeSendPing(
node, peer, current_time);
5751 if (
node.fDisconnect)
return true;
5753 MaybeSendAddr(
node, peer, current_time);
5755 MaybeSendSendHeaders(
node, peer);
5760 CNodeState &state = *
State(
node.GetId());
5763 if (m_chainman.m_best_header ==
nullptr) {
5770 bool sync_blocks_and_headers_from_peer =
false;
5771 if (state.fPreferredDownload) {
5772 sync_blocks_and_headers_from_peer =
true;
5773 }
else if (CanServeBlocks(peer) && !
node.IsAddrFetchConn()) {
5783 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5784 sync_blocks_and_headers_from_peer =
true;
5790 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5791 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5799 if (pindexStart->
pprev)
5800 pindexStart = pindexStart->
pprev;
5804 state.fSyncStarted =
true;
5828 LOCK(peer.m_block_inv_mutex);
5829 std::vector<CBlock> vHeaders;
5830 bool fRevertToInv = ((!peer.m_prefers_headers &&
5831 (!state.m_requested_hb_cmpctblocks || peer.m_blocks_for_headers_relay.size() > 1)) ||
5834 ProcessBlockAvailability(
node.GetId());
5836 if (!fRevertToInv) {
5837 bool fFoundStartingHeader =
false;
5841 for (
const uint256& hash : peer.m_blocks_for_headers_relay) {
5846 fRevertToInv =
true;
5849 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5861 fRevertToInv =
true;
5864 pBestIndex = pindex;
5865 if (fFoundStartingHeader) {
5868 }
else if (PeerHasHeader(&state, pindex)) {
5870 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5873 fFoundStartingHeader =
true;
5878 fRevertToInv =
true;
5883 if (!fRevertToInv && !vHeaders.empty()) {
5884 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5888 vHeaders.front().GetHash().ToString(),
node.GetId());
5890 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5892 LOCK(m_most_recent_block_mutex);
5893 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5897 if (cached_cmpctblock_msg.has_value()) {
5898 PushMessage(
node, std::move(cached_cmpctblock_msg.value()));
5906 state.pindexBestHeaderSent = pBestIndex;
5907 }
else if (peer.m_prefers_headers) {
5908 if (vHeaders.size() > 1) {
5911 vHeaders.front().GetHash().ToString(),
5912 vHeaders.back().GetHash().ToString(),
node.GetId());
5915 vHeaders.front().GetHash().ToString(),
node.GetId());
5918 state.pindexBestHeaderSent = pBestIndex;
5920 fRevertToInv =
true;
5926 if (!peer.m_blocks_for_headers_relay.empty()) {
5927 const uint256& hashToAnnounce = peer.m_blocks_for_headers_relay.back();
5940 if (!PeerHasHeader(&state, pindex)) {
5941 peer.m_blocks_for_inv_relay.push_back(hashToAnnounce);
5947 peer.m_blocks_for_headers_relay.clear();
5953 std::vector<CInv> vInv;
5955 LOCK(peer.m_block_inv_mutex);
5959 for (
const uint256& hash : peer.m_blocks_for_inv_relay) {
5966 peer.m_blocks_for_inv_relay.clear();
5969 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5970 LOCK(tx_relay->m_tx_inventory_mutex);
5973 if (tx_relay->m_next_inv_send_time < current_time) {
5974 fSendTrickle =
true;
5975 if (
node.IsInboundConn()) {
5984 LOCK(tx_relay->m_bloom_filter_mutex);
5985 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5989 if (fSendTrickle && tx_relay->m_send_mempool) {
5990 auto vtxinfo = m_mempool.
infoAll();
5991 tx_relay->m_send_mempool =
false;
5992 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5994 LOCK(tx_relay->m_bloom_filter_mutex);
5996 for (
const auto& txinfo : vtxinfo) {
5997 const Txid& txid{txinfo.tx->GetHash()};
5998 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
5999 const auto inv = peer.m_wtxid_relay ?
6002 tx_relay->m_tx_inventory_to_send.erase(wtxid);
6005 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6008 if (tx_relay->m_bloom_filter) {
6009 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6011 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6012 vInv.push_back(inv);
6023 std::vector<std::set<Wtxid>::iterator> vInvTx;
6024 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
6025 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
6026 vInvTx.push_back(it);
6028 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6031 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
6032 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6035 unsigned int nRelayedTransactions = 0;
6036 LOCK(tx_relay->m_bloom_filter_mutex);
6039 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
6041 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6042 std::set<Wtxid>::iterator it = vInvTx.back();
6046 tx_relay->m_tx_inventory_to_send.erase(it);
6048 auto txinfo = m_mempool.
info(wtxid);
6055 const auto inv = peer.m_wtxid_relay ?
6057 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
6059 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
6063 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6066 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6068 vInv.push_back(inv);
6069 nRelayedTransactions++;
6074 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6079 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6086 auto stalling_timeout = m_block_stalling_timeout.load();
6087 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6091 LogInfo(
"Peer is stalling block download, %s",
node.DisconnectMsg());
6092 node.fDisconnect =
true;
6096 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6106 if (state.vBlocksInFlight.size() > 0) {
6107 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6108 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6110 LogInfo(
"Timeout downloading block %s, %s", queuedBlock.pindex->GetBlockHash().ToString(),
node.DisconnectMsg());
6111 node.fDisconnect =
true;
6116 if (state.fSyncStarted && peer.m_headers_sync_timeout < std::chrono::microseconds::max()) {
6118 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6119 if (current_time > peer.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6126 LogInfo(
"Timeout downloading headers, %s",
node.DisconnectMsg());
6127 node.fDisconnect =
true;
6130 LogInfo(
"Timeout downloading headers from noban peer, not %s",
node.DisconnectMsg());
6136 state.fSyncStarted =
false;
6138 peer.m_headers_sync_timeout = 0us;
6144 peer.m_headers_sync_timeout = std::chrono::microseconds::max();
6150 ConsiderEviction(
node, peer, GetTime<std::chrono::seconds>());
6155 std::vector<CInv> vGetData;
6157 std::vector<const CBlockIndex*> vToDownload;
6159 auto get_inflight_budget = [&state]() {
6166 FindNextBlocksToDownload(peer, get_inflight_budget(), vToDownload, staller);
6167 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
6168 if (historical_blocks && !IsLimitedPeer(peer)) {
6172 TryDownloadingHistoricalBlocks(
6174 get_inflight_budget(),
6175 vToDownload, from_tip, historical_blocks->second);
6178 uint32_t nFetchFlags = GetFetchFlags(peer);
6180 BlockRequested(
node.GetId(), *pindex);
6184 if (state.vBlocksInFlight.empty() && staller != -1) {
6185 if (
State(staller)->m_stalling_since == 0us) {
6186 State(staller)->m_stalling_since = current_time;
6196 LOCK(m_tx_download_mutex);
6197 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(
node.GetId(), current_time)) {
6206 if (!vGetData.empty())
6209 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...