74#include <initializer_list>
212 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
246 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
249 const bool m_is_inbound;
252 Mutex m_misbehavior_mutex;
254 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
257 Mutex m_block_inv_mutex;
261 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
265 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
276 std::atomic<uint64_t> m_ping_nonce_sent{0};
280 std::atomic<bool> m_ping_queued{
false};
283 std::atomic<bool> m_wtxid_relay{
false};
295 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
297 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
308 std::set<Wtxid> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
312 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
315 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
318 uint64_t m_last_inv_sequence
GUARDED_BY(m_tx_inventory_mutex){1};
321 std::atomic<CAmount> m_fee_filter_received{0};
327 LOCK(m_tx_relay_mutex);
329 m_tx_relay = std::make_unique<Peer::TxRelay>();
330 return m_tx_relay.get();
335 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
364 std::atomic_bool m_addr_relay_enabled{
false};
368 mutable Mutex m_addr_send_times_mutex;
370 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
372 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
375 std::atomic_bool m_wants_addrv2{
false};
384 std::atomic<uint64_t> m_addr_rate_limited{0};
386 std::atomic<uint64_t> m_addr_processed{0};
392 Mutex m_getdata_requests_mutex;
394 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
400 Mutex m_headers_sync_mutex;
403 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
406 std::atomic<bool> m_sent_sendheaders{
false};
416 std::atomic<std::chrono::seconds> m_time_offset{0
s};
420 , m_our_services{our_services}
421 , m_is_inbound{is_inbound}
425 mutable Mutex m_tx_relay_mutex;
428 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
431using PeerRef = std::shared_ptr<Peer>;
443 uint256 hashLastUnknownBlock{};
449 bool fSyncStarted{
false};
451 std::chrono::microseconds m_stalling_since{0us};
452 std::list<QueuedBlock> vBlocksInFlight;
454 std::chrono::microseconds m_downloading_since{0us};
456 bool fPreferredDownload{
false};
458 bool m_requested_hb_cmpctblocks{
false};
460 bool m_provides_cmpctblocks{
false};
486 struct ChainSyncTimeoutState {
488 std::chrono::seconds m_timeout{0
s};
492 bool m_sent_getheaders{
false};
494 bool m_protect{
false};
497 ChainSyncTimeoutState m_chain_sync;
500 int64_t m_last_block_announcement{0};
529 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
546 void SetBestBlock(
int height,
std::chrono::seconds time)
override
548 m_best_height = height;
549 m_best_block_time = time;
557 const std::atomic<bool>& interruptMsgProc)
558 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
570 void ReattemptPrivateBroadcast(
CScheduler& scheduler);
582 void Misbehaving(Peer& peer,
const std::string& message);
593 bool via_compact_block,
const std::string& message =
"")
602 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
616 bool first_time_failure)
641 bool ProcessOrphanTx(Peer& peer)
651 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
653 bool via_compact_block)
657 bool CheckHeadersPoW(const
std::vector<
CBlockHeader>& headers, Peer& peer);
665 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
684 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
698 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
713 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
715 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
722 template <
typename... Args>
723 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
729 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
778 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
781 std::atomic<int> m_best_height{-1};
783 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
791 const Options m_opts;
793 bool RejectIncomingTxs(
const CNode& peer)
const;
801 mutable Mutex m_peer_mutex;
808 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
818 uint32_t GetFetchFlags(
const Peer& peer)
const;
820 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
837 std::atomic<int> m_wtxid_relay_peers{0};
855 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
856 std::chrono::seconds average_interval,
861 Mutex m_most_recent_block_mutex;
862 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
863 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
865 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
869 Mutex m_headers_presync_mutex;
877 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
879 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
883 std::atomic_bool m_headers_presync_should_signal{
false};
953 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
959 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
964 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
997 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
999 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1011 int64_t ApproximateBestBlockDepth() const;
1021 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1039 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1041 const
uint256& stop_hash, uint32_t max_height_diff,
1088 void ProcessAddrs(
std::string_view msg_type,
CNode& pfrom, Peer& peer,
std::vector<
CAddress>&& vAddr, const
std::atomic<
bool>& interruptMsgProc)
1094 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1100const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const
1102 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1103 if (it == m_node_states.end())
1110 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1118static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1123void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1125 assert(peer.m_addr_known);
1126 peer.m_addr_known->insert(addr.
GetKey());
1129void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1134 assert(peer.m_addr_known);
1135 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1137 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1139 peer.m_addrs_to_send.push_back(addr);
1144static void AddKnownTx(Peer& peer,
const uint256& hash)
1146 auto tx_relay = peer.GetTxRelay();
1147 if (!tx_relay)
return;
1149 LOCK(tx_relay->m_tx_inventory_mutex);
1150 tx_relay->m_tx_inventory_known_filter.insert(hash);
1154static bool CanServeBlocks(
const Peer& peer)
1161static bool IsLimitedPeer(
const Peer& peer)
1168static bool CanServeWitnesses(
const Peer& peer)
1173std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1174 std::chrono::seconds average_interval,
1175 uint64_t network_key)
1177 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1178 auto& timer{it->second};
1180 timer = now + m_rng.rand_exp_duration(average_interval);
1185bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1187 return mapBlocksInFlight.contains(hash);
1190bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1192 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1193 auto [nodeid, block_it] = range.first->second;
1194 PeerRef peer{GetPeerRef(nodeid)};
1195 if (peer && !peer->m_is_inbound)
return true;
1201void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1203 auto range = mapBlocksInFlight.equal_range(hash);
1204 if (range.first == range.second) {
1212 while (range.first != range.second) {
1213 const auto& [node_id, list_it]{range.first->second};
1215 if (from_peer && *from_peer != node_id) {
1222 if (state.vBlocksInFlight.begin() == list_it) {
1224 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1226 state.vBlocksInFlight.erase(list_it);
1228 if (state.vBlocksInFlight.empty()) {
1230 m_peers_downloading_from--;
1232 state.m_stalling_since = 0us;
1234 range.first = mapBlocksInFlight.erase(range.first);
1238bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1242 CNodeState *state =
State(nodeid);
1243 assert(state !=
nullptr);
1248 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1249 if (range.first->second.first == nodeid) {
1251 *pit = &range.first->second.second;
1258 RemoveBlockRequest(hash, nodeid);
1260 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1261 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1262 if (state->vBlocksInFlight.size() == 1) {
1264 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1265 m_peers_downloading_from++;
1267 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1269 *pit = &itInFlight->second.second;
1274void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1281 if (m_opts.ignore_incoming_txs)
return;
1283 CNodeState* nodestate =
State(nodeid);
1284 PeerRef peer{GetPeerRef(nodeid)};
1285 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1290 int num_outbound_hb_peers = 0;
1291 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1292 if (*it == nodeid) {
1293 lNodesAnnouncingHeaderAndIDs.erase(it);
1294 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1297 PeerRef peer_ref{GetPeerRef(*it)};
1298 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1300 if (peer && peer->m_is_inbound) {
1303 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1304 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1305 if (remove_peer && !remove_peer->m_is_inbound) {
1308 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1314 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1317 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1318 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1320 pnodeStop->m_bip152_highbandwidth_to = false;
1323 lNodesAnnouncingHeaderAndIDs.pop_front();
1328 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1333bool PeerManagerImpl::TipMayBeStale()
1337 if (m_last_tip_update.load() == 0
s) {
1338 m_last_tip_update = GetTime<std::chrono::seconds>();
1340 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1343int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1348bool PeerManagerImpl::CanDirectFetch()
1355 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1357 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1362void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1363 CNodeState *state =
State(nodeid);
1364 assert(state !=
nullptr);
1366 if (!state->hashLastUnknownBlock.IsNull()) {
1369 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1370 state->pindexBestKnownBlock = pindex;
1372 state->hashLastUnknownBlock.SetNull();
1377void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1378 CNodeState *state =
State(nodeid);
1379 assert(state !=
nullptr);
1381 ProcessBlockAvailability(nodeid);
1386 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1387 state->pindexBestKnownBlock = pindex;
1391 state->hashLastUnknownBlock = hash;
1396void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1401 vBlocks.reserve(vBlocks.size() +
count);
1402 CNodeState *state =
State(peer.m_id);
1403 assert(state !=
nullptr);
1406 ProcessBlockAvailability(peer.m_id);
1408 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1419 state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1420 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1429 if (state->pindexLastCommonBlock ==
nullptr ||
1430 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1431 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1432 state->pindexLastCommonBlock = fork_point;
1434 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1437 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1443 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1446void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1451 if (vBlocks.size() >=
count) {
1455 vBlocks.reserve(
count);
1458 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1475void 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)
1477 std::vector<const CBlockIndex*> vToFetch;
1478 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1479 bool is_limited_peer = IsLimitedPeer(peer);
1481 while (pindexWalk->
nHeight < nMaxHeight) {
1485 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1486 vToFetch.resize(nToFetch);
1487 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1488 vToFetch[nToFetch - 1] = pindexWalk;
1489 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1490 vToFetch[i - 1] = vToFetch[i]->
pprev;
1510 state->pindexLastCommonBlock = pindex;
1517 if (waitingfor == -1) {
1519 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1525 if (pindex->
nHeight > nWindowEnd) {
1527 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1529 if (nodeStaller) *nodeStaller = waitingfor;
1539 vBlocks.push_back(pindex);
1540 if (vBlocks.size() ==
count) {
1549void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1551 uint64_t my_services;
1553 uint64_t your_services;
1555 std::string my_user_agent;
1563 my_user_agent =
"/pynode:0.0.1/";
1565 my_tx_relay =
false;
1568 my_services = peer.m_our_services;
1569 my_time = TicksSinceEpoch<std::chrono::seconds>(
NodeClock::now());
1573 my_height = m_best_height;
1574 my_tx_relay = !RejectIncomingTxs(pnode);
1593 BCLog::NET,
"send version message: version=%d, blocks=%d%s, txrelay=%d, peer=%d\n",
1596 my_tx_relay, pnode.
GetId());
1599void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1603 if (state) state->m_last_block_announcement = time_in_seconds;
1611 m_node_states.try_emplace(m_node_states.end(), nodeid);
1613 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1619 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1622 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1626void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1630 for (
const auto& txid : unbroadcast_txids) {
1633 if (tx !=
nullptr) {
1634 InitiateTxBroadcastToAll(txid, tx->GetWitnessHash());
1643 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1646void PeerManagerImpl::ReattemptPrivateBroadcast(
CScheduler& scheduler)
1650 size_t num_for_rebroadcast{0};
1651 const auto stale_txs = m_tx_for_private_broadcast.
GetStale();
1652 if (!stale_txs.empty()) {
1654 for (
const auto& stale_tx : stale_txs) {
1658 "Reattempting broadcast of stale txid=%s wtxid=%s",
1659 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString());
1660 ++num_for_rebroadcast;
1663 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString(),
1664 mempool_acceptable.m_state.ToString());
1665 m_tx_for_private_broadcast.
Remove(stale_tx);
1674 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, delta);
1677void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1688 PeerRef peer = RemovePeer(nodeid);
1690 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1691 assert(m_wtxid_relay_peers >= 0);
1693 CNodeState *state =
State(nodeid);
1694 assert(state !=
nullptr);
1696 if (state->fSyncStarted)
1699 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1700 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1701 while (range.first != range.second) {
1702 auto [node_id, list_it] = range.first->second;
1703 if (node_id != nodeid) {
1706 range.first = mapBlocksInFlight.erase(range.first);
1711 LOCK(m_tx_download_mutex);
1712 m_txdownloadman.DisconnectedPeer(nodeid);
1714 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1715 m_num_preferred_download_peers -= state->fPreferredDownload;
1716 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1717 assert(m_peers_downloading_from >= 0);
1718 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1719 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1721 m_node_states.erase(nodeid);
1723 if (m_node_states.empty()) {
1725 assert(mapBlocksInFlight.empty());
1726 assert(m_num_preferred_download_peers == 0);
1727 assert(m_peers_downloading_from == 0);
1728 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1729 assert(m_wtxid_relay_peers == 0);
1730 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1733 if (
node.fSuccessfullyConnected &&
1734 !
node.IsBlockOnlyConn() && !
node.IsPrivateBroadcastConn() && !
node.IsInboundConn()) {
1742 LOCK(m_headers_presync_mutex);
1743 m_headers_presync_stats.erase(nodeid);
1745 if (
node.IsPrivateBroadcastConn() &&
1754bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1757 return !(GetDesirableServiceFlags(services) & (~services));
1771PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1774 auto it = m_peer_map.find(
id);
1775 return it != m_peer_map.end() ? it->second :
nullptr;
1778PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1782 auto it = m_peer_map.find(
id);
1783 if (it != m_peer_map.end()) {
1784 ret = std::move(it->second);
1785 m_peer_map.erase(it);
1794 const CNodeState* state =
State(nodeid);
1795 if (state ==
nullptr)
1797 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1798 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1799 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1805 PeerRef peer = GetPeerRef(nodeid);
1806 if (peer ==
nullptr)
return false;
1814 NodeClock::duration ping_wait{0us};
1815 if ((0 != peer->m_ping_nonce_sent) && (peer->m_ping_start.load() >
NodeClock::epoch)) {
1819 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1822 LOCK(tx_relay->m_tx_inventory_mutex);
1824 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1836 LOCK(peer->m_headers_sync_mutex);
1837 if (peer->m_headers_sync) {
1846std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1848 LOCK(m_tx_download_mutex);
1849 return m_txdownloadman.GetOrphanTransactions();
1856 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1860std::vector<PrivateBroadcast::TxBroadcastInfo> PeerManagerImpl::GetPrivateBroadcastInfo()
const
1865std::vector<CTransactionRef> PeerManagerImpl::AbortPrivateBroadcast(
const uint256&
id)
1868 std::vector<CTransactionRef> removed_txs;
1870 size_t connections_cancelled{0};
1871 for (
const auto& tx_info : snapshot) {
1873 if (tx->GetHash().ToUint256() !=
id && tx->GetWitnessHash().ToUint256() !=
id)
continue;
1874 if (
const auto peer_acks{m_tx_for_private_broadcast.
Remove(tx)}) {
1875 removed_txs.push_back(tx);
1886void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1888 if (m_opts.max_extra_txs <= 0)
1890 if (!vExtraTxnForCompact.size())
1891 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1892 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1893 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1896void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1898 LOCK(peer.m_misbehavior_mutex);
1900 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1901 peer.m_should_discourage =
true;
1910 bool via_compact_block,
const std::string& message)
1912 PeerRef peer{GetPeerRef(nodeid)};
1923 if (!via_compact_block) {
1924 if (peer) Misbehaving(*peer, message);
1932 if (peer && !via_compact_block && !peer->m_is_inbound) {
1933 if (peer) Misbehaving(*peer, message);
1940 if (peer) Misbehaving(*peer, message);
1944 if (peer) Misbehaving(*peer, message);
1949 if (message !=
"") {
1954bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex& block_index)
1968 PeerRef peer = GetPeerRef(peer_id);
1977 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1980 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
2003 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
2009 : m_rng{opts.deterministic_rng},
2011 m_chainparams(chainman.GetParams()),
2015 m_chainman(chainman),
2017 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
2018 m_warnings{warnings},
2023 if (opts.reconcile_txs) {
2028void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2039 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2041 if (m_opts.private_broadcast) {
2042 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2046void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2054 LOCK(m_tx_download_mutex);
2058 m_txdownloadman.ActiveTipChange();
2068void PeerManagerImpl::BlockConnected(
2070 const std::shared_ptr<const CBlock>& pblock,
2075 m_last_tip_update = GetTime<std::chrono::seconds>();
2078 auto stalling_timeout = m_block_stalling_timeout.load();
2082 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2091 LOCK(m_tx_download_mutex);
2092 m_txdownloadman.BlockConnected(pblock);
2096void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2098 LOCK(m_tx_download_mutex);
2099 m_txdownloadman.BlockDisconnected();
2106void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2108 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2112 if (pindex->
nHeight <= m_highest_fast_announce)
2114 m_highest_fast_announce = pindex->
nHeight;
2118 uint256 hashBlock(pblock->GetHash());
2119 const std::shared_future<CSerializedNetMsg> lazy_ser{
2123 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2124 for (
const auto& tx : pblock->vtx) {
2125 most_recent_block_txs->emplace(tx->GetHash(), tx);
2126 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2129 LOCK(m_most_recent_block_mutex);
2130 m_most_recent_block_hash = hashBlock;
2131 m_most_recent_block = pblock;
2132 m_most_recent_compact_block = pcmpctblock;
2133 m_most_recent_block_txs = std::move(most_recent_block_txs);
2141 ProcessBlockAvailability(pnode->
GetId());
2145 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2147 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2148 hashBlock.ToString(), pnode->
GetId());
2151 PushMessage(*pnode, ser_cmpctblock.Copy());
2152 state.pindexBestHeaderSent = pindex;
2161void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2163 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2166 if (fInitialDownload)
return;
2169 std::vector<uint256> vHashes;
2171 while (pindexToAnnounce != pindexFork) {
2173 pindexToAnnounce = pindexToAnnounce->
pprev;
2183 for (
auto& it : m_peer_map) {
2184 Peer& peer = *it.second;
2185 LOCK(peer.m_block_inv_mutex);
2186 for (
const uint256& hash : vHashes | std::views::reverse) {
2187 peer.m_blocks_for_headers_relay.push_back(hash);
2199void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2203 const uint256 hash(block->GetHash());
2204 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2209 it != mapBlockSource.end() &&
2210 State(it->second.first)) {
2211 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2221 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2222 if (it != mapBlockSource.end()) {
2223 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2226 if (it != mapBlockSource.end())
2227 mapBlockSource.erase(it);
2235bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2240void PeerManagerImpl::SendPings()
2243 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2246void PeerManagerImpl::InitiateTxBroadcastToAll(
const Txid& txid,
const Wtxid& wtxid)
2249 for(
auto& it : m_peer_map) {
2250 Peer& peer = *it.second;
2251 auto tx_relay = peer.GetTxRelay();
2252 if (!tx_relay)
continue;
2254 LOCK(tx_relay->m_tx_inventory_mutex);
2260 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2263 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2264 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2269void PeerManagerImpl::InitiateTxBroadcastPrivate(
const CTransactionRef& tx)
2271 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2272 if (m_tx_for_private_broadcast.
Add(tx)) {
2280void PeerManagerImpl::RelayAddress(
NodeId originator,
2296 const auto current_time{GetTime<std::chrono::seconds>()};
2304 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2306 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2307 assert(nRelayNodes <= best.size());
2311 for (
auto& [
id, peer] : m_peer_map) {
2312 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2314 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2315 if (hashKey > best[i].first) {
2316 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2317 best[i] = std::make_pair(hashKey, peer.get());
2324 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2325 PushAddress(*best[i].second, addr);
2329void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2331 std::shared_ptr<const CBlock> a_recent_block;
2332 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2334 LOCK(m_most_recent_block_mutex);
2335 a_recent_block = m_most_recent_block;
2336 a_recent_compact_block = m_most_recent_compact_block;
2339 bool need_activate_chain =
false;
2351 need_activate_chain =
true;
2355 if (need_activate_chain) {
2357 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2364 bool can_direct_fetch{
false};
2372 if (!BlockRequestAllowed(*pindex)) {
2373 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2400 can_direct_fetch = CanDirectFetch();
2404 std::shared_ptr<const CBlock> pblock;
2405 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2406 pblock = a_recent_block;
2424 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2434 pblock = pblockRead;
2442 bool sendMerkleBlock =
false;
2444 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2445 LOCK(tx_relay->m_bloom_filter_mutex);
2446 if (tx_relay->m_bloom_filter) {
2447 sendMerkleBlock =
true;
2448 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2451 if (sendMerkleBlock) {
2459 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2470 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2483 LOCK(peer.m_block_inv_mutex);
2485 if (inv.
hash == peer.m_continuation_block) {
2489 std::vector<CInv> vInv;
2490 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2492 peer.m_continuation_block.SetNull();
2500 auto txinfo{std::visit(
2501 [&](
const auto&
id) {
2502 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2506 return std::move(txinfo.tx);
2511 LOCK(m_most_recent_block_mutex);
2512 if (m_most_recent_block_txs !=
nullptr) {
2513 auto it = m_most_recent_block_txs->find(gtxid);
2514 if (it != m_most_recent_block_txs->end())
return it->second;
2521void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2525 auto tx_relay = peer.GetTxRelay();
2527 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2528 std::vector<CInv> vNotFound;
2533 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2534 if (interruptMsgProc)
return;
2539 const CInv &inv = *it++;
2541 if (tx_relay ==
nullptr) {
2547 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2550 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2553 vNotFound.push_back(inv);
2559 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2560 const CInv &inv = *it++;
2562 ProcessGetBlockData(pfrom, peer, inv);
2571 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2573 if (!vNotFound.empty()) {
2592uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2594 uint32_t nFetchFlags = 0;
2595 if (CanServeWitnesses(peer)) {
2604 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2606 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2613 uint32_t tx_requested_size{0};
2614 for (
const auto& tx : resp.txn) tx_requested_size += tx->ComputeTotalSize();
2620bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2624 Misbehaving(peer,
"header with invalid proof of work");
2629 if (!CheckHeadersAreContinuous(headers)) {
2630 Misbehaving(peer,
"non-continuous headers sequence");
2655void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2656 const std::vector<CBlockHeader>& headers)
2660 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2661 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2663 headers[0].hashPrevBlock.ToString(),
2664 best_header->nHeight,
2674bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2678 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2681 hashLastBlock = header.GetHash();
2686bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2688 if (peer.m_headers_sync) {
2689 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2691 if (result.success) peer.m_last_getheaders_timestamp = {};
2692 if (result.request_more) {
2693 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2695 Assume(!locator.vHave.empty());
2698 if (!locator.vHave.empty()) {
2701 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2704 locator.vHave.front().ToString(), pfrom.
GetId());
2709 peer.m_headers_sync.reset(
nullptr);
2714 LOCK(m_headers_presync_mutex);
2715 m_headers_presync_stats.erase(pfrom.
GetId());
2718 HeadersPresyncStats stats;
2719 stats.first = peer.m_headers_sync->GetPresyncWork();
2721 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2722 peer.m_headers_sync->GetPresyncTime()};
2726 LOCK(m_headers_presync_mutex);
2727 m_headers_presync_stats[pfrom.
GetId()] = stats;
2728 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2729 bool best_updated =
false;
2730 if (best_it == m_headers_presync_stats.end()) {
2734 const HeadersPresyncStats* stat_best{
nullptr};
2735 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2736 if (!stat_best || stat > *stat_best) {
2741 m_headers_presync_bestpeer = peer_best;
2742 best_updated = (peer_best == pfrom.
GetId());
2743 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2745 m_headers_presync_bestpeer = pfrom.
GetId();
2746 best_updated =
true;
2748 if (best_updated && stats.second.has_value()) {
2750 m_headers_presync_should_signal =
true;
2754 if (result.success) {
2757 headers.swap(result.pow_validated_headers);
2760 return result.success;
2768bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
2775 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2779 if (total_work < minimum_chain_work) {
2783 if (headers.size() == m_opts.max_headers_result) {
2793 LOCK(peer.m_headers_sync_mutex);
2795 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2800 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2814bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2816 if (header ==
nullptr) {
2818 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2826bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2834 peer.m_last_getheaders_timestamp = current_time;
2845void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2848 CNodeState *nodestate =
State(pfrom.
GetId());
2851 std::vector<const CBlockIndex*> vToFetch;
2859 vToFetch.push_back(pindexWalk);
2861 pindexWalk = pindexWalk->
pprev;
2873 std::vector<CInv> vGetData;
2875 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2880 uint32_t nFetchFlags = GetFetchFlags(peer);
2882 BlockRequested(pfrom.
GetId(), *pindex);
2886 if (vGetData.size() > 1) {
2891 if (vGetData.size() > 0) {
2892 if (!m_opts.ignore_incoming_txs &&
2893 nodestate->m_provides_cmpctblocks &&
2894 vGetData.size() == 1 &&
2895 mapBlocksInFlight.size() == 1 &&
2911void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2912 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2915 CNodeState *nodestate =
State(pfrom.
GetId());
2924 nodestate->m_last_block_announcement =
GetTime();
2932 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2954 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) {
2956 nodestate->m_chain_sync.m_protect =
true;
2957 ++m_outbound_peers_with_protect_from_disconnect;
2962void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2963 std::vector<CBlockHeader>&& headers,
2964 bool via_compact_block)
2966 size_t nCount = headers.size();
2973 LOCK(peer.m_headers_sync_mutex);
2974 if (peer.m_headers_sync) {
2975 peer.m_headers_sync.reset(
nullptr);
2976 LOCK(m_headers_presync_mutex);
2977 m_headers_presync_stats.erase(pfrom.
GetId());
2981 peer.m_last_getheaders_timestamp = {};
2989 if (!CheckHeadersPoW(headers, peer)) {
3004 bool already_validated_work =
false;
3007 bool have_headers_sync =
false;
3009 LOCK(peer.m_headers_sync_mutex);
3011 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3023 if (headers.empty()) {
3027 have_headers_sync = !!peer.m_headers_sync;
3032 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3034 if (!headers_connect_blockindex) {
3038 HandleUnconnectingHeaders(pfrom, peer, headers);
3045 peer.m_last_getheaders_timestamp = {};
3055 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3062 already_validated_work =
true;
3068 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3069 *chain_start_header, headers)) {
3081 bool received_new_header{last_received_header ==
nullptr};
3087 state, &pindexLast)};
3093 "If this happens with all peers, consider database corruption (that -reindex may fix) "
3094 "or a potential consensus incompatibility.",
3097 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3103 if (processed && received_new_header) {
3104 LogBlockHeader(*pindexLast, pfrom,
false);
3108 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3110 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3115 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3118 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3124 bool first_time_failure)
3130 PeerRef peer{GetPeerRef(nodeid)};
3133 ptx->GetHash().ToString(),
3134 ptx->GetWitnessHash().ToString(),
3138 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3141 AddToCompactExtraTransactions(ptx);
3143 for (
const Txid& parent_txid : unique_parents) {
3144 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3147 return package_to_validate;
3150void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3156 m_txdownloadman.MempoolAcceptedTx(tx);
3160 tx->GetHash().ToString(),
3161 tx->GetWitnessHash().ToString(),
3164 InitiateTxBroadcastToAll(tx->GetHash(), tx->GetWitnessHash());
3167 AddToCompactExtraTransactions(removedTx);
3177 const auto&
package = package_to_validate.m_txns;
3178 const auto& senders = package_to_validate.
m_senders;
3181 m_txdownloadman.MempoolRejectedPackage(package);
3184 if (!
Assume(package.size() == 2))
return;
3188 auto package_iter = package.rbegin();
3189 auto senders_iter = senders.rbegin();
3190 while (package_iter != package.rend()) {
3191 const auto& tx = *package_iter;
3192 const NodeId nodeid = *senders_iter;
3193 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3197 const auto& tx_result = it_result->second;
3198 switch (tx_result.m_result_type) {
3201 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3211 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3229bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3236 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3239 const Txid& orphanHash = porphanTx->GetHash();
3240 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3257 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3266bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3268 const uint256& stop_hash, uint32_t max_height_diff,
3272 const bool supported_filter_type =
3275 if (!supported_filter_type) {
3277 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg());
3278 node.fDisconnect =
true;
3287 if (!stop_index || !BlockRequestAllowed(*stop_index)) {
3290 node.fDisconnect =
true;
3295 uint32_t stop_height = stop_index->
nHeight;
3296 if (start_height > stop_height) {
3298 "start height %d and stop height %d, %s",
3299 start_height, stop_height,
node.DisconnectMsg());
3300 node.fDisconnect =
true;
3303 if (stop_height - start_height >= max_height_diff) {
3305 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg());
3306 node.fDisconnect =
true;
3311 if (!filter_index) {
3321 uint8_t filter_type_ser;
3322 uint32_t start_height;
3325 vRecv >> filter_type_ser >> start_height >> stop_hash;
3331 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3336 std::vector<BlockFilter> filters;
3338 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3343 for (
const auto& filter : filters) {
3350 uint8_t filter_type_ser;
3351 uint32_t start_height;
3354 vRecv >> filter_type_ser >> start_height >> stop_hash;
3360 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3366 if (start_height > 0) {
3368 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3370 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3376 std::vector<uint256> filter_hashes;
3378 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3392 uint8_t filter_type_ser;
3395 vRecv >> filter_type_ser >> stop_hash;
3401 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3402 std::numeric_limits<uint32_t>::max(),
3403 stop_index, filter_index)) {
3411 for (
int i = headers.size() - 1; i >= 0; i--) {
3416 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3430 bool new_block{
false};
3431 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3433 node.m_last_block_time = GetTime<std::chrono::seconds>();
3438 RemoveBlockRequest(block->GetHash(), std::nullopt);
3441 mapBlockSource.erase(block->GetHash());
3445void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3447 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3448 bool fBlockRead{
false};
3452 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3453 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3454 bool requested_block_from_this_peer{
false};
3457 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3459 while (range_flight.first != range_flight.second) {
3460 auto [node_id, block_it] = range_flight.first->second;
3461 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3462 requested_block_from_this_peer =
true;
3465 range_flight.first++;
3468 if (!requested_block_from_this_peer) {
3480 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3491 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3494 if (first_in_flight) {
3499 std::vector<CInv> invs;
3504 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3517 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3532void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3544 "Saw new %sheader hash=%s height=%d %s",
3545 via_compact_block ?
"cmpctblock " :
"",
3557void PeerManagerImpl::PushPrivateBroadcastTx(
CNode&
node)
3564 node.fDisconnect =
true;
3570 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3576void PeerManagerImpl::ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3578 const std::atomic<bool>& interruptMsgProc)
3593 uint64_t nNonce = 1;
3596 std::string cleanSubVer;
3597 int starting_height = -1;
3600 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3615 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s",
3617 GetDesirableServiceFlags(nServices),
3630 if (!vRecv.
empty()) {
3638 if (!vRecv.
empty()) {
3639 std::string strSubVer;
3643 if (!vRecv.
empty()) {
3644 vRecv >> starting_height;
3664 PushNodeVersion(pfrom, peer);
3673 peer.m_their_services = nServices;
3677 pfrom.cleanSubVer = cleanSubVer;
3688 (fRelay || (peer.m_our_services &
NODE_BLOOM))) {
3689 auto*
const tx_relay = peer.SetTxRelay();
3691 LOCK(tx_relay->m_bloom_filter_mutex);
3692 tx_relay->m_relay_txs = fRelay;
3698 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, %s%s",
3699 cleanSubVer.empty() ?
"<no user agent>" : cleanSubVer, pfrom.
nVersion,
3701 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3719 if (greatest_common_version >= 70016) {
3734 const auto* tx_relay = peer.GetTxRelay();
3735 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3737 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3750 m_num_preferred_download_peers += state->fPreferredDownload;
3756 bool send_getaddr{
false};
3758 send_getaddr = SetupAddressRelay(pfrom, peer);
3768 peer.m_getaddr_sent =
true;
3792 peer.m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3796 m_outbound_time_offsets.Add(peer.m_time_offset);
3797 m_outbound_time_offsets.WarnIfOutOfSync();
3801 if (greatest_common_version <= 70012) {
3802 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3803 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3826 auto new_peer_msg = [&]() {
3828 return strprintf(
"New %s peer connected: transport: %s, version: %d, %s%s",
3832 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3840 LogInfo(
"%s", new_peer_msg());
3843 if (
auto tx_relay = peer.GetTxRelay()) {
3852 tx_relay->m_tx_inventory_mutex,
3853 return tx_relay->m_tx_inventory_to_send.empty() &&
3854 tx_relay->m_next_inv_send_time == 0
s));
3864 PushPrivateBroadcastTx(pfrom);
3877 if (m_txreconciliation) {
3878 if (!peer.m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3882 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3888 const CNodeState* state =
State(pfrom.
GetId());
3890 .m_preferred = state->fPreferredDownload,
3891 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3892 .m_wtxid_relay = peer.m_wtxid_relay,
3901 peer.m_prefers_headers =
true;
3906 bool sendcmpct_hb{
false};
3907 uint64_t sendcmpct_version{0};
3908 vRecv >> sendcmpct_hb >> sendcmpct_version;
3914 CNodeState* nodestate =
State(pfrom.
GetId());
3915 nodestate->m_provides_cmpctblocks =
true;
3916 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3933 if (!peer.m_wtxid_relay) {
3934 peer.m_wtxid_relay =
true;
3935 m_wtxid_relay_peers++;
3954 peer.m_wants_addrv2 =
true;
3962 if (!m_txreconciliation) {
3963 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3974 if (RejectIncomingTxs(pfrom)) {
3983 const auto* tx_relay = peer.GetTxRelay();
3984 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3990 uint32_t peer_txreconcl_version;
3991 uint64_t remote_salt;
3992 vRecv >> peer_txreconcl_version >> remote_salt;
3995 peer_txreconcl_version, remote_salt);
4027 const auto ser_params{
4035 std::vector<CAddress> vAddr;
4036 vRecv >> ser_params(vAddr);
4037 ProcessAddrs(msg_type, pfrom, peer, std::move(vAddr), interruptMsgProc);
4042 std::vector<CInv> vInv;
4046 Misbehaving(peer,
strprintf(
"inv message size = %u", vInv.size()));
4050 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4054 const auto current_time{GetTime<std::chrono::microseconds>()};
4057 for (
CInv& inv : vInv) {
4058 if (interruptMsgProc)
return;
4063 if (peer.m_wtxid_relay) {
4070 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4073 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4081 best_block = &inv.
hash;
4084 if (reject_tx_invs) {
4090 AddKnownTx(peer, inv.
hash);
4093 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4101 if (best_block !=
nullptr) {
4113 if (state.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4114 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer)) {
4116 m_chainman.m_best_header->nHeight, best_block->ToString(),
4119 if (!state.fSyncStarted) {
4120 peer.m_inv_triggered_getheaders_before_sync =
true;
4124 m_last_block_inv_triggering_headers_sync = *best_block;
4133 std::vector<CInv> vInv;
4137 Misbehaving(peer,
strprintf(
"getdata message size = %u", vInv.size()));
4143 if (vInv.size() > 0) {
4148 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4149 if (!pushed_tx_opt) {
4160 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4164 peer.m_ping_queued =
true;
4175 LOCK(peer.m_getdata_requests_mutex);
4176 peer.m_getdata_requests.insert(peer.m_getdata_requests.end(), vInv.begin(), vInv.end());
4177 ProcessGetData(pfrom, peer, interruptMsgProc);
4186 vRecv >> locator >> hashStop;
4202 std::shared_ptr<const CBlock> a_recent_block;
4204 LOCK(m_most_recent_block_mutex);
4205 a_recent_block = m_most_recent_block;
4208 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4223 for (; pindex; pindex = m_chainman.
ActiveChain().Next(*pindex))
4238 if (--nLimit <= 0) {
4242 WITH_LOCK(peer.m_block_inv_mutex, {peer.m_continuation_block = pindex->GetBlockHash();});
4254 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4258 std::shared_ptr<const CBlock> recent_block;
4260 LOCK(m_most_recent_block_mutex);
4261 if (m_most_recent_block_hash == req.
blockhash)
4262 recent_block = m_most_recent_block;
4266 SendBlockTransactions(pfrom, peer, *recent_block, req);
4285 if (!block_pos.IsNull()) {
4292 SendBlockTransactions(pfrom, peer, block, req);
4305 WITH_LOCK(peer.m_getdata_requests_mutex, peer.m_getdata_requests.push_back(inv));
4313 vRecv >> locator >> hashStop;
4331 if (m_chainman.
ActiveTip() ==
nullptr ||
4333 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4340 CNodeState *nodestate =
State(pfrom.
GetId());
4349 if (!BlockRequestAllowed(*pindex)) {
4350 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4363 std::vector<CBlock> vHeaders;
4364 int nLimit = m_opts.max_headers_result;
4366 for (; pindex; pindex = m_chainman.
ActiveChain().Next(*pindex))
4369 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4384 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4390 if (RejectIncomingTxs(pfrom)) {
4404 const Txid& txid = ptx->GetHash();
4405 const Wtxid& wtxid = ptx->GetWitnessHash();
4408 AddKnownTx(peer, hash);
4410 if (
const auto num_broadcasted{m_tx_for_private_broadcast.
Remove(ptx)}) {
4412 "network from %s; stopping private broadcast attempts",
4423 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4424 if (!should_validate) {
4429 if (!m_mempool.
exists(txid)) {
4430 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4433 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4435 InitiateTxBroadcastToAll(txid, wtxid);
4439 if (package_to_validate) {
4442 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4443 ProcessPackageResult(package_to_validate.value(), package_result);
4449 Assume(!package_to_validate.has_value());
4459 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4462 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4463 ProcessPackageResult(package_to_validate.value(), package_result);
4479 vRecv >> cmpctblock;
4481 bool received_new_header =
false;
4491 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer);
4501 received_new_header =
true;
4509 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4516 if (received_new_header) {
4517 LogBlockHeader(*pindex, pfrom,
true);
4520 bool fProcessBLOCKTXN =
false;
4524 bool fRevertToHeaderProcessing =
false;
4528 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4529 bool fBlockReconstructed =
false;
4535 CNodeState *nodestate =
State(pfrom.
GetId());
4540 nodestate->m_last_block_announcement =
GetTime();
4546 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4547 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4548 bool requested_block_from_this_peer{
false};
4551 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4553 while (range_flight.first != range_flight.second) {
4554 if (range_flight.first->second.first == pfrom.
GetId()) {
4555 requested_block_from_this_peer =
true;
4558 range_flight.first++;
4563 if (requested_block_from_this_peer) {
4566 std::vector<CInv> vInv(1);
4574 if (!already_in_flight && !CanDirectFetch()) {
4582 requested_block_from_this_peer) {
4583 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4584 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4585 if (!(*queuedBlockIt)->partialBlock)
4598 Misbehaving(peer,
"invalid compact block");
4601 if (first_in_flight) {
4603 std::vector<CInv> vInv(1);
4614 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4619 fProcessBLOCKTXN =
true;
4620 }
else if (first_in_flight) {
4627 IsBlockRequestedFromOutbound(blockhash) ||
4646 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4651 std::vector<CTransactionRef> dummy;
4653 status = tempBlock.FillBlock(*pblock, dummy,
4656 fBlockReconstructed =
true;
4660 if (requested_block_from_this_peer) {
4663 std::vector<CInv> vInv(1);
4669 fRevertToHeaderProcessing =
true;
4674 if (fProcessBLOCKTXN) {
4677 return ProcessCompactBlockTxns(pfrom, peer, txn);
4680 if (fRevertToHeaderProcessing) {
4686 return ProcessHeadersMessage(pfrom, peer, {cmpctblock.
header},
true);
4689 if (fBlockReconstructed) {
4694 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4712 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4729 return ProcessCompactBlockTxns(pfrom, peer, resp);
4740 std::vector<CBlockHeader> headers;
4744 if (nCount > m_opts.max_headers_result) {
4745 Misbehaving(peer,
strprintf(
"headers message size = %u", nCount));
4748 headers.resize(nCount);
4749 for (
unsigned int n = 0; n < nCount; n++) {
4750 vRecv >> headers[n];
4754 ProcessHeadersMessage(pfrom, peer, std::move(headers),
false);
4758 if (m_headers_presync_should_signal.exchange(
false)) {
4759 HeadersPresyncStats stats;
4761 LOCK(m_headers_presync_mutex);
4762 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4763 if (it != m_headers_presync_stats.end()) stats = it->second;
4781 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4792 Misbehaving(peer,
"mutated block");
4797 bool forceProcessing =
false;
4798 const uint256 hash(pblock->GetHash());
4799 bool min_pow_checked =
false;
4804 forceProcessing = IsBlockRequested(hash);
4805 RemoveBlockRequest(hash, pfrom.
GetId());
4809 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4813 min_pow_checked =
true;
4816 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4833 Assume(SetupAddressRelay(pfrom, peer));
4837 if (peer.m_getaddr_recvd) {
4841 peer.m_getaddr_recvd =
true;
4843 peer.m_addrs_to_send.clear();
4844 std::vector<CAddress> vAddr;
4850 for (
const CAddress &addr : vAddr) {
4851 PushAddress(peer, addr);
4879 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4880 LOCK(tx_relay->m_tx_inventory_mutex);
4881 tx_relay->m_send_mempool =
true;
4907 ProcessPong(pfrom, peer, time_received, vRecv);
4923 Misbehaving(peer,
"too-large bloom filter");
4924 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4926 LOCK(tx_relay->m_bloom_filter_mutex);
4927 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4928 tx_relay->m_relay_txs =
true;
4942 std::vector<unsigned char> vData;
4950 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4951 LOCK(tx_relay->m_bloom_filter_mutex);
4952 if (tx_relay->m_bloom_filter) {
4953 tx_relay->m_bloom_filter->insert(vData);
4959 Misbehaving(peer,
"bad filteradd message");
4970 auto tx_relay = peer.GetTxRelay();
4971 if (!tx_relay)
return;
4974 LOCK(tx_relay->m_bloom_filter_mutex);
4975 tx_relay->m_bloom_filter =
nullptr;
4976 tx_relay->m_relay_txs =
true;
4985 vRecv >> newFeeFilter;
4987 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4988 tx_relay->m_fee_filter_received = newFeeFilter;
4996 ProcessGetCFilters(pfrom, peer, vRecv);
5001 ProcessGetCFHeaders(pfrom, peer, vRecv);
5006 ProcessGetCFCheckPt(pfrom, peer, vRecv);
5011 std::vector<CInv> vInv;
5013 std::vector<GenTxid> tx_invs;
5015 for (
CInv &inv : vInv) {
5021 LOCK(m_tx_download_mutex);
5022 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5031bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5034 LOCK(peer.m_misbehavior_mutex);
5037 if (!peer.m_should_discourage)
return false;
5039 peer.m_should_discourage =
false;
5044 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5050 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5070bool PeerManagerImpl::ProcessMessages(
CNode&
node, std::atomic<bool>& interruptMsgProc)
5075 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5076 if (maybe_peer ==
nullptr)
return false;
5077 Peer& peer{*maybe_peer};
5081 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent)
return false;
5084 LOCK(peer.m_getdata_requests_mutex);
5085 if (!peer.m_getdata_requests.empty()) {
5086 ProcessGetData(
node, peer, interruptMsgProc);
5090 const bool processed_orphan = ProcessOrphanTx(peer);
5092 if (
node.fDisconnect)
5095 if (processed_orphan)
return true;
5100 LOCK(peer.m_getdata_requests_mutex);
5101 if (!peer.m_getdata_requests.empty())
return true;
5105 if (
node.fPauseSend)
return false;
5107 auto poll_result{
node.PollMessage()};
5114 bool fMoreWork = poll_result->second;
5118 node.m_addr_name.c_str(),
5119 node.ConnectionTypeAsString().c_str(),
5125 if (m_opts.capture_messages) {
5130 ProcessMessage(peer,
node,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5131 if (interruptMsgProc)
return false;
5133 LOCK(peer.m_getdata_requests_mutex);
5134 if (!peer.m_getdata_requests.empty()) fMoreWork =
true;
5141 LOCK(m_tx_download_mutex);
5142 if (m_txdownloadman.HaveMoreWork(peer.m_id)) fMoreWork =
true;
5143 }
catch (
const std::exception& e) {
5152void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5165 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5167 if (state.m_chain_sync.m_timeout != 0
s) {
5168 state.m_chain_sync.m_timeout = 0
s;
5169 state.m_chain_sync.m_work_header =
nullptr;
5170 state.m_chain_sync.m_sent_getheaders =
false;
5172 }
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)) {
5180 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5181 state.m_chain_sync.m_sent_getheaders =
false;
5182 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5186 if (state.m_chain_sync.m_sent_getheaders) {
5188 LogInfo(
"Outbound peer has old chain, best known block = %s, %s", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg());
5191 assert(state.m_chain_sync.m_work_header);
5196 MaybeSendGetHeaders(pto,
5197 GetLocator(state.m_chain_sync.m_work_header->pprev),
5199 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());
5200 state.m_chain_sync.m_sent_getheaders =
true;
5221 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5225 if (pnode->
GetId() > youngest_peer.first) {
5226 next_youngest_peer = youngest_peer;
5227 youngest_peer.first = pnode->GetId();
5228 youngest_peer.second = pnode->m_last_block_time;
5231 NodeId to_disconnect = youngest_peer.first;
5232 if (youngest_peer.second > next_youngest_peer.second) {
5235 to_disconnect = next_youngest_peer.first;
5244 CNodeState *node_state =
State(pnode->
GetId());
5245 if (node_state ==
nullptr ||
5248 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5252 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5253 pnode->
GetId(), TicksSinceEpoch<std::chrono::seconds>(pnode->
m_connected), node_state->vBlocksInFlight.size());
5268 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5271 AssertLockHeld(::cs_main);
5275 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5276 CNodeState *state = State(pnode->GetId());
5277 if (state == nullptr) return;
5279 if (state->m_chain_sync.m_protect) return;
5282 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5283 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5284 worst_peer = pnode->GetId();
5285 oldest_block_announcement = state->m_last_block_announcement;
5288 if (worst_peer != -1) {
5299 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5303 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5304 pnode->
GetId(), TicksSinceEpoch<std::chrono::seconds>(pnode->
m_connected), state.vBlocksInFlight.size());
5320void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5325 auto now{GetTime<std::chrono::seconds>()};
5327 EvictExtraOutboundPeers(current_time);
5329 if (now > m_stale_tip_check_time) {
5333 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5342 if (!m_initial_sync_finished && CanDirectFetch()) {
5344 m_initial_sync_finished =
true;
5351 peer.m_ping_nonce_sent &&
5361 bool pingSend =
false;
5363 if (peer.m_ping_queued) {
5368 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5377 }
while (
nonce == 0);
5378 peer.m_ping_queued =
false;
5379 peer.m_ping_start = now;
5381 peer.m_ping_nonce_sent =
nonce;
5385 peer.m_ping_nonce_sent = 0;
5391void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5394 if (!peer.m_addr_relay_enabled)
return;
5396 LOCK(peer.m_addr_send_times_mutex);
5399 peer.m_next_local_addr_send < current_time) {
5406 if (peer.m_next_local_addr_send != 0us) {
5407 peer.m_addr_known->reset();
5410 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5411 if (peer.m_next_local_addr_send == 0us) {
5415 if (IsAddrCompatible(peer, local_addr)) {
5416 std::vector<CAddress> self_announcement{local_addr};
5417 if (peer.m_wants_addrv2) {
5425 PushAddress(peer, local_addr);
5432 if (current_time <= peer.m_next_addr_send)
return;
5445 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5446 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5449 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5450 peer.m_addrs_to_send.end());
5453 if (peer.m_addrs_to_send.empty())
return;
5455 if (peer.m_wants_addrv2) {
5460 peer.m_addrs_to_send.clear();
5463 if (peer.m_addrs_to_send.capacity() > 40) {
5464 peer.m_addrs_to_send.shrink_to_fit();
5468void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5476 CNodeState &state = *
State(
node.GetId());
5477 if (state.pindexBestKnownBlock !=
nullptr &&
5484 peer.m_sent_sendheaders =
true;
5489void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5491 if (m_opts.ignore_incoming_txs)
return;
5507 if (peer.m_fee_filter_sent == MAX_FILTER) {
5510 peer.m_next_send_feefilter = 0us;
5513 if (current_time > peer.m_next_send_feefilter) {
5514 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5517 if (filterToSend != peer.m_fee_filter_sent) {
5519 peer.m_fee_filter_sent = filterToSend;
5526 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5532class CompareInvMempoolOrder
5536 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5538 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5547bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5560 const size_t nAvail{vRecv.
size()};
5561 bool bPingFinished =
false;
5562 std::string sProblem;
5564 if (nAvail >=
sizeof(
nonce)) {
5568 if (peer.m_ping_nonce_sent != 0) {
5569 if (
nonce == peer.m_ping_nonce_sent) {
5571 bPingFinished =
true;
5572 const auto ping_time = ping_end - peer.m_ping_start.load();
5573 if (ping_time.count() >= 0) {
5584 sProblem =
"Timing mishap";
5588 sProblem =
"Nonce mismatch";
5591 bPingFinished =
true;
5592 sProblem =
"Nonce zero";
5596 sProblem =
"Unsolicited pong without ping";
5600 bPingFinished =
true;
5601 sProblem =
"Short payload";
5604 if (!(sProblem.empty())) {
5608 peer.m_ping_nonce_sent,
5612 if (bPingFinished) {
5613 peer.m_ping_nonce_sent = 0;
5617bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5622 if (
node.IsBlockOnlyConn())
return false;
5624 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5628 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5634void PeerManagerImpl::ProcessAddrs(std::string_view msg_type,
CNode& pfrom, Peer& peer, std::vector<CAddress>&& vAddr,
const std::atomic<bool>& interruptMsgProc)
5639 if (!SetupAddressRelay(pfrom, peer)) {
5646 Misbehaving(peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
5651 std::vector<CAddress> vAddrOk;
5657 const auto time_diff{current_time - peer.m_addr_token_timestamp};
5661 peer.m_addr_token_timestamp = current_time;
5664 uint64_t num_proc = 0;
5665 uint64_t num_rate_limit = 0;
5666 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
5669 if (interruptMsgProc)
5673 if (peer.m_addr_token_bucket < 1.0) {
5679 peer.m_addr_token_bucket -= 1.0;
5688 addr.
nTime = std::chrono::time_point_cast<std::chrono::seconds>(current_time - 5 * 24h);
5690 AddAddressKnown(peer, addr);
5697 if (addr.
nTime > current_time - 10min && !peer.m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
5699 RelayAddress(pfrom.
GetId(), addr, reachable);
5703 vAddrOk.push_back(addr);
5706 peer.m_addr_processed += num_proc;
5707 peer.m_addr_rate_limited += num_rate_limit;
5708 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
5709 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
5711 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
5712 if (vAddr.size() < 1000) peer.m_getaddr_sent =
false;
5721bool PeerManagerImpl::SendMessages(
CNode&
node)
5726 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5727 if (!maybe_peer)
return false;
5728 Peer& peer{*maybe_peer};
5733 if (MaybeDiscourageAndDisconnect(
node, peer))
return true;
5736 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent) {
5737 PushNodeVersion(
node, peer);
5738 peer.m_outbound_version_message_sent =
true;
5742 if (!
node.fSuccessfullyConnected ||
node.fDisconnect)
5746 const auto current_time{GetTime<std::chrono::microseconds>()};
5751 if (
node.IsPrivateBroadcastConn()) {
5755 node.fDisconnect =
true;
5762 node.fDisconnect =
true;
5766 MaybeSendPing(
node, peer, now);
5769 if (
node.fDisconnect)
return true;
5771 MaybeSendAddr(
node, peer, current_time);
5773 MaybeSendSendHeaders(
node, peer);
5778 CNodeState &state = *
State(
node.GetId());
5781 if (m_chainman.m_best_header ==
nullptr) {
5788 bool sync_blocks_and_headers_from_peer =
false;
5789 if (state.fPreferredDownload) {
5790 sync_blocks_and_headers_from_peer =
true;
5791 }
else if (CanServeBlocks(peer) && !
node.IsAddrFetchConn()) {
5801 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5802 sync_blocks_and_headers_from_peer =
true;
5808 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5809 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5817 if (pindexStart->
pprev)
5818 pindexStart = pindexStart->
pprev;
5822 state.fSyncStarted =
true;
5846 LOCK(peer.m_block_inv_mutex);
5847 std::vector<CBlock> vHeaders;
5848 bool fRevertToInv = ((!peer.m_prefers_headers &&
5849 (!state.m_requested_hb_cmpctblocks || peer.m_blocks_for_headers_relay.size() > 1)) ||
5852 ProcessBlockAvailability(
node.GetId());
5854 if (!fRevertToInv) {
5855 bool fFoundStartingHeader =
false;
5859 for (
const uint256& hash : peer.m_blocks_for_headers_relay) {
5864 fRevertToInv =
true;
5867 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5879 fRevertToInv =
true;
5882 pBestIndex = pindex;
5883 if (fFoundStartingHeader) {
5886 }
else if (PeerHasHeader(&state, pindex)) {
5888 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5891 fFoundStartingHeader =
true;
5896 fRevertToInv =
true;
5901 if (!fRevertToInv && !vHeaders.empty()) {
5902 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5906 vHeaders.front().GetHash().ToString(),
node.GetId());
5908 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5910 LOCK(m_most_recent_block_mutex);
5911 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5915 if (cached_cmpctblock_msg.has_value()) {
5916 PushMessage(
node, std::move(cached_cmpctblock_msg.value()));
5924 state.pindexBestHeaderSent = pBestIndex;
5925 }
else if (peer.m_prefers_headers) {
5926 if (vHeaders.size() > 1) {
5929 vHeaders.front().GetHash().ToString(),
5930 vHeaders.back().GetHash().ToString(),
node.GetId());
5933 vHeaders.front().GetHash().ToString(),
node.GetId());
5936 state.pindexBestHeaderSent = pBestIndex;
5938 fRevertToInv =
true;
5944 if (!peer.m_blocks_for_headers_relay.empty()) {
5945 const uint256& hashToAnnounce = peer.m_blocks_for_headers_relay.back();
5958 if (!PeerHasHeader(&state, pindex)) {
5959 peer.m_blocks_for_inv_relay.push_back(hashToAnnounce);
5965 peer.m_blocks_for_headers_relay.clear();
5971 std::vector<CInv> vInv;
5973 LOCK(peer.m_block_inv_mutex);
5977 for (
const uint256& hash : peer.m_blocks_for_inv_relay) {
5984 peer.m_blocks_for_inv_relay.clear();
5987 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5988 LOCK(tx_relay->m_tx_inventory_mutex);
5991 if (tx_relay->m_next_inv_send_time < current_time) {
5992 fSendTrickle =
true;
5993 if (
node.IsInboundConn()) {
6002 LOCK(tx_relay->m_bloom_filter_mutex);
6003 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
6007 if (fSendTrickle && tx_relay->m_send_mempool) {
6008 auto vtxinfo = m_mempool.
infoAll();
6009 tx_relay->m_send_mempool =
false;
6010 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6012 LOCK(tx_relay->m_bloom_filter_mutex);
6014 for (
const auto& txinfo : vtxinfo) {
6015 const Txid& txid{txinfo.tx->GetHash()};
6016 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
6017 const auto inv = peer.m_wtxid_relay ?
6020 tx_relay->m_tx_inventory_to_send.erase(wtxid);
6023 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6026 if (tx_relay->m_bloom_filter) {
6027 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6029 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6030 vInv.push_back(inv);
6041 std::vector<std::set<Wtxid>::iterator> vInvTx;
6042 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
6043 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
6044 vInvTx.push_back(it);
6046 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6049 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
6050 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6053 unsigned int nRelayedTransactions = 0;
6054 LOCK(tx_relay->m_bloom_filter_mutex);
6057 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
6059 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6060 std::set<Wtxid>::iterator it = vInvTx.back();
6064 tx_relay->m_tx_inventory_to_send.erase(it);
6066 auto txinfo = m_mempool.
info(wtxid);
6073 const auto inv = peer.m_wtxid_relay ?
6075 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
6077 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
6081 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6084 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6086 vInv.push_back(inv);
6087 nRelayedTransactions++;
6092 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6097 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6104 auto stalling_timeout = m_block_stalling_timeout.load();
6105 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6109 LogInfo(
"Peer is stalling block download, %s",
node.DisconnectMsg());
6110 node.fDisconnect =
true;
6114 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6124 if (state.vBlocksInFlight.size() > 0) {
6125 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6126 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6128 LogInfo(
"Timeout downloading block %s, %s", queuedBlock.pindex->GetBlockHash().ToString(),
node.DisconnectMsg());
6129 node.fDisconnect =
true;
6134 if (state.fSyncStarted && peer.m_headers_sync_timeout < std::chrono::microseconds::max()) {
6136 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6137 if (current_time > peer.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6144 LogInfo(
"Timeout downloading headers, %s",
node.DisconnectMsg());
6145 node.fDisconnect =
true;
6148 LogInfo(
"Timeout downloading headers from noban peer, not %s",
node.DisconnectMsg());
6154 state.fSyncStarted =
false;
6156 peer.m_headers_sync_timeout = 0us;
6162 peer.m_headers_sync_timeout = std::chrono::microseconds::max();
6168 ConsiderEviction(
node, peer, GetTime<std::chrono::seconds>());
6173 std::vector<CInv> vGetData;
6175 std::vector<const CBlockIndex*> vToDownload;
6177 auto get_inflight_budget = [&state]() {
6184 FindNextBlocksToDownload(peer, get_inflight_budget(), vToDownload, staller);
6185 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
6186 if (historical_blocks && !IsLimitedPeer(peer)) {
6190 TryDownloadingHistoricalBlocks(
6192 get_inflight_budget(),
6193 vToDownload, from_tip, historical_blocks->second);
6196 uint32_t nFetchFlags = GetFetchFlags(peer);
6198 BlockRequested(
node.GetId(), *pindex);
6202 if (state.vBlocksInFlight.empty() && staller != -1) {
6203 if (
State(staller)->m_stalling_since == 0us) {
6204 State(staller)->m_stalling_since = current_time;
6214 LOCK(m_tx_download_mutex);
6215 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(
node.GetId(), current_time)) {
6224 if (!vGetData.empty())
6227 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...
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
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)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
bool DisconnectNode(std::string_view node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return randomly selected addresses.
bool CheckIncomingNonce(uint64_t nonce)
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, Txid > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
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....
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
General SipHash-2-4 implementation.
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
bool CompareMiningScoreWithTopology(const Wtxid &hasha, const Wtxid &hashb) const
TxMempoolInfo info_for_relay(const T &id, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
CFeeRate GetMinFee(size_t sizelimit) const
CTransactionRef get(const Txid &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
TxMempoolInfo info(const T &id) const
bool exists(const Txid &txid) const
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
std::set< Txid > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
unsigned long size() const
void RemoveUnbroadcastTx(const Txid &txid, bool unchecked=false)
Removes a transaction from the unbroadcast set.
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void BlockChecked(const std::shared_ptr< const CBlock > &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void ActiveTipChange(const CBlockIndex &new_tip, bool is_ibd)
Notifies listeners any time the block chain tip changes, synchronously.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected Provides the block that was disconnected.
virtual void BlockConnected(const kernel::ChainstateRole &role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
void ClearBlockIndexCandidates() EXCLUSIVE_LOCKS_REQUIRED(void PopulateBlockIndexCandidates() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex * FindForkInGlobalIndex(const CBlockLocator &locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Populate the candidate set by calling TryAddBlockIndexCandidate on all valid block indices.
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
bool IsInitialBlockDownload() const noexcept
Check whether we are doing an initial block download (synchronizing from disk or network)
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Chainstate & ActiveChainstate() const
Alternatives to CurrentChainstate() used by older code to query latest chainstate information without...
SnapshotCompletionResult MaybeValidateSnapshot(Chainstate &validated_cs, Chainstate &unvalidated_cs) EXCLUSIVE_LOCKS_REQUIRED(Chainstate & CurrentChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Try to validate an assumeutxo snapshot by using a validated historical chainstate targeted at the sna...
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool ProcessNewBlockHeaders(std::span< const CBlockHeader > headers, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const arith_uint256 & MinimumChainWork() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
void ReportHeadersPresync(int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Double ended buffer combining vector and stream-like interfaces.
void ignore(size_t num_ignore)
uint64_t rand64() noexcept
Generate a random 64-bit integer.
const uint256 & ToUint256() const LIFETIMEBOUND
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual bool ProcessMessages(CNode &node, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
virtual bool SendMessages(CNode &node) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing, bool segwit_active)
bool IsTxAvailable(size_t index) const
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< Wtxid, CTransactionRef > > &extra_txn)
virtual util::Expected< void, std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
virtual std::vector< node::TxOrphanage::OrphanInfo > GetOrphanTransactions()=0
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
virtual void UnitTestMisbehaving(NodeId peer_id)=0
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests....
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
Store a list of transactions to be broadcast privately.
void NodeConfirmedReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Mark that the node has confirmed reception of the transaction we sent it by responding with PONG to o...
std::vector< TxBroadcastInfo > GetBroadcastInfo() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get stats about all transactions currently being privately broadcast.
bool HavePendingTransactions() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if there are transactions that need to be broadcast.
bool DidNodeConfirmReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if the node has confirmed reception of the transaction.
std::optional< size_t > Remove(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Forget a transaction.
std::optional< CTransactionRef > PickTxForSend(const NodeId &will_send_to_nodeid, const CService &will_send_to_address) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Pick the transaction with the fewest send attempts, and confirmations, and oldest send/confirm times.
std::optional< CTransactionRef > GetTxForNode(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transaction that was picked for sending to a given node by PickTxForSend().
bool Add(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a transaction to the storage.
std::vector< CTransactionRef > GetStale() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transactions that have not been broadcast recently.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
std::string GetDebugMessage() const
std::string ToString() const
256-bit unsigned big integer.
constexpr bool IsNull() const
std::string ToString() const
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool LoadingBlocks() const
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t > > block_part=std::nullopt) const
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
bool IsPruneMode() const
Whether running in -prune mode.
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
Manages warning messages within a node.
std::string ToString() const
const uint256 & ToUint256() const LIFETIMEBOUND
The util::Expected class provides a standard way for low-level functions to return either error value...
The util::Unexpected class represents an unexpected value stored in util::Expected.
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
@ BLOCK_HEADER_LOW_WORK
the block header may be on a too-little-work chain
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ BLOCK_RESULT_UNSET
initial value. Block has not yet been rejected
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_NO_MEMPOOL
this node does not have a mempool so can't validate the transaction
@ TX_RESULT_UNSET
initial value. Tx has not yet been rejected
static size_t RecursiveDynamicUsage(const CScript &script)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
is a home for simple enum and struct type definitions that can be used internally by functions in the...
#define LogDebug(category,...)
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
TRACEPOINT_SEMAPHORE(net, inbound_message)
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr size_t NUM_PRIVATE_BROADCAST_PER_TX
For private broadcast, send a transaction to this many peers.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto PRIVATE_BROADCAST_MAX_CONNECTION_LIFETIME
Private broadcast connections must complete within this time.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" message type for wtxid-based relay starts with this version
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" message type and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
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 NodeClockContext or SetMock...
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...