74#include <initializer_list>
210 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
244 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
247 const bool m_is_inbound;
250 Mutex m_misbehavior_mutex;
252 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
255 Mutex m_block_inv_mutex;
259 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
263 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
274 std::atomic<uint64_t> m_ping_nonce_sent{0};
278 std::atomic<bool> m_ping_queued{
false};
281 std::atomic<bool> m_wtxid_relay{
false};
293 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
295 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
306 std::set<Wtxid> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
310 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
313 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
316 uint64_t m_last_inv_sequence
GUARDED_BY(m_tx_inventory_mutex){1};
319 std::atomic<CAmount> m_fee_filter_received{0};
325 LOCK(m_tx_relay_mutex);
327 m_tx_relay = std::make_unique<Peer::TxRelay>();
328 return m_tx_relay.get();
333 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
362 std::atomic_bool m_addr_relay_enabled{
false};
366 mutable Mutex m_addr_send_times_mutex;
368 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
370 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
373 std::atomic_bool m_wants_addrv2{
false};
382 std::atomic<uint64_t> m_addr_rate_limited{0};
384 std::atomic<uint64_t> m_addr_processed{0};
390 Mutex m_getdata_requests_mutex;
392 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
398 Mutex m_headers_sync_mutex;
401 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
404 std::atomic<bool> m_sent_sendheaders{
false};
414 std::atomic<std::chrono::seconds> m_time_offset{0
s};
418 , m_our_services{our_services}
419 , m_is_inbound{is_inbound}
423 mutable Mutex m_tx_relay_mutex;
426 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
429using PeerRef = std::shared_ptr<Peer>;
441 uint256 hashLastUnknownBlock{};
447 bool fSyncStarted{
false};
449 std::chrono::microseconds m_stalling_since{0us};
450 std::list<QueuedBlock> vBlocksInFlight;
452 std::chrono::microseconds m_downloading_since{0us};
454 bool fPreferredDownload{
false};
456 bool m_requested_hb_cmpctblocks{
false};
458 bool m_provides_cmpctblocks{
false};
484 struct ChainSyncTimeoutState {
486 std::chrono::seconds m_timeout{0
s};
490 bool m_sent_getheaders{
false};
492 bool m_protect{
false};
495 ChainSyncTimeoutState m_chain_sync;
498 int64_t m_last_block_announcement{0};
527 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
544 void SetBestBlock(
int height,
std::chrono::seconds time)
override
546 m_best_height = height;
547 m_best_block_time = time;
555 const std::atomic<bool>& interruptMsgProc)
556 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
568 void ReattemptPrivateBroadcast(
CScheduler& scheduler);
583 void Misbehaving(Peer& peer, const
std::
string& message);
594 bool via_compact_block, const
std::
string& message = "")
603 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
617 bool first_time_failure)
642 bool ProcessOrphanTx(Peer& peer)
652 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
654 bool via_compact_block)
658 bool CheckHeadersPoW(const
std::vector<
CBlockHeader>& headers, Peer& peer);
666 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
685 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
699 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
714 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
716 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
723 template <
typename... Args>
724 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
728 template <
typename... Args>
729 void MakeAndPushFeature(
CNode&
node, std::string_view feature_id, Args&&...
args)
const
732 std::vector<unsigned char> feature_data;
739 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
788 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
791 std::atomic<int> m_best_height{-1};
793 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
801 const Options m_opts;
803 bool RejectIncomingTxs(
const CNode& peer)
const;
811 mutable Mutex m_peer_mutex;
818 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
828 uint32_t GetFetchFlags(
const Peer& peer)
const;
830 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
847 std::atomic<int> m_wtxid_relay_peers{0};
865 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
866 std::chrono::seconds average_interval,
871 Mutex m_most_recent_block_mutex;
872 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
873 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
875 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
879 Mutex m_headers_presync_mutex;
887 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
889 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
893 std::atomic_bool m_headers_presync_should_signal{
false};
963 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
969 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
974 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
1007 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
1009 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1021 int64_t ApproximateBestBlockDepth() const;
1031 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1049 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1051 const
uint256& stop_hash, uint32_t max_height_diff,
1098 void ProcessAddrs(
std::string_view msg_type,
CNode& pfrom, Peer& peer,
std::vector<
CAddress>&& vAddr, const
std::atomic<
bool>& interruptMsgProc)
1104 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1110const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const
1112 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1113 if (it == m_node_states.end())
1120 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1128static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1133void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1135 assert(peer.m_addr_known);
1136 peer.m_addr_known->insert(addr.
GetKey());
1139void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1144 assert(peer.m_addr_known);
1145 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1147 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1149 peer.m_addrs_to_send.push_back(addr);
1154static void AddKnownTx(Peer& peer,
const uint256& hash)
1156 auto tx_relay = peer.GetTxRelay();
1157 if (!tx_relay)
return;
1159 LOCK(tx_relay->m_tx_inventory_mutex);
1160 tx_relay->m_tx_inventory_known_filter.insert(hash);
1164static bool CanServeBlocks(
const Peer& peer)
1171static bool IsLimitedPeer(
const Peer& peer)
1178static bool CanServeWitnesses(
const Peer& peer)
1183std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1184 std::chrono::seconds average_interval,
1185 uint64_t network_key)
1187 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1188 auto& timer{it->second};
1190 timer = now + m_rng.rand_exp_duration(average_interval);
1195bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1197 return mapBlocksInFlight.contains(hash);
1200bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1202 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1203 auto [nodeid, block_it] = range.first->second;
1204 PeerRef peer{GetPeerRef(nodeid)};
1205 if (peer && !peer->m_is_inbound)
return true;
1211void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1213 auto range = mapBlocksInFlight.equal_range(hash);
1214 if (range.first == range.second) {
1222 while (range.first != range.second) {
1223 const auto& [node_id, list_it]{range.first->second};
1225 if (from_peer && *from_peer != node_id) {
1232 if (state.vBlocksInFlight.begin() == list_it) {
1234 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1236 state.vBlocksInFlight.erase(list_it);
1238 if (state.vBlocksInFlight.empty()) {
1240 m_peers_downloading_from--;
1242 state.m_stalling_since = 0us;
1244 range.first = mapBlocksInFlight.erase(range.first);
1248bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1252 CNodeState *state =
State(nodeid);
1253 assert(state !=
nullptr);
1258 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1259 if (range.first->second.first == nodeid) {
1261 *pit = &range.first->second.second;
1268 RemoveBlockRequest(hash, nodeid);
1270 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1271 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1272 if (state->vBlocksInFlight.size() == 1) {
1274 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1275 m_peers_downloading_from++;
1277 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1279 *pit = &itInFlight->second.second;
1284void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1291 if (m_opts.ignore_incoming_txs)
return;
1293 CNodeState* nodestate =
State(nodeid);
1294 PeerRef peer{GetPeerRef(nodeid)};
1295 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1300 int num_outbound_hb_peers = 0;
1301 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1302 if (*it == nodeid) {
1303 lNodesAnnouncingHeaderAndIDs.erase(it);
1304 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1307 PeerRef peer_ref{GetPeerRef(*it)};
1308 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1310 if (peer && peer->m_is_inbound) {
1313 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1314 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1315 if (remove_peer && !remove_peer->m_is_inbound) {
1318 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1327 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1330 if (nodeid_was_appended && lNodesAnnouncingHeaderAndIDs.size() > 3) {
1333 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop) {
1336 pnodeStop->m_bip152_highbandwidth_to =
false;
1339 lNodesAnnouncingHeaderAndIDs.pop_front();
1343bool PeerManagerImpl::TipMayBeStale()
1347 if (m_last_tip_update.load() == 0
s) {
1348 m_last_tip_update = GetTime<std::chrono::seconds>();
1350 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1353int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1358bool PeerManagerImpl::CanDirectFetch()
1365 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1367 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1372void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1373 CNodeState *state =
State(nodeid);
1374 assert(state !=
nullptr);
1376 if (!state->hashLastUnknownBlock.IsNull()) {
1379 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1380 state->pindexBestKnownBlock = pindex;
1382 state->hashLastUnknownBlock.SetNull();
1387void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1388 CNodeState *state =
State(nodeid);
1389 assert(state !=
nullptr);
1391 ProcessBlockAvailability(nodeid);
1396 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1397 state->pindexBestKnownBlock = pindex;
1401 state->hashLastUnknownBlock = hash;
1406void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1411 vBlocks.reserve(vBlocks.size() +
count);
1412 CNodeState *state =
State(peer.m_id);
1413 assert(state !=
nullptr);
1416 ProcessBlockAvailability(peer.m_id);
1418 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1429 state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1430 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1439 if (state->pindexLastCommonBlock ==
nullptr ||
1440 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1441 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1442 state->pindexLastCommonBlock = fork_point;
1444 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1447 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1453 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1456void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1461 if (vBlocks.size() >=
count) {
1465 vBlocks.reserve(
count);
1468 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1485void 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)
1487 std::vector<const CBlockIndex*> vToFetch;
1488 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1489 bool is_limited_peer = IsLimitedPeer(peer);
1491 while (pindexWalk->
nHeight < nMaxHeight) {
1495 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1496 vToFetch.resize(nToFetch);
1497 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1498 vToFetch[nToFetch - 1] = pindexWalk;
1499 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1500 vToFetch[i - 1] = vToFetch[i]->
pprev;
1520 state->pindexLastCommonBlock = pindex;
1527 if (waitingfor == -1) {
1529 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1535 if (pindex->
nHeight > nWindowEnd) {
1537 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1539 if (nodeStaller) *nodeStaller = waitingfor;
1549 vBlocks.push_back(pindex);
1550 if (vBlocks.size() ==
count) {
1559void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1561 uint64_t my_services;
1563 uint64_t your_services;
1565 std::string my_user_agent;
1573 my_user_agent =
"/pynode:0.0.1/";
1575 my_tx_relay =
false;
1578 my_services = peer.m_our_services;
1579 my_time = TicksSinceEpoch<std::chrono::seconds>(
NodeClock::now());
1583 my_height = m_best_height;
1584 my_tx_relay = !RejectIncomingTxs(pnode);
1603 BCLog::NET,
"send version message: version=%d, blocks=%d%s, txrelay=%d, peer=%d\n",
1606 my_tx_relay, pnode.
GetId());
1609void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1613 if (state) state->m_last_block_announcement = time_in_seconds;
1621 m_node_states.try_emplace(m_node_states.end(), nodeid);
1623 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1629 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1632 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1636void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1640 for (
const auto& txid : unbroadcast_txids) {
1643 if (tx !=
nullptr) {
1644 InitiateTxBroadcastToAll(txid, tx->GetWitnessHash());
1653 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1656void PeerManagerImpl::ReattemptPrivateBroadcast(
CScheduler& scheduler)
1660 size_t num_for_rebroadcast{0};
1661 const auto stale_txs = m_tx_for_private_broadcast.
GetStale();
1662 if (!stale_txs.empty()) {
1664 for (
const auto& stale_tx : stale_txs) {
1668 "Reattempting broadcast of stale txid=%s wtxid=%s",
1669 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString());
1670 ++num_for_rebroadcast;
1673 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString(),
1674 mempool_acceptable.m_state.ToString());
1675 m_tx_for_private_broadcast.
Remove(stale_tx);
1684 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, delta);
1687void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1698 PeerRef peer = RemovePeer(nodeid);
1700 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1701 assert(m_wtxid_relay_peers >= 0);
1703 CNodeState *state =
State(nodeid);
1704 assert(state !=
nullptr);
1706 if (state->fSyncStarted)
1709 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1710 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1711 while (range.first != range.second) {
1712 auto [node_id, list_it] = range.first->second;
1713 if (node_id != nodeid) {
1716 range.first = mapBlocksInFlight.erase(range.first);
1721 LOCK(m_tx_download_mutex);
1722 m_txdownloadman.DisconnectedPeer(nodeid);
1724 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1725 m_num_preferred_download_peers -= state->fPreferredDownload;
1726 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1727 assert(m_peers_downloading_from >= 0);
1728 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1729 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1731 m_node_states.erase(nodeid);
1733 if (m_node_states.empty()) {
1735 assert(mapBlocksInFlight.empty());
1736 assert(m_num_preferred_download_peers == 0);
1737 assert(m_peers_downloading_from == 0);
1738 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1739 assert(m_wtxid_relay_peers == 0);
1740 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1743 if (
node.fSuccessfullyConnected &&
1744 !
node.IsBlockOnlyConn() && !
node.IsPrivateBroadcastConn() && !
node.IsInboundConn()) {
1752 LOCK(m_headers_presync_mutex);
1753 m_headers_presync_stats.erase(nodeid);
1755 if (
node.IsPrivateBroadcastConn() &&
1764bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1767 return !(GetDesirableServiceFlags(services) & (~services));
1781PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1784 auto it = m_peer_map.find(
id);
1785 return it != m_peer_map.end() ? it->second :
nullptr;
1788PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1792 auto it = m_peer_map.find(
id);
1793 if (it != m_peer_map.end()) {
1794 ret = std::move(it->second);
1795 m_peer_map.erase(it);
1800std::vector<PeerRef> PeerManagerImpl::GetAllPeers()
const
1802 std::vector<PeerRef> peers;
1804 peers.reserve(m_peer_map.size());
1805 for (
const auto& [
_, peer] : m_peer_map) {
1806 peers.push_back(peer);
1815 const CNodeState* state =
State(nodeid);
1816 if (state ==
nullptr)
1818 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1819 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1820 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1826 PeerRef peer = GetPeerRef(nodeid);
1827 if (peer ==
nullptr)
return false;
1835 NodeClock::duration ping_wait{0us};
1836 if ((0 != peer->m_ping_nonce_sent) && (peer->m_ping_start.load() >
NodeClock::epoch)) {
1840 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1843 LOCK(tx_relay->m_tx_inventory_mutex);
1845 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1857 LOCK(peer->m_headers_sync_mutex);
1858 if (peer->m_headers_sync) {
1867std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1869 LOCK(m_tx_download_mutex);
1870 return m_txdownloadman.GetOrphanTransactions();
1877 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1878 .private_broadcast = m_opts.private_broadcast,
1882std::vector<PrivateBroadcast::TxBroadcastInfo> PeerManagerImpl::GetPrivateBroadcastInfo()
const
1887std::vector<CTransactionRef> PeerManagerImpl::AbortPrivateBroadcast(
const uint256&
id)
1890 std::vector<CTransactionRef> removed_txs;
1892 size_t connections_cancelled{0};
1893 for (
const auto& tx_info : snapshot) {
1895 if (tx->GetHash().ToUint256() !=
id && tx->GetWitnessHash().ToUint256() !=
id)
continue;
1896 if (
const auto peer_acks{m_tx_for_private_broadcast.
Remove(tx)}) {
1897 removed_txs.push_back(tx);
1908void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1910 if (m_opts.max_extra_txs <= 0)
1912 if (!vExtraTxnForCompact.size())
1913 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1914 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1915 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1918void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1920 LOCK(peer.m_misbehavior_mutex);
1922 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1923 peer.m_should_discourage =
true;
1932 bool via_compact_block,
const std::string& message)
1934 PeerRef peer{GetPeerRef(nodeid)};
1945 if (!via_compact_block) {
1946 if (peer) Misbehaving(*peer, message);
1954 if (peer && !via_compact_block && !peer->m_is_inbound) {
1955 if (peer) Misbehaving(*peer, message);
1962 if (peer) Misbehaving(*peer, message);
1966 if (peer) Misbehaving(*peer, message);
1971 if (message !=
"") {
1976bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex& block_index)
1990 PeerRef peer = GetPeerRef(peer_id);
1999 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
2002 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
2025 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
2031 : m_rng{opts.deterministic_rng},
2033 m_chainparams(chainman.GetParams()),
2037 m_chainman(chainman),
2039 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
2040 m_warnings{warnings},
2045 if (opts.reconcile_txs) {
2050void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2061 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2063 if (m_opts.private_broadcast) {
2064 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2068void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2076 LOCK(m_tx_download_mutex);
2080 m_txdownloadman.ActiveTipChange();
2090void PeerManagerImpl::BlockConnected(
2092 const std::shared_ptr<const CBlock>& pblock,
2097 m_last_tip_update = GetTime<std::chrono::seconds>();
2100 auto stalling_timeout = m_block_stalling_timeout.load();
2104 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2113 LOCK(m_tx_download_mutex);
2114 m_txdownloadman.BlockConnected(pblock);
2118void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2120 LOCK(m_tx_download_mutex);
2121 m_txdownloadman.BlockDisconnected();
2128void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2130 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2134 if (pindex->
nHeight <= m_highest_fast_announce)
2136 m_highest_fast_announce = pindex->
nHeight;
2140 uint256 hashBlock(pblock->GetHash());
2141 const std::shared_future<CSerializedNetMsg> lazy_ser{
2145 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2146 for (
const auto& tx : pblock->vtx) {
2147 most_recent_block_txs->emplace(tx->GetHash(), tx);
2148 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2151 LOCK(m_most_recent_block_mutex);
2152 m_most_recent_block_hash = hashBlock;
2153 m_most_recent_block = pblock;
2154 m_most_recent_compact_block = pcmpctblock;
2155 m_most_recent_block_txs = std::move(most_recent_block_txs);
2163 ProcessBlockAvailability(pnode->
GetId());
2167 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2169 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2170 hashBlock.ToString(), pnode->
GetId());
2173 PushMessage(*pnode, ser_cmpctblock.Copy());
2174 state.pindexBestHeaderSent = pindex;
2183void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2185 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2188 if (fInitialDownload)
return;
2191 std::vector<uint256> vHashes;
2193 while (pindexToAnnounce != pindexFork) {
2195 pindexToAnnounce = pindexToAnnounce->
pprev;
2205 for (
auto& it : m_peer_map) {
2206 Peer& peer = *it.second;
2207 LOCK(peer.m_block_inv_mutex);
2208 for (
const uint256& hash : vHashes | std::views::reverse) {
2209 peer.m_blocks_for_headers_relay.push_back(hash);
2221void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2225 const uint256 hash(block->GetHash());
2226 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2231 it != mapBlockSource.end() &&
2232 State(it->second.first)) {
2233 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2243 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2244 if (it != mapBlockSource.end()) {
2245 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2248 if (it != mapBlockSource.end())
2249 mapBlockSource.erase(it);
2257bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2262void PeerManagerImpl::SendPings()
2265 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2268void PeerManagerImpl::InitiateTxBroadcastToAll(
const Txid& txid,
const Wtxid& wtxid)
2270 for (
const PeerRef& peer_ref : GetAllPeers()) {
2271 if (!peer_ref)
continue;
2272 Peer& peer{*peer_ref};
2274 auto tx_relay = peer.GetTxRelay();
2275 if (!tx_relay)
continue;
2277 LOCK(tx_relay->m_tx_inventory_mutex);
2283 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2286 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2287 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2292void PeerManagerImpl::InitiateTxBroadcastPrivate(
const CTransactionRef& tx)
2294 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2295 if (m_tx_for_private_broadcast.
Add(tx)) {
2303void PeerManagerImpl::RelayAddress(
NodeId originator,
2319 const auto current_time{GetTime<std::chrono::seconds>()};
2327 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2329 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2330 assert(nRelayNodes <= best.size());
2334 for (
auto& [
id, peer] : m_peer_map) {
2335 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2337 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2338 if (hashKey > best[i].first) {
2339 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2340 best[i] = std::make_pair(hashKey, peer.get());
2347 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2348 PushAddress(*best[i].second, addr);
2352void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2354 std::shared_ptr<const CBlock> a_recent_block;
2355 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2357 LOCK(m_most_recent_block_mutex);
2358 a_recent_block = m_most_recent_block;
2359 a_recent_compact_block = m_most_recent_compact_block;
2362 bool need_activate_chain =
false;
2374 need_activate_chain =
true;
2378 if (need_activate_chain) {
2380 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2387 bool can_direct_fetch{
false};
2395 if (!BlockRequestAllowed(*pindex)) {
2396 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2423 can_direct_fetch = CanDirectFetch();
2427 std::shared_ptr<const CBlock> pblock;
2428 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2429 pblock = a_recent_block;
2447 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2457 pblock = pblockRead;
2465 bool sendMerkleBlock =
false;
2467 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2468 LOCK(tx_relay->m_bloom_filter_mutex);
2469 if (tx_relay->m_bloom_filter) {
2470 sendMerkleBlock =
true;
2471 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2474 if (sendMerkleBlock) {
2482 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2493 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2506 LOCK(peer.m_block_inv_mutex);
2508 if (inv.
hash == peer.m_continuation_block) {
2512 std::vector<CInv> vInv;
2513 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2515 peer.m_continuation_block.SetNull();
2523 auto txinfo{std::visit(
2524 [&](
const auto&
id) {
2525 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2529 return std::move(txinfo.tx);
2534 LOCK(m_most_recent_block_mutex);
2535 if (m_most_recent_block_txs !=
nullptr) {
2536 auto it = m_most_recent_block_txs->find(gtxid);
2537 if (it != m_most_recent_block_txs->end())
return it->second;
2544void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2548 auto tx_relay = peer.GetTxRelay();
2550 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2551 std::vector<CInv> vNotFound;
2556 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2557 if (interruptMsgProc)
return;
2562 const CInv &inv = *it++;
2564 if (tx_relay ==
nullptr) {
2570 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2573 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2576 vNotFound.push_back(inv);
2582 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2583 const CInv &inv = *it++;
2585 ProcessGetBlockData(pfrom, peer, inv);
2594 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2596 if (!vNotFound.empty()) {
2615uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2617 uint32_t nFetchFlags = 0;
2618 if (CanServeWitnesses(peer)) {
2627 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2629 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2636 uint32_t tx_requested_size{0};
2637 for (
const auto& tx : resp.txn) tx_requested_size += tx->ComputeTotalSize();
2643bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2647 Misbehaving(peer,
"header with invalid proof of work");
2652 if (!CheckHeadersAreContinuous(headers)) {
2653 Misbehaving(peer,
"non-continuous headers sequence");
2678void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2679 const std::vector<CBlockHeader>& headers)
2683 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2684 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2686 headers[0].hashPrevBlock.ToString(),
2687 best_header->nHeight,
2697bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2701 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2704 hashLastBlock = header.GetHash();
2709bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2711 if (peer.m_headers_sync) {
2712 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2714 if (result.success) peer.m_last_getheaders_timestamp = {};
2715 if (result.request_more) {
2716 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2718 Assume(!locator.vHave.empty());
2721 if (!locator.vHave.empty()) {
2724 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2727 locator.vHave.front().ToString(), pfrom.
GetId());
2732 peer.m_headers_sync.reset(
nullptr);
2737 LOCK(m_headers_presync_mutex);
2738 m_headers_presync_stats.erase(pfrom.
GetId());
2741 HeadersPresyncStats stats;
2742 stats.first = peer.m_headers_sync->GetPresyncWork();
2744 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2745 peer.m_headers_sync->GetPresyncTime()};
2749 LOCK(m_headers_presync_mutex);
2750 m_headers_presync_stats[pfrom.
GetId()] = stats;
2751 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2752 bool best_updated =
false;
2753 if (best_it == m_headers_presync_stats.end()) {
2757 const HeadersPresyncStats* stat_best{
nullptr};
2758 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2759 if (!stat_best || stat > *stat_best) {
2764 m_headers_presync_bestpeer = peer_best;
2765 best_updated = (peer_best == pfrom.
GetId());
2766 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2768 m_headers_presync_bestpeer = pfrom.
GetId();
2769 best_updated =
true;
2771 if (best_updated && stats.second.has_value()) {
2773 m_headers_presync_should_signal =
true;
2777 if (result.success) {
2780 headers.swap(result.pow_validated_headers);
2783 return result.success;
2791bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
2798 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2802 if (total_work < minimum_chain_work) {
2806 if (headers.size() == m_opts.max_headers_result) {
2816 LOCK(peer.m_headers_sync_mutex);
2818 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2823 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2837bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2839 if (header ==
nullptr) {
2841 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2849bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2857 peer.m_last_getheaders_timestamp = current_time;
2868void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2871 CNodeState *nodestate =
State(pfrom.
GetId());
2874 std::vector<const CBlockIndex*> vToFetch;
2882 vToFetch.push_back(pindexWalk);
2884 pindexWalk = pindexWalk->
pprev;
2896 std::vector<CInv> vGetData;
2898 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2903 uint32_t nFetchFlags = GetFetchFlags(peer);
2905 BlockRequested(pfrom.
GetId(), *pindex);
2909 if (vGetData.size() > 1) {
2914 if (vGetData.size() > 0) {
2915 if (!m_opts.ignore_incoming_txs &&
2916 nodestate->m_provides_cmpctblocks &&
2917 vGetData.size() == 1 &&
2918 mapBlocksInFlight.size() == 1 &&
2934void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2935 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2938 CNodeState *nodestate =
State(pfrom.
GetId());
2947 nodestate->m_last_block_announcement =
GetTime();
2955 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2977 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) {
2979 nodestate->m_chain_sync.m_protect =
true;
2980 ++m_outbound_peers_with_protect_from_disconnect;
2985void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2986 std::vector<CBlockHeader>&& headers,
2987 bool via_compact_block)
2989 size_t nCount = headers.size();
2996 LOCK(peer.m_headers_sync_mutex);
2997 if (peer.m_headers_sync) {
2998 peer.m_headers_sync.reset(
nullptr);
2999 LOCK(m_headers_presync_mutex);
3000 m_headers_presync_stats.erase(pfrom.
GetId());
3004 peer.m_last_getheaders_timestamp = {};
3012 if (!CheckHeadersPoW(headers, peer)) {
3027 bool already_validated_work =
false;
3030 bool have_headers_sync =
false;
3032 LOCK(peer.m_headers_sync_mutex);
3034 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3046 if (headers.empty()) {
3050 have_headers_sync = !!peer.m_headers_sync;
3055 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3057 if (!headers_connect_blockindex) {
3061 HandleUnconnectingHeaders(pfrom, peer, headers);
3068 peer.m_last_getheaders_timestamp = {};
3078 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3085 already_validated_work =
true;
3091 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3092 *chain_start_header, headers)) {
3104 bool received_new_header{last_received_header ==
nullptr};
3110 state, &pindexLast)};
3116 "If this happens with all peers, consider database corruption (that -reindex may fix) "
3117 "or a potential consensus incompatibility.",
3120 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3126 if (processed && received_new_header) {
3127 LogBlockHeader(*pindexLast, pfrom,
false);
3131 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3133 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3138 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3141 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3147 bool first_time_failure)
3153 PeerRef peer{GetPeerRef(nodeid)};
3156 ptx->GetHash().ToString(),
3157 ptx->GetWitnessHash().ToString(),
3161 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3164 AddToCompactExtraTransactions(ptx);
3166 for (
const Txid& parent_txid : unique_parents) {
3167 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3170 return package_to_validate;
3173void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3179 m_txdownloadman.MempoolAcceptedTx(tx);
3183 tx->GetHash().ToString(),
3184 tx->GetWitnessHash().ToString(),
3187 InitiateTxBroadcastToAll(tx->GetHash(), tx->GetWitnessHash());
3190 AddToCompactExtraTransactions(removedTx);
3200 const auto&
package = package_to_validate.m_txns;
3201 const auto& senders = package_to_validate.
m_senders;
3204 m_txdownloadman.MempoolRejectedPackage(package);
3207 if (!
Assume(package.size() == 2))
return;
3211 auto package_iter = package.rbegin();
3212 auto senders_iter = senders.rbegin();
3213 while (package_iter != package.rend()) {
3214 const auto& tx = *package_iter;
3215 const NodeId nodeid = *senders_iter;
3216 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3220 const auto& tx_result = it_result->second;
3221 switch (tx_result.m_result_type) {
3224 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3234 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3252bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3259 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3262 const Txid& orphanHash = porphanTx->GetHash();
3263 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3280 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3289bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3291 const uint256& stop_hash, uint32_t max_height_diff,
3295 const bool supported_filter_type =
3298 if (!supported_filter_type) {
3300 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg());
3301 node.fDisconnect =
true;
3310 if (!stop_index || !BlockRequestAllowed(*stop_index)) {
3313 node.fDisconnect =
true;
3318 uint32_t stop_height = stop_index->
nHeight;
3319 if (start_height > stop_height) {
3321 "start height %d and stop height %d, %s",
3322 start_height, stop_height,
node.DisconnectMsg());
3323 node.fDisconnect =
true;
3326 if (stop_height - start_height >= max_height_diff) {
3328 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg());
3329 node.fDisconnect =
true;
3334 if (!filter_index) {
3344 uint8_t filter_type_ser;
3345 uint32_t start_height;
3348 vRecv >> filter_type_ser >> start_height >> stop_hash;
3354 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3359 std::vector<BlockFilter> filters;
3361 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3366 for (
const auto& filter : filters) {
3373 uint8_t filter_type_ser;
3374 uint32_t start_height;
3377 vRecv >> filter_type_ser >> start_height >> stop_hash;
3383 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3389 if (start_height > 0) {
3391 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3393 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3399 std::vector<uint256> filter_hashes;
3401 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3415 uint8_t filter_type_ser;
3418 vRecv >> filter_type_ser >> stop_hash;
3424 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3425 std::numeric_limits<uint32_t>::max(),
3426 stop_index, filter_index)) {
3434 for (
int i = headers.size() - 1; i >= 0; i--) {
3439 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3453 bool new_block{
false};
3454 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3456 node.m_last_block_time = GetTime<std::chrono::seconds>();
3461 RemoveBlockRequest(block->GetHash(), std::nullopt);
3464 mapBlockSource.erase(block->GetHash());
3468void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3470 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3471 bool fBlockRead{
false};
3475 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3476 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3477 bool requested_block_from_this_peer{
false};
3480 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3482 while (range_flight.first != range_flight.second) {
3483 auto [node_id, block_it] = range_flight.first->second;
3484 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3485 requested_block_from_this_peer =
true;
3488 range_flight.first++;
3491 if (!requested_block_from_this_peer) {
3503 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3514 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3517 if (first_in_flight) {
3522 std::vector<CInv> invs;
3527 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3540 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3555void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3567 "Saw new %sheader hash=%s height=%d %s",
3568 via_compact_block ?
"cmpctblock " :
"",
3580void PeerManagerImpl::PushPrivateBroadcastTx(
CNode&
node)
3587 node.fDisconnect =
true;
3593 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3599void PeerManagerImpl::ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3601 const std::atomic<bool>& interruptMsgProc)
3616 uint64_t nNonce = 1;
3619 std::string cleanSubVer;
3620 int starting_height = -1;
3623 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3638 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s",
3640 GetDesirableServiceFlags(nServices),
3653 if (!vRecv.
empty()) {
3661 if (!vRecv.
empty()) {
3662 std::string strSubVer;
3666 if (!vRecv.
empty()) {
3667 vRecv >> starting_height;
3687 PushNodeVersion(pfrom, peer);
3691 const int greatest_common_version = std::min(nVersion, pfrom.
AdvertisedVersion());
3696 peer.m_their_services = nServices;
3700 pfrom.cleanSubVer = cleanSubVer;
3711 (fRelay || (peer.m_our_services &
NODE_BLOOM))) {
3712 auto*
const tx_relay = peer.SetTxRelay();
3714 LOCK(tx_relay->m_bloom_filter_mutex);
3715 tx_relay->m_relay_txs = fRelay;
3721 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, %s%s",
3722 cleanSubVer.empty() ?
"<no user agent>" : cleanSubVer, pfrom.
nVersion,
3724 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3742 if (greatest_common_version >= 70016) {
3757 const auto* tx_relay = peer.GetTxRelay();
3758 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3760 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3778 m_num_preferred_download_peers += state->fPreferredDownload;
3784 bool send_getaddr{
false};
3786 send_getaddr = SetupAddressRelay(pfrom, peer);
3796 peer.m_getaddr_sent =
true;
3820 peer.m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3824 m_outbound_time_offsets.Add(peer.m_time_offset);
3825 m_outbound_time_offsets.WarnIfOutOfSync();
3829 if (greatest_common_version <= 70012) {
3830 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3831 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3854 auto new_peer_msg = [&]() {
3856 return strprintf(
"New %s peer connected: transport: %s, version: %d, %s%s",
3860 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3868 LogInfo(
"%s", new_peer_msg());
3871 if (
auto tx_relay = peer.GetTxRelay()) {
3880 tx_relay->m_tx_inventory_mutex,
3881 return tx_relay->m_tx_inventory_to_send.empty() &&
3882 tx_relay->m_next_inv_send_time == 0
s));
3892 PushPrivateBroadcastTx(pfrom);
3905 if (m_txreconciliation) {
3906 if (!peer.m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3910 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3916 const CNodeState* state =
State(pfrom.
GetId());
3918 .m_preferred = state->fPreferredDownload,
3919 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3920 .m_wtxid_relay = peer.m_wtxid_relay,
3929 peer.m_prefers_headers =
true;
3934 bool sendcmpct_hb{
false};
3935 uint64_t sendcmpct_version{0};
3936 vRecv >> sendcmpct_hb >> sendcmpct_version;
3942 CNodeState* nodestate =
State(pfrom.
GetId());
3943 nodestate->m_provides_cmpctblocks =
true;
3944 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3961 if (!peer.m_wtxid_relay) {
3962 peer.m_wtxid_relay =
true;
3963 m_wtxid_relay_peers++;
3982 peer.m_wants_addrv2 =
true;
3999 std::string feature_id;
4003 std::vector<unsigned char> feature_data_vec;
4006 }
catch (
const std::exception&) {
4009 if (feature_id.size() < 4 || !vRecv.
empty()) {
4029 if (!m_txreconciliation) {
4030 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
4041 if (RejectIncomingTxs(pfrom)) {
4050 const auto* tx_relay = peer.GetTxRelay();
4051 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
4057 uint32_t peer_txreconcl_version;
4058 uint64_t remote_salt;
4059 vRecv >> peer_txreconcl_version >> remote_salt;
4062 peer_txreconcl_version, remote_salt);
4094 const auto ser_params{
4102 std::vector<CAddress> vAddr;
4103 vRecv >> ser_params(vAddr);
4104 ProcessAddrs(msg_type, pfrom, peer, std::move(vAddr), interruptMsgProc);
4109 std::vector<CInv> vInv;
4113 Misbehaving(peer,
strprintf(
"inv message size = %u", vInv.size()));
4117 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4121 const auto current_time{GetTime<std::chrono::microseconds>()};
4124 for (
CInv& inv : vInv) {
4125 if (interruptMsgProc)
return;
4130 if (peer.m_wtxid_relay) {
4137 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4140 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4148 best_block = &inv.
hash;
4151 if (reject_tx_invs) {
4157 AddKnownTx(peer, inv.
hash);
4160 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4168 if (best_block !=
nullptr) {
4180 if (state.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4181 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer)) {
4183 m_chainman.m_best_header->nHeight, best_block->ToString(),
4186 if (!state.fSyncStarted) {
4187 peer.m_inv_triggered_getheaders_before_sync =
true;
4191 m_last_block_inv_triggering_headers_sync = *best_block;
4200 std::vector<CInv> vInv;
4204 Misbehaving(peer,
strprintf(
"getdata message size = %u", vInv.size()));
4210 if (vInv.size() > 0) {
4215 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4216 if (!pushed_tx_opt) {
4227 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4231 peer.m_ping_queued =
true;
4242 LOCK(peer.m_getdata_requests_mutex);
4243 peer.m_getdata_requests.insert(peer.m_getdata_requests.end(), vInv.begin(), vInv.end());
4244 ProcessGetData(pfrom, peer, interruptMsgProc);
4253 vRecv >> locator >> hashStop;
4269 std::shared_ptr<const CBlock> a_recent_block;
4271 LOCK(m_most_recent_block_mutex);
4272 a_recent_block = m_most_recent_block;
4275 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4290 for (; pindex; pindex = m_chainman.
ActiveChain().Next(*pindex))
4305 if (--nLimit <= 0) {
4309 WITH_LOCK(peer.m_block_inv_mutex, {peer.m_continuation_block = pindex->GetBlockHash();});
4321 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4325 std::shared_ptr<const CBlock> recent_block;
4327 LOCK(m_most_recent_block_mutex);
4328 if (m_most_recent_block_hash == req.
blockhash)
4329 recent_block = m_most_recent_block;
4333 SendBlockTransactions(pfrom, peer, *recent_block, req);
4352 if (!block_pos.IsNull()) {
4359 SendBlockTransactions(pfrom, peer, block, req);
4372 WITH_LOCK(peer.m_getdata_requests_mutex, peer.m_getdata_requests.push_back(inv));
4380 vRecv >> locator >> hashStop;
4398 if (m_chainman.
ActiveTip() ==
nullptr ||
4400 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4407 CNodeState *nodestate =
State(pfrom.
GetId());
4416 if (!BlockRequestAllowed(*pindex)) {
4417 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4430 std::vector<CBlock> vHeaders;
4431 int nLimit = m_opts.max_headers_result;
4433 for (; pindex; pindex = m_chainman.
ActiveChain().Next(*pindex))
4436 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4451 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4457 if (RejectIncomingTxs(pfrom)) {
4471 const Txid& txid = ptx->GetHash();
4472 const Wtxid& wtxid = ptx->GetWitnessHash();
4475 AddKnownTx(peer, hash);
4477 if (
const auto num_broadcasted{m_tx_for_private_broadcast.
Remove(ptx)}) {
4479 "network from %s; stopping private broadcast attempts",
4490 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4491 if (!should_validate) {
4496 if (!m_mempool.
exists(txid)) {
4497 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4500 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4502 InitiateTxBroadcastToAll(txid, wtxid);
4506 if (package_to_validate) {
4509 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4510 ProcessPackageResult(package_to_validate.value(), package_result);
4516 Assume(!package_to_validate.has_value());
4526 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4529 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4530 ProcessPackageResult(package_to_validate.value(), package_result);
4546 vRecv >> cmpctblock;
4548 bool received_new_header =
false;
4558 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer);
4568 received_new_header =
true;
4576 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4583 if (received_new_header) {
4584 LogBlockHeader(*pindex, pfrom,
true);
4587 bool fProcessBLOCKTXN =
false;
4591 bool fRevertToHeaderProcessing =
false;
4595 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4596 bool fBlockReconstructed =
false;
4602 CNodeState *nodestate =
State(pfrom.
GetId());
4607 nodestate->m_last_block_announcement =
GetTime();
4613 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4614 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4615 bool requested_block_from_this_peer{
false};
4618 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4620 while (range_flight.first != range_flight.second) {
4621 if (range_flight.first->second.first == pfrom.
GetId()) {
4622 requested_block_from_this_peer =
true;
4625 range_flight.first++;
4630 if (requested_block_from_this_peer) {
4633 std::vector<CInv> vInv(1);
4641 if (!already_in_flight && !CanDirectFetch()) {
4649 requested_block_from_this_peer) {
4650 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4651 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4652 if (!(*queuedBlockIt)->partialBlock)
4665 Misbehaving(peer,
"invalid compact block");
4668 if (first_in_flight) {
4670 std::vector<CInv> vInv(1);
4681 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4686 fProcessBLOCKTXN =
true;
4687 }
else if (first_in_flight) {
4694 IsBlockRequestedFromOutbound(blockhash) ||
4713 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4718 std::vector<CTransactionRef> dummy;
4720 status = tempBlock.FillBlock(*pblock, dummy,
4723 fBlockReconstructed =
true;
4727 if (requested_block_from_this_peer) {
4730 std::vector<CInv> vInv(1);
4736 fRevertToHeaderProcessing =
true;
4741 if (fProcessBLOCKTXN) {
4744 return ProcessCompactBlockTxns(pfrom, peer, txn);
4747 if (fRevertToHeaderProcessing) {
4753 return ProcessHeadersMessage(pfrom, peer, {cmpctblock.
header},
true);
4756 if (fBlockReconstructed) {
4761 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4779 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4796 return ProcessCompactBlockTxns(pfrom, peer, resp);
4807 std::vector<CBlockHeader> headers;
4811 if (nCount > m_opts.max_headers_result) {
4812 Misbehaving(peer,
strprintf(
"headers message size = %u", nCount));
4815 headers.resize(nCount);
4816 for (
unsigned int n = 0; n < nCount; n++) {
4817 vRecv >> headers[n];
4821 ProcessHeadersMessage(pfrom, peer, std::move(headers),
false);
4825 if (m_headers_presync_should_signal.exchange(
false)) {
4826 HeadersPresyncStats stats;
4828 LOCK(m_headers_presync_mutex);
4829 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4830 if (it != m_headers_presync_stats.end()) stats = it->second;
4848 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4859 Misbehaving(peer,
"mutated block");
4864 bool forceProcessing =
false;
4865 const uint256 hash(pblock->GetHash());
4866 bool min_pow_checked =
false;
4871 forceProcessing = IsBlockRequested(hash);
4872 RemoveBlockRequest(hash, pfrom.
GetId());
4876 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4880 min_pow_checked =
true;
4883 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4900 Assume(SetupAddressRelay(pfrom, peer));
4904 if (peer.m_getaddr_recvd) {
4908 peer.m_getaddr_recvd =
true;
4910 peer.m_addrs_to_send.clear();
4911 std::vector<CAddress> vAddr;
4917 for (
const CAddress &addr : vAddr) {
4918 PushAddress(peer, addr);
4946 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4947 LOCK(tx_relay->m_tx_inventory_mutex);
4948 tx_relay->m_send_mempool =
true;
4974 ProcessPong(pfrom, peer, time_received, vRecv);
4990 Misbehaving(peer,
"too-large bloom filter");
4991 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4993 LOCK(tx_relay->m_bloom_filter_mutex);
4994 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4995 tx_relay->m_relay_txs =
true;
5009 std::vector<unsigned char> vData;
5017 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5018 LOCK(tx_relay->m_bloom_filter_mutex);
5019 if (tx_relay->m_bloom_filter) {
5020 tx_relay->m_bloom_filter->insert(vData);
5026 Misbehaving(peer,
"bad filteradd message");
5037 auto tx_relay = peer.GetTxRelay();
5038 if (!tx_relay)
return;
5041 LOCK(tx_relay->m_bloom_filter_mutex);
5042 tx_relay->m_bloom_filter =
nullptr;
5043 tx_relay->m_relay_txs =
true;
5052 vRecv >> newFeeFilter;
5054 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5055 tx_relay->m_fee_filter_received = newFeeFilter;
5063 ProcessGetCFilters(pfrom, peer, vRecv);
5068 ProcessGetCFHeaders(pfrom, peer, vRecv);
5073 ProcessGetCFCheckPt(pfrom, peer, vRecv);
5078 std::vector<CInv> vInv;
5080 std::vector<GenTxid> tx_invs;
5082 for (
CInv &inv : vInv) {
5088 LOCK(m_tx_download_mutex);
5089 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5098bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5101 LOCK(peer.m_misbehavior_mutex);
5104 if (!peer.m_should_discourage)
return false;
5106 peer.m_should_discourage =
false;
5111 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5117 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5137bool PeerManagerImpl::ProcessMessages(
CNode&
node, std::atomic<bool>& interruptMsgProc)
5142 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5143 if (maybe_peer ==
nullptr)
return false;
5144 Peer& peer{*maybe_peer};
5148 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent)
return false;
5151 LOCK(peer.m_getdata_requests_mutex);
5152 if (!peer.m_getdata_requests.empty()) {
5153 ProcessGetData(
node, peer, interruptMsgProc);
5157 const bool processed_orphan = ProcessOrphanTx(peer);
5159 if (
node.fDisconnect)
5162 if (processed_orphan)
return true;
5167 LOCK(peer.m_getdata_requests_mutex);
5168 if (!peer.m_getdata_requests.empty())
return true;
5172 if (
node.fPauseSend)
return false;
5174 auto poll_result{
node.PollMessage()};
5181 bool fMoreWork = poll_result->second;
5185 node.m_addr_name.c_str(),
5186 node.ConnectionTypeAsString().c_str(),
5192 if (m_opts.capture_messages) {
5197 ProcessMessage(peer,
node,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5198 if (interruptMsgProc)
return false;
5200 LOCK(peer.m_getdata_requests_mutex);
5201 if (!peer.m_getdata_requests.empty()) fMoreWork =
true;
5208 LOCK(m_tx_download_mutex);
5209 if (m_txdownloadman.HaveMoreWork(peer.m_id)) fMoreWork =
true;
5210 }
catch (
const std::exception& e) {
5219void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5232 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5234 if (state.m_chain_sync.m_timeout != 0
s) {
5235 state.m_chain_sync.m_timeout = 0
s;
5236 state.m_chain_sync.m_work_header =
nullptr;
5237 state.m_chain_sync.m_sent_getheaders =
false;
5239 }
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)) {
5247 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5248 state.m_chain_sync.m_sent_getheaders =
false;
5249 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5253 if (state.m_chain_sync.m_sent_getheaders) {
5255 LogInfo(
"Outbound peer has old chain, best known block = %s, %s", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg());
5258 assert(state.m_chain_sync.m_work_header);
5263 MaybeSendGetHeaders(pto,
5264 GetLocator(state.m_chain_sync.m_work_header->pprev),
5266 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());
5267 state.m_chain_sync.m_sent_getheaders =
true;
5288 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5292 if (pnode->
GetId() > youngest_peer.first) {
5293 next_youngest_peer = youngest_peer;
5294 youngest_peer.first = pnode->GetId();
5295 youngest_peer.second = pnode->m_last_block_time;
5298 NodeId to_disconnect = youngest_peer.first;
5299 if (youngest_peer.second > next_youngest_peer.second) {
5302 to_disconnect = next_youngest_peer.first;
5311 CNodeState *node_state =
State(pnode->
GetId());
5312 if (node_state ==
nullptr ||
5315 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5319 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5320 pnode->
GetId(), TicksSinceEpoch<std::chrono::seconds>(pnode->
m_connected), node_state->vBlocksInFlight.size());
5335 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5338 AssertLockHeld(::cs_main);
5342 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5343 CNodeState *state = State(pnode->GetId());
5344 if (state == nullptr) return;
5346 if (state->m_chain_sync.m_protect) return;
5349 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5350 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5351 worst_peer = pnode->GetId();
5352 oldest_block_announcement = state->m_last_block_announcement;
5355 if (worst_peer != -1) {
5366 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5370 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5371 pnode->
GetId(), TicksSinceEpoch<std::chrono::seconds>(pnode->
m_connected), state.vBlocksInFlight.size());
5387void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5392 auto now{GetTime<std::chrono::seconds>()};
5394 EvictExtraOutboundPeers(current_time);
5396 if (now > m_stale_tip_check_time) {
5400 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5409 if (!m_initial_sync_finished && CanDirectFetch()) {
5411 m_initial_sync_finished =
true;
5418 peer.m_ping_nonce_sent &&
5428 bool pingSend =
false;
5430 if (peer.m_ping_queued) {
5435 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5444 }
while (
nonce == 0);
5445 peer.m_ping_queued =
false;
5446 peer.m_ping_start = now;
5448 peer.m_ping_nonce_sent =
nonce;
5452 peer.m_ping_nonce_sent = 0;
5458void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5461 if (!peer.m_addr_relay_enabled)
return;
5463 LOCK(peer.m_addr_send_times_mutex);
5466 peer.m_next_local_addr_send < current_time) {
5473 if (peer.m_next_local_addr_send != 0us) {
5474 peer.m_addr_known->reset();
5477 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5478 if (peer.m_next_local_addr_send == 0us) {
5482 if (IsAddrCompatible(peer, local_addr)) {
5483 std::vector<CAddress> self_announcement{local_addr};
5484 if (peer.m_wants_addrv2) {
5492 PushAddress(peer, local_addr);
5499 if (current_time <= peer.m_next_addr_send)
return;
5512 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5513 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5516 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5517 peer.m_addrs_to_send.end());
5520 if (peer.m_addrs_to_send.empty())
return;
5522 if (peer.m_wants_addrv2) {
5527 peer.m_addrs_to_send.clear();
5530 if (peer.m_addrs_to_send.capacity() > 40) {
5531 peer.m_addrs_to_send.shrink_to_fit();
5535void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5543 CNodeState &state = *
State(
node.GetId());
5544 if (state.pindexBestKnownBlock !=
nullptr &&
5551 peer.m_sent_sendheaders =
true;
5556void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5558 if (m_opts.ignore_incoming_txs)
return;
5574 if (peer.m_fee_filter_sent == MAX_FILTER) {
5577 peer.m_next_send_feefilter = 0us;
5580 if (current_time > peer.m_next_send_feefilter) {
5581 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5584 if (filterToSend != peer.m_fee_filter_sent) {
5586 peer.m_fee_filter_sent = filterToSend;
5593 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5599class CompareInvMempoolOrder
5603 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5605 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5614bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5627 const size_t nAvail{vRecv.
size()};
5628 bool bPingFinished =
false;
5629 std::string sProblem;
5631 if (nAvail >=
sizeof(
nonce)) {
5635 if (peer.m_ping_nonce_sent != 0) {
5636 if (
nonce == peer.m_ping_nonce_sent) {
5638 bPingFinished =
true;
5639 const auto ping_time = ping_end - peer.m_ping_start.load();
5640 if (ping_time.count() >= 0) {
5651 sProblem =
"Timing mishap";
5655 sProblem =
"Nonce mismatch";
5658 bPingFinished =
true;
5659 sProblem =
"Nonce zero";
5663 sProblem =
"Unsolicited pong without ping";
5667 bPingFinished =
true;
5668 sProblem =
"Short payload";
5671 if (!(sProblem.empty())) {
5675 peer.m_ping_nonce_sent,
5679 if (bPingFinished) {
5680 peer.m_ping_nonce_sent = 0;
5684bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5689 if (
node.IsBlockOnlyConn())
return false;
5691 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5695 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5701void PeerManagerImpl::ProcessAddrs(std::string_view msg_type,
CNode& pfrom, Peer& peer, std::vector<CAddress>&& vAddr,
const std::atomic<bool>& interruptMsgProc)
5706 if (!SetupAddressRelay(pfrom, peer)) {
5713 Misbehaving(peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
5718 std::vector<CAddress> vAddrOk;
5724 const auto time_diff{current_time - peer.m_addr_token_timestamp};
5728 peer.m_addr_token_timestamp = current_time;
5731 uint64_t num_proc = 0;
5732 uint64_t num_rate_limit = 0;
5733 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
5736 if (interruptMsgProc)
5740 if (peer.m_addr_token_bucket < 1.0) {
5746 peer.m_addr_token_bucket -= 1.0;
5755 addr.
nTime = std::chrono::time_point_cast<std::chrono::seconds>(current_time - 5 * 24h);
5757 AddAddressKnown(peer, addr);
5764 if (addr.
nTime > current_time - 10min && !peer.m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
5766 RelayAddress(pfrom.
GetId(), addr, reachable);
5770 vAddrOk.push_back(addr);
5773 peer.m_addr_processed += num_proc;
5774 peer.m_addr_rate_limited += num_rate_limit;
5775 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
5776 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
5778 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
5779 if (vAddr.size() < 1000) peer.m_getaddr_sent =
false;
5788bool PeerManagerImpl::SendMessages(
CNode&
node)
5793 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5794 if (!maybe_peer)
return false;
5795 Peer& peer{*maybe_peer};
5800 if (MaybeDiscourageAndDisconnect(
node, peer))
return true;
5803 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent) {
5804 PushNodeVersion(
node, peer);
5805 peer.m_outbound_version_message_sent =
true;
5809 if (!
node.fSuccessfullyConnected ||
node.fDisconnect)
5813 const auto current_time{GetTime<std::chrono::microseconds>()};
5818 if (
node.IsPrivateBroadcastConn()) {
5822 node.fDisconnect =
true;
5829 node.fDisconnect =
true;
5833 MaybeSendPing(
node, peer, now);
5836 if (
node.fDisconnect)
return true;
5838 MaybeSendAddr(
node, peer, current_time);
5840 MaybeSendSendHeaders(
node, peer);
5845 CNodeState &state = *
State(
node.GetId());
5848 if (m_chainman.m_best_header ==
nullptr) {
5855 bool sync_blocks_and_headers_from_peer =
false;
5856 if (state.fPreferredDownload) {
5857 sync_blocks_and_headers_from_peer =
true;
5858 }
else if (CanServeBlocks(peer) && !
node.IsAddrFetchConn()) {
5868 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5869 sync_blocks_and_headers_from_peer =
true;
5875 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5876 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5884 if (pindexStart->
pprev)
5885 pindexStart = pindexStart->
pprev;
5889 state.fSyncStarted =
true;
5913 LOCK(peer.m_block_inv_mutex);
5914 std::vector<CBlock> vHeaders;
5915 bool fRevertToInv = ((!peer.m_prefers_headers &&
5916 (!state.m_requested_hb_cmpctblocks || peer.m_blocks_for_headers_relay.size() > 1)) ||
5919 ProcessBlockAvailability(
node.GetId());
5921 if (!fRevertToInv) {
5922 bool fFoundStartingHeader =
false;
5926 for (
const uint256& hash : peer.m_blocks_for_headers_relay) {
5931 fRevertToInv =
true;
5934 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5946 fRevertToInv =
true;
5949 pBestIndex = pindex;
5950 if (fFoundStartingHeader) {
5953 }
else if (PeerHasHeader(&state, pindex)) {
5955 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5958 fFoundStartingHeader =
true;
5963 fRevertToInv =
true;
5968 if (!fRevertToInv && !vHeaders.empty()) {
5969 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5973 vHeaders.front().GetHash().ToString(),
node.GetId());
5975 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5977 LOCK(m_most_recent_block_mutex);
5978 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5982 if (cached_cmpctblock_msg.has_value()) {
5983 PushMessage(
node, std::move(cached_cmpctblock_msg.value()));
5991 state.pindexBestHeaderSent = pBestIndex;
5992 }
else if (peer.m_prefers_headers) {
5993 if (vHeaders.size() > 1) {
5996 vHeaders.front().GetHash().ToString(),
5997 vHeaders.back().GetHash().ToString(),
node.GetId());
6000 vHeaders.front().GetHash().ToString(),
node.GetId());
6003 state.pindexBestHeaderSent = pBestIndex;
6005 fRevertToInv =
true;
6011 if (!peer.m_blocks_for_headers_relay.empty()) {
6012 const uint256& hashToAnnounce = peer.m_blocks_for_headers_relay.back();
6025 if (!PeerHasHeader(&state, pindex)) {
6026 peer.m_blocks_for_inv_relay.push_back(hashToAnnounce);
6032 peer.m_blocks_for_headers_relay.clear();
6038 std::vector<CInv> vInv;
6040 LOCK(peer.m_block_inv_mutex);
6044 for (
const uint256& hash : peer.m_blocks_for_inv_relay) {
6051 peer.m_blocks_for_inv_relay.clear();
6054 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
6055 LOCK(tx_relay->m_tx_inventory_mutex);
6058 if (tx_relay->m_next_inv_send_time < current_time) {
6059 fSendTrickle =
true;
6060 if (
node.IsInboundConn()) {
6069 LOCK(tx_relay->m_bloom_filter_mutex);
6070 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
6074 if (fSendTrickle && tx_relay->m_send_mempool) {
6075 auto vtxinfo = m_mempool.
infoAll();
6076 tx_relay->m_send_mempool =
false;
6077 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6079 LOCK(tx_relay->m_bloom_filter_mutex);
6081 for (
const auto& txinfo : vtxinfo) {
6082 const Txid& txid{txinfo.tx->GetHash()};
6083 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
6084 const auto inv = peer.m_wtxid_relay ?
6087 tx_relay->m_tx_inventory_to_send.erase(wtxid);
6090 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6093 if (tx_relay->m_bloom_filter) {
6094 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6096 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6097 vInv.push_back(inv);
6108 std::vector<std::set<Wtxid>::iterator> vInvTx;
6109 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
6110 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
6111 vInvTx.push_back(it);
6113 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6116 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
6117 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6120 unsigned int nRelayedTransactions = 0;
6121 LOCK(tx_relay->m_bloom_filter_mutex);
6124 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
6126 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6127 std::set<Wtxid>::iterator it = vInvTx.back();
6131 tx_relay->m_tx_inventory_to_send.erase(it);
6133 auto txinfo = m_mempool.
info(wtxid);
6140 const auto inv = peer.m_wtxid_relay ?
6142 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
6144 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
6148 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6151 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6153 vInv.push_back(inv);
6154 nRelayedTransactions++;
6159 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6164 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6171 auto stalling_timeout = m_block_stalling_timeout.load();
6172 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6176 LogInfo(
"Peer is stalling block download, %s",
node.DisconnectMsg());
6177 node.fDisconnect =
true;
6181 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6191 if (state.vBlocksInFlight.size() > 0) {
6192 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6193 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6195 LogInfo(
"Timeout downloading block %s, %s", queuedBlock.pindex->GetBlockHash().ToString(),
node.DisconnectMsg());
6196 node.fDisconnect =
true;
6201 if (state.fSyncStarted && peer.m_headers_sync_timeout < std::chrono::microseconds::max()) {
6203 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6204 if (current_time > peer.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6211 LogInfo(
"Timeout downloading headers, %s",
node.DisconnectMsg());
6212 node.fDisconnect =
true;
6215 LogInfo(
"Timeout downloading headers from noban peer, not %s",
node.DisconnectMsg());
6221 state.fSyncStarted =
false;
6223 peer.m_headers_sync_timeout = 0us;
6229 peer.m_headers_sync_timeout = std::chrono::microseconds::max();
6235 ConsiderEviction(
node, peer, GetTime<std::chrono::seconds>());
6240 std::vector<CInv> vGetData;
6242 std::vector<const CBlockIndex*> vToDownload;
6244 auto get_inflight_budget = [&state]() {
6251 FindNextBlocksToDownload(peer, get_inflight_budget(), vToDownload, staller);
6252 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
6253 if (historical_blocks && !IsLimitedPeer(peer)) {
6257 TryDownloadingHistoricalBlocks(
6259 get_inflight_budget(),
6260 vToDownload, from_tip, historical_blocks->second);
6263 uint32_t nFetchFlags = GetFetchFlags(peer);
6265 BlockRequested(
node.GetId(), *pindex);
6269 if (state.vBlocksInFlight.empty() && staller != -1) {
6270 if (
State(staller)->m_stalling_since == 0us) {
6271 State(staller)->m_stalling_since = current_time;
6281 LOCK(m_tx_download_mutex);
6282 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(
node.GetId(), current_time)) {
6291 if (!vGetData.empty())
6294 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.
bool Contains(const CBlockIndex &index) const
Efficiently check whether a block is present in this chain.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex &index) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
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...
bool GetNetworkActive() const
bool GetTryNewOutboundPeer() const
class CConnman::PrivateBroadcast m_private_broadcast
bool ShouldRunInactivityChecks(const CNode &node, NodeClock::time_point now) const
Return true if we should disconnect the peer for failing an inactivity check.
std::vector< CAddress > GetAddresses(CNode &requestor, size_t max_addresses, size_t max_pct)
Return addresses from the per-requestor cache.
void SetTryNewOutboundPeer(bool flag)
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
void ForEachNode(const NodeFn &func) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return randomly selected addresses.
int GetExtraBlockRelayCount() const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
bool DisconnectNode(std::string_view node) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
Mutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
int GetExtraFullOutboundCount() const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
bool GetUseAddrmanOutgoing() const
bool CheckIncomingNonce(uint64_t nonce) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
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
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
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
const NodeClock::time_point m_connected
Unix epoch time at peer connection.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
std::atomic_bool fPauseSend
std::string DisconnectMsg() const
Helper function to log disconnects.
void PongReceived(NodeClock::duration ping_time)
A ping-pong round trip has completed successfully. Update latest and minimum ping durations.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
bool IsPrivateBroadcastConn() const
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
int AdvertisedVersion() const
Protocol version advertised in our VERSION message.
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
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)
CBlockFileInfo *GetBlockFileInfo(size_t n) EXCLUSIVE_LOCKS_REQUIRED(bool WriteBlockUndo(const CBlockUndo &blockundo, BlockValidationState &state, CBlockIndex &block) EXCLUSIVE_LOCKS_REQUIRED(FlatFilePos WriteBlock(const CBlock &block, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(void UpdateBlockInfo(const CBlock &block, unsigned int nHeight, const FlatFilePos &pos) EXCLUSIVE_LOCKS_REQUIRED(bool IsPruneMode() const
Get block file info entry for one block file.
bool LoadingBlocks() const
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t > > block_part=std::nullopt) const
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
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,...)
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * FEATURE
BIP 434 Peer feature negotiation.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
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...
bool ShouldDebugLog(Category category)
Return whether messages with specified category should be debug logged.
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 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 constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
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
static constexpr size_t MAX_FEATUREDATA_LENGTH
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static constexpr size_t MAX_FEATUREID_LENGTH
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 FEATURE_VERSION
"feature" message type for feature negotiation 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 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_VECTOR(obj, n)
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
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
NodeClock::duration m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
std::chrono::seconds time_offset
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
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.
Version of the system clock that is mockable in the context of tests (via FakeNodeClock or SetMockTim...
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
static constexpr time_point epoch
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_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...