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);
277 std::atomic<int> m_starting_height{-1};
280 std::atomic<uint64_t> m_ping_nonce_sent{0};
282 std::atomic<std::chrono::microseconds> m_ping_start{0us};
284 std::atomic<bool> m_ping_queued{
false};
287 std::atomic<bool> m_wtxid_relay{
false};
299 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
301 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
312 std::set<Wtxid> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
316 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
319 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
322 uint64_t m_last_inv_sequence
GUARDED_BY(m_tx_inventory_mutex){1};
325 std::atomic<CAmount> m_fee_filter_received{0};
331 LOCK(m_tx_relay_mutex);
333 m_tx_relay = std::make_unique<Peer::TxRelay>();
334 return m_tx_relay.get();
339 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
368 std::atomic_bool m_addr_relay_enabled{
false};
372 mutable Mutex m_addr_send_times_mutex;
374 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
376 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
379 std::atomic_bool m_wants_addrv2{
false};
388 std::atomic<uint64_t> m_addr_rate_limited{0};
390 std::atomic<uint64_t> m_addr_processed{0};
396 Mutex m_getdata_requests_mutex;
398 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
404 Mutex m_headers_sync_mutex;
407 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
410 std::atomic<bool> m_sent_sendheaders{
false};
420 std::atomic<std::chrono::seconds> m_time_offset{0
s};
424 , m_our_services{our_services}
425 , m_is_inbound{is_inbound}
429 mutable Mutex m_tx_relay_mutex;
432 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
435using PeerRef = std::shared_ptr<Peer>;
447 uint256 hashLastUnknownBlock{};
453 bool fSyncStarted{
false};
455 std::chrono::microseconds m_stalling_since{0us};
456 std::list<QueuedBlock> vBlocksInFlight;
458 std::chrono::microseconds m_downloading_since{0us};
460 bool fPreferredDownload{
false};
462 bool m_requested_hb_cmpctblocks{
false};
464 bool m_provides_cmpctblocks{
false};
490 struct ChainSyncTimeoutState {
492 std::chrono::seconds m_timeout{0
s};
496 bool m_sent_getheaders{
false};
498 bool m_protect{
false};
501 ChainSyncTimeoutState m_chain_sync;
504 int64_t m_last_block_announcement{0};
533 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
548 void SetBestBlock(
int height,
std::chrono::seconds time)
override
550 m_best_height = height;
551 m_best_block_time = time;
555 std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
556 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
571 void ReattemptPrivateBroadcast(
CScheduler& scheduler);
583 void Misbehaving(Peer& peer,
const std::string& message);
594 bool via_compact_block,
const std::string& message =
"")
603 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
617 bool first_time_failure)
642 bool ProcessOrphanTx(Peer& peer)
652 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
654 bool via_compact_block)
658 bool CheckHeadersPoW(const
std::vector<
CBlockHeader>& headers, Peer& peer);
666 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
685 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
699 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
714 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
716 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
723 template <
typename... Args>
724 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
730 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
736 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
779 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
782 std::atomic<int> m_best_height{-1};
784 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
792 const Options m_opts;
794 bool RejectIncomingTxs(
const CNode& peer)
const;
802 mutable Mutex m_peer_mutex;
809 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
819 uint32_t GetFetchFlags(
const Peer& peer)
const;
821 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
838 std::atomic<int> m_wtxid_relay_peers{0};
856 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
857 std::chrono::seconds average_interval,
862 Mutex m_most_recent_block_mutex;
863 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
864 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
866 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
870 Mutex m_headers_presync_mutex;
878 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
880 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
884 std::atomic_bool m_headers_presync_should_signal{
false};
954 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
960 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
965 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
998 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
1000 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1012 int64_t ApproximateBestBlockDepth() const;
1022 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1040 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1042 const
uint256& stop_hash, uint32_t max_height_diff,
1090 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1096const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const
1098 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1099 if (it == m_node_states.end())
1106 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1114static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1119void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1121 assert(peer.m_addr_known);
1122 peer.m_addr_known->insert(addr.
GetKey());
1125void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1130 assert(peer.m_addr_known);
1131 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1133 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1135 peer.m_addrs_to_send.push_back(addr);
1140static void AddKnownTx(Peer& peer,
const uint256& hash)
1142 auto tx_relay = peer.GetTxRelay();
1143 if (!tx_relay)
return;
1145 LOCK(tx_relay->m_tx_inventory_mutex);
1146 tx_relay->m_tx_inventory_known_filter.insert(hash);
1150static bool CanServeBlocks(
const Peer& peer)
1157static bool IsLimitedPeer(
const Peer& peer)
1164static bool CanServeWitnesses(
const Peer& peer)
1169std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1170 std::chrono::seconds average_interval,
1171 uint64_t network_key)
1173 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1174 auto& timer{it->second};
1176 timer = now + m_rng.rand_exp_duration(average_interval);
1181bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1183 return mapBlocksInFlight.contains(hash);
1186bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1188 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1189 auto [nodeid, block_it] = range.first->second;
1190 PeerRef peer{GetPeerRef(nodeid)};
1191 if (peer && !peer->m_is_inbound)
return true;
1197void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1199 auto range = mapBlocksInFlight.equal_range(hash);
1200 if (range.first == range.second) {
1208 while (range.first != range.second) {
1209 const auto& [node_id, list_it]{range.first->second};
1211 if (from_peer && *from_peer != node_id) {
1218 if (state.vBlocksInFlight.begin() == list_it) {
1220 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1222 state.vBlocksInFlight.erase(list_it);
1224 if (state.vBlocksInFlight.empty()) {
1226 m_peers_downloading_from--;
1228 state.m_stalling_since = 0us;
1230 range.first = mapBlocksInFlight.erase(range.first);
1234bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1238 CNodeState *state =
State(nodeid);
1239 assert(state !=
nullptr);
1244 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1245 if (range.first->second.first == nodeid) {
1247 *pit = &range.first->second.second;
1254 RemoveBlockRequest(hash, nodeid);
1256 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1257 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1258 if (state->vBlocksInFlight.size() == 1) {
1260 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1261 m_peers_downloading_from++;
1263 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1265 *pit = &itInFlight->second.second;
1270void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1277 if (m_opts.ignore_incoming_txs)
return;
1279 CNodeState* nodestate =
State(nodeid);
1280 PeerRef peer{GetPeerRef(nodeid)};
1281 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1286 int num_outbound_hb_peers = 0;
1287 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1288 if (*it == nodeid) {
1289 lNodesAnnouncingHeaderAndIDs.erase(it);
1290 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1293 PeerRef peer_ref{GetPeerRef(*it)};
1294 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1296 if (peer && peer->m_is_inbound) {
1299 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1300 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1301 if (remove_peer && !remove_peer->m_is_inbound) {
1304 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1310 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1313 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1314 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1316 pnodeStop->m_bip152_highbandwidth_to = false;
1319 lNodesAnnouncingHeaderAndIDs.pop_front();
1324 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1329bool PeerManagerImpl::TipMayBeStale()
1333 if (m_last_tip_update.load() == 0
s) {
1334 m_last_tip_update = GetTime<std::chrono::seconds>();
1336 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1339int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1344bool PeerManagerImpl::CanDirectFetch()
1351 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1353 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1358void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1359 CNodeState *state =
State(nodeid);
1360 assert(state !=
nullptr);
1362 if (!state->hashLastUnknownBlock.IsNull()) {
1365 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1366 state->pindexBestKnownBlock = pindex;
1368 state->hashLastUnknownBlock.SetNull();
1373void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1374 CNodeState *state =
State(nodeid);
1375 assert(state !=
nullptr);
1377 ProcessBlockAvailability(nodeid);
1382 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1383 state->pindexBestKnownBlock = pindex;
1387 state->hashLastUnknownBlock = hash;
1392void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1397 vBlocks.reserve(vBlocks.size() +
count);
1398 CNodeState *state =
State(peer.m_id);
1399 assert(state !=
nullptr);
1402 ProcessBlockAvailability(peer.m_id);
1404 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1415 state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1416 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1425 if (state->pindexLastCommonBlock ==
nullptr ||
1426 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1427 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1428 state->pindexLastCommonBlock = fork_point;
1430 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1433 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1439 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1442void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1447 if (vBlocks.size() >=
count) {
1451 vBlocks.reserve(
count);
1454 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1471void 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)
1473 std::vector<const CBlockIndex*> vToFetch;
1474 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1475 bool is_limited_peer = IsLimitedPeer(peer);
1477 while (pindexWalk->
nHeight < nMaxHeight) {
1481 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1482 vToFetch.resize(nToFetch);
1483 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1484 vToFetch[nToFetch - 1] = pindexWalk;
1485 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1486 vToFetch[i - 1] = vToFetch[i]->
pprev;
1506 state->pindexLastCommonBlock = pindex;
1513 if (waitingfor == -1) {
1515 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1521 if (pindex->
nHeight > nWindowEnd) {
1523 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1525 if (nodeStaller) *nodeStaller = waitingfor;
1535 vBlocks.push_back(pindex);
1536 if (vBlocks.size() ==
count) {
1545void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1547 uint64_t my_services;
1549 uint64_t your_services;
1551 std::string my_user_agent;
1559 my_user_agent =
"/pynode:0.0.1/";
1561 my_tx_relay =
false;
1564 my_services = peer.m_our_services;
1569 my_height = m_best_height;
1570 my_tx_relay = !RejectIncomingTxs(pnode);
1589 BCLog::NET,
"send version message: version=%d, blocks=%d%s, txrelay=%d, peer=%d\n",
1592 my_tx_relay, pnode.
GetId());
1595void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1599 if (state) state->m_last_block_announcement = time_in_seconds;
1607 m_node_states.try_emplace(m_node_states.end(), nodeid);
1609 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1615 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1618 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1622void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1626 for (
const auto& txid : unbroadcast_txids) {
1629 if (tx !=
nullptr) {
1630 InitiateTxBroadcastToAll(txid, tx->GetWitnessHash());
1639 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1642void PeerManagerImpl::ReattemptPrivateBroadcast(
CScheduler& scheduler)
1646 size_t num_for_rebroadcast{0};
1647 const auto stale_txs = m_tx_for_private_broadcast.
GetStale();
1648 if (!stale_txs.empty()) {
1650 for (
const auto& stale_tx : stale_txs) {
1654 "Reattempting broadcast of stale txid=%s wtxid=%s",
1655 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString());
1656 ++num_for_rebroadcast;
1659 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString(),
1660 mempool_acceptable.m_state.ToString());
1661 m_tx_for_private_broadcast.
Remove(stale_tx);
1670 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, delta);
1673void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1684 PeerRef peer = RemovePeer(nodeid);
1686 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1687 assert(m_wtxid_relay_peers >= 0);
1689 CNodeState *state =
State(nodeid);
1690 assert(state !=
nullptr);
1692 if (state->fSyncStarted)
1695 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1696 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1697 while (range.first != range.second) {
1698 auto [node_id, list_it] = range.first->second;
1699 if (node_id != nodeid) {
1702 range.first = mapBlocksInFlight.erase(range.first);
1707 LOCK(m_tx_download_mutex);
1708 m_txdownloadman.DisconnectedPeer(nodeid);
1710 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1711 m_num_preferred_download_peers -= state->fPreferredDownload;
1712 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1713 assert(m_peers_downloading_from >= 0);
1714 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1715 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1717 m_node_states.erase(nodeid);
1719 if (m_node_states.empty()) {
1721 assert(mapBlocksInFlight.empty());
1722 assert(m_num_preferred_download_peers == 0);
1723 assert(m_peers_downloading_from == 0);
1724 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1725 assert(m_wtxid_relay_peers == 0);
1726 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1729 if (
node.fSuccessfullyConnected &&
1730 !
node.IsBlockOnlyConn() && !
node.IsPrivateBroadcastConn() && !
node.IsInboundConn()) {
1738 LOCK(m_headers_presync_mutex);
1739 m_headers_presync_stats.erase(nodeid);
1741 if (
node.IsPrivateBroadcastConn() &&
1750bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1753 return !(GetDesirableServiceFlags(services) & (~services));
1767PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1770 auto it = m_peer_map.find(
id);
1771 return it != m_peer_map.end() ? it->second :
nullptr;
1774PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1778 auto it = m_peer_map.find(
id);
1779 if (it != m_peer_map.end()) {
1780 ret = std::move(it->second);
1781 m_peer_map.erase(it);
1790 const CNodeState* state =
State(nodeid);
1791 if (state ==
nullptr)
1793 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1794 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1795 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1801 PeerRef peer = GetPeerRef(nodeid);
1802 if (peer ==
nullptr)
return false;
1811 auto ping_wait{0us};
1812 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1813 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1816 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1819 LOCK(tx_relay->m_tx_inventory_mutex);
1821 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1833 LOCK(peer->m_headers_sync_mutex);
1834 if (peer->m_headers_sync) {
1843std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1845 LOCK(m_tx_download_mutex);
1846 return m_txdownloadman.GetOrphanTransactions();
1853 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1857void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1859 if (m_opts.max_extra_txs <= 0)
1861 if (!vExtraTxnForCompact.size())
1862 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1863 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1864 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1867void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1869 LOCK(peer.m_misbehavior_mutex);
1871 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1872 peer.m_should_discourage =
true;
1881 bool via_compact_block,
const std::string& message)
1883 PeerRef peer{GetPeerRef(nodeid)};
1894 if (!via_compact_block) {
1895 if (peer) Misbehaving(*peer, message);
1903 if (peer && !via_compact_block && !peer->m_is_inbound) {
1904 if (peer) Misbehaving(*peer, message);
1911 if (peer) Misbehaving(*peer, message);
1915 if (peer) Misbehaving(*peer, message);
1920 if (message !=
"") {
1925bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1939 PeerRef peer = GetPeerRef(peer_id);
1948 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1951 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
1974 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1980 : m_rng{opts.deterministic_rng},
1982 m_chainparams(chainman.GetParams()),
1986 m_chainman(chainman),
1988 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
1989 m_warnings{warnings},
1994 if (opts.reconcile_txs) {
1999void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2010 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2012 if (m_opts.private_broadcast) {
2013 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2017void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2025 LOCK(m_tx_download_mutex);
2029 m_txdownloadman.ActiveTipChange();
2039void PeerManagerImpl::BlockConnected(
2041 const std::shared_ptr<const CBlock>& pblock,
2046 m_last_tip_update = GetTime<std::chrono::seconds>();
2049 auto stalling_timeout = m_block_stalling_timeout.load();
2053 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2063 LOCK(m_tx_download_mutex);
2064 m_txdownloadman.BlockConnected(pblock);
2067void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2069 LOCK(m_tx_download_mutex);
2070 m_txdownloadman.BlockDisconnected();
2077void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2079 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2083 if (pindex->
nHeight <= m_highest_fast_announce)
2085 m_highest_fast_announce = pindex->
nHeight;
2089 uint256 hashBlock(pblock->GetHash());
2090 const std::shared_future<CSerializedNetMsg> lazy_ser{
2094 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2095 for (
const auto& tx : pblock->vtx) {
2096 most_recent_block_txs->emplace(tx->GetHash(), tx);
2097 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2100 LOCK(m_most_recent_block_mutex);
2101 m_most_recent_block_hash = hashBlock;
2102 m_most_recent_block = pblock;
2103 m_most_recent_compact_block = pcmpctblock;
2104 m_most_recent_block_txs = std::move(most_recent_block_txs);
2112 ProcessBlockAvailability(pnode->
GetId());
2116 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2118 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2119 hashBlock.ToString(), pnode->
GetId());
2122 PushMessage(*pnode, ser_cmpctblock.Copy());
2123 state.pindexBestHeaderSent = pindex;
2132void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2134 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2137 if (fInitialDownload)
return;
2140 std::vector<uint256> vHashes;
2142 while (pindexToAnnounce != pindexFork) {
2144 pindexToAnnounce = pindexToAnnounce->
pprev;
2154 for (
auto& it : m_peer_map) {
2155 Peer& peer = *it.second;
2156 LOCK(peer.m_block_inv_mutex);
2157 for (
const uint256& hash : vHashes | std::views::reverse) {
2158 peer.m_blocks_for_headers_relay.push_back(hash);
2170void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2174 const uint256 hash(block->GetHash());
2175 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2180 it != mapBlockSource.end() &&
2181 State(it->second.first)) {
2182 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2192 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2193 if (it != mapBlockSource.end()) {
2194 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2197 if (it != mapBlockSource.end())
2198 mapBlockSource.erase(it);
2206bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2211void PeerManagerImpl::SendPings()
2214 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2217void PeerManagerImpl::InitiateTxBroadcastToAll(
const Txid& txid,
const Wtxid& wtxid)
2220 for(
auto& it : m_peer_map) {
2221 Peer& peer = *it.second;
2222 auto tx_relay = peer.GetTxRelay();
2223 if (!tx_relay)
continue;
2225 LOCK(tx_relay->m_tx_inventory_mutex);
2231 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2234 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2235 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2240void PeerManagerImpl::InitiateTxBroadcastPrivate(
const CTransactionRef& tx)
2242 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2243 if (m_tx_for_private_broadcast.
Add(tx)) {
2251void PeerManagerImpl::RelayAddress(
NodeId originator,
2267 const auto current_time{GetTime<std::chrono::seconds>()};
2275 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2277 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2278 assert(nRelayNodes <= best.size());
2282 for (
auto& [
id, peer] : m_peer_map) {
2283 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2285 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2286 if (hashKey > best[i].first) {
2287 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2288 best[i] = std::make_pair(hashKey, peer.get());
2295 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2296 PushAddress(*best[i].second, addr);
2300void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2302 std::shared_ptr<const CBlock> a_recent_block;
2303 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2305 LOCK(m_most_recent_block_mutex);
2306 a_recent_block = m_most_recent_block;
2307 a_recent_compact_block = m_most_recent_compact_block;
2310 bool need_activate_chain =
false;
2322 need_activate_chain =
true;
2326 if (need_activate_chain) {
2328 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2335 bool can_direct_fetch{
false};
2343 if (!BlockRequestAllowed(pindex)) {
2344 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2371 can_direct_fetch = CanDirectFetch();
2375 std::shared_ptr<const CBlock> pblock;
2376 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2377 pblock = a_recent_block;
2395 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2405 pblock = pblockRead;
2413 bool sendMerkleBlock =
false;
2415 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2416 LOCK(tx_relay->m_bloom_filter_mutex);
2417 if (tx_relay->m_bloom_filter) {
2418 sendMerkleBlock =
true;
2419 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2422 if (sendMerkleBlock) {
2430 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2441 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2454 LOCK(peer.m_block_inv_mutex);
2456 if (inv.
hash == peer.m_continuation_block) {
2460 std::vector<CInv> vInv;
2461 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2463 peer.m_continuation_block.SetNull();
2471 auto txinfo{std::visit(
2472 [&](
const auto&
id) {
2473 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2477 return std::move(txinfo.tx);
2482 LOCK(m_most_recent_block_mutex);
2483 if (m_most_recent_block_txs !=
nullptr) {
2484 auto it = m_most_recent_block_txs->find(gtxid);
2485 if (it != m_most_recent_block_txs->end())
return it->second;
2492void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2496 auto tx_relay = peer.GetTxRelay();
2498 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2499 std::vector<CInv> vNotFound;
2504 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2505 if (interruptMsgProc)
return;
2510 const CInv &inv = *it++;
2512 if (tx_relay ==
nullptr) {
2518 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2521 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2524 vNotFound.push_back(inv);
2530 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2531 const CInv &inv = *it++;
2533 ProcessGetBlockData(pfrom, peer, inv);
2542 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2544 if (!vNotFound.empty()) {
2563uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2565 uint32_t nFetchFlags = 0;
2566 if (CanServeWitnesses(peer)) {
2575 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2577 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2584 uint32_t tx_requested_size{0};
2585 for (
const auto& tx : resp.txn) tx_requested_size += tx->ComputeTotalSize();
2591bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2595 Misbehaving(peer,
"header with invalid proof of work");
2600 if (!CheckHeadersAreContinuous(headers)) {
2601 Misbehaving(peer,
"non-continuous headers sequence");
2626void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2627 const std::vector<CBlockHeader>& headers)
2631 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2632 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2634 headers[0].hashPrevBlock.ToString(),
2635 best_header->nHeight,
2645bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2649 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2652 hashLastBlock = header.GetHash();
2657bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2659 if (peer.m_headers_sync) {
2660 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2662 if (result.success) peer.m_last_getheaders_timestamp = {};
2663 if (result.request_more) {
2664 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2666 Assume(!locator.vHave.empty());
2669 if (!locator.vHave.empty()) {
2672 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2675 locator.vHave.front().ToString(), pfrom.
GetId());
2680 peer.m_headers_sync.reset(
nullptr);
2685 LOCK(m_headers_presync_mutex);
2686 m_headers_presync_stats.erase(pfrom.
GetId());
2689 HeadersPresyncStats stats;
2690 stats.first = peer.m_headers_sync->GetPresyncWork();
2692 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2693 peer.m_headers_sync->GetPresyncTime()};
2697 LOCK(m_headers_presync_mutex);
2698 m_headers_presync_stats[pfrom.
GetId()] = stats;
2699 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2700 bool best_updated =
false;
2701 if (best_it == m_headers_presync_stats.end()) {
2705 const HeadersPresyncStats* stat_best{
nullptr};
2706 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2707 if (!stat_best || stat > *stat_best) {
2712 m_headers_presync_bestpeer = peer_best;
2713 best_updated = (peer_best == pfrom.
GetId());
2714 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2716 m_headers_presync_bestpeer = pfrom.
GetId();
2717 best_updated =
true;
2719 if (best_updated && stats.second.has_value()) {
2721 m_headers_presync_should_signal =
true;
2725 if (result.success) {
2728 headers.swap(result.pow_validated_headers);
2731 return result.success;
2739bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
2746 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2750 if (total_work < minimum_chain_work) {
2754 if (headers.size() == m_opts.max_headers_result) {
2764 LOCK(peer.m_headers_sync_mutex);
2766 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2771 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2785bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2787 if (header ==
nullptr) {
2789 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2797bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2805 peer.m_last_getheaders_timestamp = current_time;
2816void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2819 CNodeState *nodestate =
State(pfrom.
GetId());
2822 std::vector<const CBlockIndex*> vToFetch;
2830 vToFetch.push_back(pindexWalk);
2832 pindexWalk = pindexWalk->
pprev;
2843 std::vector<CInv> vGetData;
2845 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2850 uint32_t nFetchFlags = GetFetchFlags(peer);
2852 BlockRequested(pfrom.
GetId(), *pindex);
2856 if (vGetData.size() > 1) {
2861 if (vGetData.size() > 0) {
2862 if (!m_opts.ignore_incoming_txs &&
2863 nodestate->m_provides_cmpctblocks &&
2864 vGetData.size() == 1 &&
2865 mapBlocksInFlight.size() == 1 &&
2881void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2882 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2885 CNodeState *nodestate =
State(pfrom.
GetId());
2894 nodestate->m_last_block_announcement =
GetTime();
2902 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2924 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) {
2926 nodestate->m_chain_sync.m_protect =
true;
2927 ++m_outbound_peers_with_protect_from_disconnect;
2932void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2933 std::vector<CBlockHeader>&& headers,
2934 bool via_compact_block)
2936 size_t nCount = headers.size();
2943 LOCK(peer.m_headers_sync_mutex);
2944 if (peer.m_headers_sync) {
2945 peer.m_headers_sync.reset(
nullptr);
2946 LOCK(m_headers_presync_mutex);
2947 m_headers_presync_stats.erase(pfrom.
GetId());
2951 peer.m_last_getheaders_timestamp = {};
2959 if (!CheckHeadersPoW(headers, peer)) {
2974 bool already_validated_work =
false;
2977 bool have_headers_sync =
false;
2979 LOCK(peer.m_headers_sync_mutex);
2981 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2993 if (headers.empty()) {
2997 have_headers_sync = !!peer.m_headers_sync;
3002 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3004 if (!headers_connect_blockindex) {
3008 HandleUnconnectingHeaders(pfrom, peer, headers);
3015 peer.m_last_getheaders_timestamp = {};
3025 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3032 already_validated_work =
true;
3038 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3039 *chain_start_header, headers)) {
3051 bool received_new_header{last_received_header ==
nullptr};
3057 state, &pindexLast)};
3063 "If this happens with all peers, consider database corruption (that -reindex may fix) "
3064 "or a potential consensus incompatibility.",
3067 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3073 if (processed && received_new_header) {
3074 LogBlockHeader(*pindexLast, pfrom,
false);
3078 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3080 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3082 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
3086 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3089 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3095 bool first_time_failure)
3101 PeerRef peer{GetPeerRef(nodeid)};
3104 ptx->GetHash().ToString(),
3105 ptx->GetWitnessHash().ToString(),
3109 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3112 AddToCompactExtraTransactions(ptx);
3114 for (
const Txid& parent_txid : unique_parents) {
3115 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3118 return package_to_validate;
3121void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3127 m_txdownloadman.MempoolAcceptedTx(tx);
3131 tx->GetHash().ToString(),
3132 tx->GetWitnessHash().ToString(),
3135 InitiateTxBroadcastToAll(tx->GetHash(), tx->GetWitnessHash());
3138 AddToCompactExtraTransactions(removedTx);
3148 const auto&
package = package_to_validate.m_txns;
3149 const auto& senders = package_to_validate.
m_senders;
3152 m_txdownloadman.MempoolRejectedPackage(package);
3155 if (!
Assume(package.size() == 2))
return;
3159 auto package_iter = package.rbegin();
3160 auto senders_iter = senders.rbegin();
3161 while (package_iter != package.rend()) {
3162 const auto& tx = *package_iter;
3163 const NodeId nodeid = *senders_iter;
3164 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3168 const auto& tx_result = it_result->second;
3169 switch (tx_result.m_result_type) {
3172 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3182 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3200bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3207 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3210 const Txid& orphanHash = porphanTx->GetHash();
3211 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3228 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3237bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3239 const uint256& stop_hash, uint32_t max_height_diff,
3243 const bool supported_filter_type =
3246 if (!supported_filter_type) {
3248 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg(
fLogIPs));
3249 node.fDisconnect =
true;
3258 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3261 node.fDisconnect =
true;
3266 uint32_t stop_height = stop_index->
nHeight;
3267 if (start_height > stop_height) {
3269 "start height %d and stop height %d, %s\n",
3270 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3271 node.fDisconnect =
true;
3274 if (stop_height - start_height >= max_height_diff) {
3276 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3277 node.fDisconnect =
true;
3282 if (!filter_index) {
3292 uint8_t filter_type_ser;
3293 uint32_t start_height;
3296 vRecv >> filter_type_ser >> start_height >> stop_hash;
3302 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3307 std::vector<BlockFilter> filters;
3309 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3314 for (
const auto& filter : filters) {
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,
3337 if (start_height > 0) {
3339 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3341 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3347 std::vector<uint256> filter_hashes;
3349 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3363 uint8_t filter_type_ser;
3366 vRecv >> filter_type_ser >> stop_hash;
3372 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3373 std::numeric_limits<uint32_t>::max(),
3374 stop_index, filter_index)) {
3382 for (
int i = headers.size() - 1; i >= 0; i--) {
3387 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3401 bool new_block{
false};
3402 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3404 node.m_last_block_time = GetTime<std::chrono::seconds>();
3409 RemoveBlockRequest(block->GetHash(), std::nullopt);
3412 mapBlockSource.erase(block->GetHash());
3416void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3418 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3419 bool fBlockRead{
false};
3423 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3424 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3425 bool requested_block_from_this_peer{
false};
3428 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3430 while (range_flight.first != range_flight.second) {
3431 auto [node_id, block_it] = range_flight.first->second;
3432 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3433 requested_block_from_this_peer =
true;
3436 range_flight.first++;
3439 if (!requested_block_from_this_peer) {
3451 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3462 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3465 if (first_in_flight) {
3470 std::vector<CInv> invs;
3475 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3488 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3503void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3515 "Saw new %sheader hash=%s height=%d peer=%d%s",
3516 via_compact_block ?
"cmpctblock " :
"",
3529void PeerManagerImpl::PushPrivateBroadcastTx(
CNode&
node)
3536 node.fDisconnect =
true;
3542 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3548void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3549 const std::chrono::microseconds time_received,
3550 const std::atomic<bool>& interruptMsgProc)
3556 PeerRef peer = GetPeerRef(pfrom.
GetId());
3557 if (peer ==
nullptr)
return;
3567 uint64_t nNonce = 1;
3570 std::string cleanSubVer;
3571 int starting_height = -1;
3574 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3589 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3591 GetDesirableServiceFlags(nServices),
3604 if (!vRecv.
empty()) {
3612 if (!vRecv.
empty()) {
3613 std::string strSubVer;
3617 if (!vRecv.
empty()) {
3618 vRecv >> starting_height;
3638 PushNodeVersion(pfrom, *peer);
3647 peer->m_their_services = nServices;
3651 pfrom.cleanSubVer = cleanSubVer;
3653 peer->m_starting_height = starting_height;
3663 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3664 auto*
const tx_relay = peer->SetTxRelay();
3666 LOCK(tx_relay->m_bloom_filter_mutex);
3667 tx_relay->m_relay_txs = fRelay;
3673 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3694 if (greatest_common_version >= 70016) {
3709 const auto* tx_relay = peer->GetTxRelay();
3710 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3712 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3725 m_num_preferred_download_peers += state->fPreferredDownload;
3731 bool send_getaddr{
false};
3733 send_getaddr = SetupAddressRelay(pfrom, *peer);
3743 peer->m_getaddr_sent =
true;
3767 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3771 m_outbound_time_offsets.Add(peer->m_time_offset);
3772 m_outbound_time_offsets.WarnIfOutOfSync();
3776 if (greatest_common_version <= 70012) {
3777 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3778 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3801 auto new_peer_msg = [&]() {
3803 return strprintf(
"New %s peer connected: transport: %s, version: %d, blocks=%d peer=%d%s%s\n",
3806 pfrom.
nVersion.load(), peer->m_starting_height,
3808 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3816 LogInfo(
"%s", new_peer_msg());
3819 if (
auto tx_relay = peer->GetTxRelay()) {
3828 tx_relay->m_tx_inventory_mutex,
3829 return tx_relay->m_tx_inventory_to_send.empty() &&
3830 tx_relay->m_next_inv_send_time == 0
s));
3840 PushPrivateBroadcastTx(pfrom);
3853 if (m_txreconciliation) {
3854 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3858 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3864 const CNodeState* state =
State(pfrom.
GetId());
3866 .m_preferred = state->fPreferredDownload,
3867 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3868 .m_wtxid_relay = peer->m_wtxid_relay,
3877 peer->m_prefers_headers =
true;
3882 bool sendcmpct_hb{
false};
3883 uint64_t sendcmpct_version{0};
3884 vRecv >> sendcmpct_hb >> sendcmpct_version;
3890 CNodeState* nodestate =
State(pfrom.
GetId());
3891 nodestate->m_provides_cmpctblocks =
true;
3892 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3909 if (!peer->m_wtxid_relay) {
3910 peer->m_wtxid_relay =
true;
3911 m_wtxid_relay_peers++;
3930 peer->m_wants_addrv2 =
true;
3938 if (!m_txreconciliation) {
3939 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3950 if (RejectIncomingTxs(pfrom)) {
3959 const auto* tx_relay = peer->GetTxRelay();
3960 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3966 uint32_t peer_txreconcl_version;
3967 uint64_t remote_salt;
3968 vRecv >> peer_txreconcl_version >> remote_salt;
3971 peer_txreconcl_version, remote_salt);
4003 const auto ser_params{
4011 std::vector<CAddress> vAddr;
4013 vRecv >> ser_params(vAddr);
4015 if (!SetupAddressRelay(pfrom, *peer)) {
4022 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
4027 std::vector<CAddress> vAddrOk;
4028 const auto current_a_time{Now<NodeSeconds>()};
4031 const auto current_time{GetTime<std::chrono::microseconds>()};
4034 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
4038 peer->m_addr_token_timestamp = current_time;
4041 uint64_t num_proc = 0;
4042 uint64_t num_rate_limit = 0;
4043 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
4046 if (interruptMsgProc)
4050 if (peer->m_addr_token_bucket < 1.0) {
4056 peer->m_addr_token_bucket -= 1.0;
4065 addr.
nTime = current_a_time - 5 * 24h;
4067 AddAddressKnown(*peer, addr);
4074 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
4076 RelayAddress(pfrom.
GetId(), addr, reachable);
4080 vAddrOk.push_back(addr);
4083 peer->m_addr_processed += num_proc;
4084 peer->m_addr_rate_limited += num_rate_limit;
4085 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
4086 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
4088 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
4089 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
4100 std::vector<CInv> vInv;
4104 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
4108 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4112 const auto current_time{GetTime<std::chrono::microseconds>()};
4115 for (
CInv& inv : vInv) {
4116 if (interruptMsgProc)
return;
4121 if (peer->m_wtxid_relay) {
4128 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4131 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4139 best_block = &inv.
hash;
4142 if (reject_tx_invs) {
4148 AddKnownTx(*peer, inv.
hash);
4151 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4159 if (best_block !=
nullptr) {
4171 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4172 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
4174 m_chainman.m_best_header->nHeight, best_block->ToString(),
4177 if (!state.fSyncStarted) {
4178 peer->m_inv_triggered_getheaders_before_sync =
true;
4182 m_last_block_inv_triggering_headers_sync = *best_block;
4191 std::vector<CInv> vInv;
4195 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
4201 if (vInv.size() > 0) {
4206 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4207 if (!pushed_tx_opt) {
4218 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4222 peer->m_ping_queued =
true;
4223 MaybeSendPing(pfrom, *peer, GetTime<std::chrono::microseconds>());
4233 LOCK(peer->m_getdata_requests_mutex);
4234 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
4235 ProcessGetData(pfrom, *peer, interruptMsgProc);
4244 vRecv >> locator >> hashStop;
4260 std::shared_ptr<const CBlock> a_recent_block;
4262 LOCK(m_most_recent_block_mutex);
4263 a_recent_block = m_most_recent_block;
4266 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4281 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4296 if (--nLimit <= 0) {
4300 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4312 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4316 std::shared_ptr<const CBlock> recent_block;
4318 LOCK(m_most_recent_block_mutex);
4319 if (m_most_recent_block_hash == req.
blockhash)
4320 recent_block = m_most_recent_block;
4324 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4343 if (!block_pos.IsNull()) {
4350 SendBlockTransactions(pfrom, *peer, block, req);
4363 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4371 vRecv >> locator >> hashStop;
4389 if (m_chainman.
ActiveTip() ==
nullptr ||
4391 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4398 CNodeState *nodestate =
State(pfrom.
GetId());
4408 if (!BlockRequestAllowed(pindex)) {
4409 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4422 std::vector<CBlock> vHeaders;
4423 int nLimit = m_opts.max_headers_result;
4425 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4428 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4443 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4449 if (RejectIncomingTxs(pfrom)) {
4463 const Txid& txid = ptx->GetHash();
4464 const Wtxid& wtxid = ptx->GetWitnessHash();
4467 AddKnownTx(*peer, hash);
4469 if (
const auto num_broadcasted{m_tx_for_private_broadcast.
Remove(ptx)}) {
4471 "network from peer=%d%s; stopping private broadcast attempts",
4482 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4483 if (!should_validate) {
4488 if (!m_mempool.
exists(txid)) {
4489 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4492 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4494 InitiateTxBroadcastToAll(txid, wtxid);
4498 if (package_to_validate) {
4501 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4502 ProcessPackageResult(package_to_validate.value(), package_result);
4508 Assume(!package_to_validate.has_value());
4518 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4521 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4522 ProcessPackageResult(package_to_validate.value(), package_result);
4538 vRecv >> cmpctblock;
4540 bool received_new_header =
false;
4550 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4560 received_new_header =
true;
4568 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4575 if (received_new_header) {
4576 LogBlockHeader(*pindex, pfrom,
true);
4579 bool fProcessBLOCKTXN =
false;
4583 bool fRevertToHeaderProcessing =
false;
4587 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4588 bool fBlockReconstructed =
false;
4594 CNodeState *nodestate =
State(pfrom.
GetId());
4599 nodestate->m_last_block_announcement =
GetTime();
4605 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4606 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4607 bool requested_block_from_this_peer{
false};
4610 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4612 while (range_flight.first != range_flight.second) {
4613 if (range_flight.first->second.first == pfrom.
GetId()) {
4614 requested_block_from_this_peer =
true;
4617 range_flight.first++;
4622 if (requested_block_from_this_peer) {
4625 std::vector<CInv> vInv(1);
4626 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4633 if (!already_in_flight && !CanDirectFetch()) {
4641 requested_block_from_this_peer) {
4642 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4643 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4644 if (!(*queuedBlockIt)->partialBlock)
4657 Misbehaving(*peer,
"invalid compact block");
4660 if (first_in_flight) {
4662 std::vector<CInv> vInv(1);
4663 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4673 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4678 fProcessBLOCKTXN =
true;
4679 }
else if (first_in_flight) {
4686 IsBlockRequestedFromOutbound(blockhash) ||
4705 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4710 std::vector<CTransactionRef> dummy;
4712 status = tempBlock.FillBlock(*pblock, dummy,
4715 fBlockReconstructed =
true;
4719 if (requested_block_from_this_peer) {
4722 std::vector<CInv> vInv(1);
4723 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4728 fRevertToHeaderProcessing =
true;
4733 if (fProcessBLOCKTXN) {
4736 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4739 if (fRevertToHeaderProcessing) {
4745 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4748 if (fBlockReconstructed) {
4753 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4771 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4788 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4799 std::vector<CBlockHeader> headers;
4803 if (nCount > m_opts.max_headers_result) {
4804 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4807 headers.resize(nCount);
4808 for (
unsigned int n = 0; n < nCount; n++) {
4809 vRecv >> headers[n];
4813 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4817 if (m_headers_presync_should_signal.exchange(
false)) {
4818 HeadersPresyncStats stats;
4820 LOCK(m_headers_presync_mutex);
4821 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4822 if (it != m_headers_presync_stats.end()) stats = it->second;
4840 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4851 Misbehaving(*peer,
"mutated block");
4856 bool forceProcessing =
false;
4857 const uint256 hash(pblock->GetHash());
4858 bool min_pow_checked =
false;
4863 forceProcessing = IsBlockRequested(hash);
4864 RemoveBlockRequest(hash, pfrom.
GetId());
4868 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4872 min_pow_checked =
true;
4875 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4892 Assume(SetupAddressRelay(pfrom, *peer));
4896 if (peer->m_getaddr_recvd) {
4900 peer->m_getaddr_recvd =
true;
4902 peer->m_addrs_to_send.clear();
4903 std::vector<CAddress> vAddr;
4909 for (
const CAddress &addr : vAddr) {
4910 PushAddress(*peer, addr);
4938 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4939 LOCK(tx_relay->m_tx_inventory_mutex);
4940 tx_relay->m_send_mempool =
true;
4966 const auto ping_end = time_received;
4969 bool bPingFinished =
false;
4970 std::string sProblem;
4972 if (nAvail >=
sizeof(
nonce)) {
4976 if (peer->m_ping_nonce_sent != 0) {
4977 if (
nonce == peer->m_ping_nonce_sent) {
4979 bPingFinished =
true;
4980 const auto ping_time = ping_end - peer->m_ping_start.load();
4981 if (ping_time.count() >= 0) {
4992 sProblem =
"Timing mishap";
4996 sProblem =
"Nonce mismatch";
4999 bPingFinished =
true;
5000 sProblem =
"Nonce zero";
5004 sProblem =
"Unsolicited pong without ping";
5008 bPingFinished =
true;
5009 sProblem =
"Short payload";
5012 if (!(sProblem.empty())) {
5016 peer->m_ping_nonce_sent,
5020 if (bPingFinished) {
5021 peer->m_ping_nonce_sent = 0;
5038 Misbehaving(*peer,
"too-large bloom filter");
5039 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5041 LOCK(tx_relay->m_bloom_filter_mutex);
5042 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
5043 tx_relay->m_relay_txs =
true;
5057 std::vector<unsigned char> vData;
5065 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5066 LOCK(tx_relay->m_bloom_filter_mutex);
5067 if (tx_relay->m_bloom_filter) {
5068 tx_relay->m_bloom_filter->insert(vData);
5074 Misbehaving(*peer,
"bad filteradd message");
5085 auto tx_relay = peer->GetTxRelay();
5086 if (!tx_relay)
return;
5089 LOCK(tx_relay->m_bloom_filter_mutex);
5090 tx_relay->m_bloom_filter =
nullptr;
5091 tx_relay->m_relay_txs =
true;
5100 vRecv >> newFeeFilter;
5102 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5103 tx_relay->m_fee_filter_received = newFeeFilter;
5111 ProcessGetCFilters(pfrom, *peer, vRecv);
5116 ProcessGetCFHeaders(pfrom, *peer, vRecv);
5121 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
5126 std::vector<CInv> vInv;
5128 std::vector<GenTxid> tx_invs;
5130 for (
CInv &inv : vInv) {
5136 LOCK(m_tx_download_mutex);
5137 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5146bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5149 LOCK(peer.m_misbehavior_mutex);
5152 if (!peer.m_should_discourage)
return false;
5154 peer.m_should_discourage =
false;
5159 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5165 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5185bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
5190 PeerRef peer = GetPeerRef(pfrom->
GetId());
5191 if (peer ==
nullptr)
return false;
5195 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
5198 LOCK(peer->m_getdata_requests_mutex);
5199 if (!peer->m_getdata_requests.empty()) {
5200 ProcessGetData(*pfrom, *peer, interruptMsgProc);
5204 const bool processed_orphan = ProcessOrphanTx(*peer);
5209 if (processed_orphan)
return true;
5214 LOCK(peer->m_getdata_requests_mutex);
5215 if (!peer->m_getdata_requests.empty())
return true;
5228 bool fMoreWork = poll_result->second;
5239 if (m_opts.capture_messages) {
5244 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5245 if (interruptMsgProc)
return false;
5247 LOCK(peer->m_getdata_requests_mutex);
5248 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5255 LOCK(m_tx_download_mutex);
5256 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
5257 }
catch (
const std::exception& e) {
5266void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5279 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5281 if (state.m_chain_sync.m_timeout != 0
s) {
5282 state.m_chain_sync.m_timeout = 0
s;
5283 state.m_chain_sync.m_work_header =
nullptr;
5284 state.m_chain_sync.m_sent_getheaders =
false;
5286 }
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)) {
5294 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5295 state.m_chain_sync.m_sent_getheaders =
false;
5296 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5300 if (state.m_chain_sync.m_sent_getheaders) {
5302 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5305 assert(state.m_chain_sync.m_work_header);
5310 MaybeSendGetHeaders(pto,
5311 GetLocator(state.m_chain_sync.m_work_header->pprev),
5313 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());
5314 state.m_chain_sync.m_sent_getheaders =
true;
5326void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5335 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5339 if (pnode->
GetId() > youngest_peer.first) {
5340 next_youngest_peer = youngest_peer;
5341 youngest_peer.first = pnode->GetId();
5342 youngest_peer.second = pnode->m_last_block_time;
5345 NodeId to_disconnect = youngest_peer.first;
5346 if (youngest_peer.second > next_youngest_peer.second) {
5349 to_disconnect = next_youngest_peer.first;
5358 CNodeState *node_state =
State(pnode->
GetId());
5359 if (node_state ==
nullptr ||
5362 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5366 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5382 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5385 AssertLockHeld(::cs_main);
5389 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5390 CNodeState *state = State(pnode->GetId());
5391 if (state == nullptr) return;
5393 if (state->m_chain_sync.m_protect) return;
5396 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5397 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5398 worst_peer = pnode->GetId();
5399 oldest_block_announcement = state->m_last_block_announcement;
5402 if (worst_peer != -1) {
5413 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5417 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5434void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5438 auto now{GetTime<std::chrono::seconds>()};
5440 EvictExtraOutboundPeers(now);
5442 if (now > m_stale_tip_check_time) {
5446 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5455 if (!m_initial_sync_finished && CanDirectFetch()) {
5457 m_initial_sync_finished =
true;
5461void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5464 peer.m_ping_nonce_sent &&
5474 bool pingSend =
false;
5476 if (peer.m_ping_queued) {
5481 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5490 }
while (
nonce == 0);
5491 peer.m_ping_queued =
false;
5492 peer.m_ping_start = now;
5494 peer.m_ping_nonce_sent =
nonce;
5498 peer.m_ping_nonce_sent = 0;
5504void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5507 if (!peer.m_addr_relay_enabled)
return;
5509 LOCK(peer.m_addr_send_times_mutex);
5512 peer.m_next_local_addr_send < current_time) {
5519 if (peer.m_next_local_addr_send != 0us) {
5520 peer.m_addr_known->reset();
5523 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5524 if (peer.m_next_local_addr_send == 0us) {
5528 if (IsAddrCompatible(peer, local_addr)) {
5529 std::vector<CAddress> self_announcement{local_addr};
5530 if (peer.m_wants_addrv2) {
5538 PushAddress(peer, local_addr);
5545 if (current_time <= peer.m_next_addr_send)
return;
5558 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5559 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5562 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5563 peer.m_addrs_to_send.end());
5566 if (peer.m_addrs_to_send.empty())
return;
5568 if (peer.m_wants_addrv2) {
5573 peer.m_addrs_to_send.clear();
5576 if (peer.m_addrs_to_send.capacity() > 40) {
5577 peer.m_addrs_to_send.shrink_to_fit();
5581void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5589 CNodeState &state = *
State(
node.GetId());
5590 if (state.pindexBestKnownBlock !=
nullptr &&
5597 peer.m_sent_sendheaders =
true;
5602void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5604 if (m_opts.ignore_incoming_txs)
return;
5620 if (peer.m_fee_filter_sent == MAX_FILTER) {
5623 peer.m_next_send_feefilter = 0us;
5626 if (current_time > peer.m_next_send_feefilter) {
5627 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5630 if (filterToSend != peer.m_fee_filter_sent) {
5632 peer.m_fee_filter_sent = filterToSend;
5639 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5645class CompareInvMempoolOrder
5649 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5651 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5660bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5670bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5675 if (
node.IsBlockOnlyConn())
return false;
5677 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5681 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5687bool PeerManagerImpl::SendMessages(
CNode* pto)
5692 PeerRef peer = GetPeerRef(pto->
GetId());
5693 if (!peer)
return false;
5698 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5701 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5702 PushNodeVersion(*pto, *peer);
5703 peer->m_outbound_version_message_sent =
true;
5710 const auto current_time{GetTime<std::chrono::microseconds>()};
5730 MaybeSendPing(*pto, *peer, current_time);
5735 MaybeSendAddr(*pto, *peer, current_time);
5737 MaybeSendSendHeaders(*pto, *peer);
5745 if (m_chainman.m_best_header ==
nullptr) {
5752 bool sync_blocks_and_headers_from_peer =
false;
5753 if (state.fPreferredDownload) {
5754 sync_blocks_and_headers_from_peer =
true;
5765 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5766 sync_blocks_and_headers_from_peer =
true;
5772 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5773 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5781 if (pindexStart->
pprev)
5782 pindexStart = pindexStart->
pprev;
5783 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5786 state.fSyncStarted =
true;
5810 LOCK(peer->m_block_inv_mutex);
5811 std::vector<CBlock> vHeaders;
5812 bool fRevertToInv = ((!peer->m_prefers_headers &&
5813 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5816 ProcessBlockAvailability(pto->
GetId());
5818 if (!fRevertToInv) {
5819 bool fFoundStartingHeader =
false;
5823 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5828 fRevertToInv =
true;
5831 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5843 fRevertToInv =
true;
5846 pBestIndex = pindex;
5847 if (fFoundStartingHeader) {
5850 }
else if (PeerHasHeader(&state, pindex)) {
5852 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5855 fFoundStartingHeader =
true;
5860 fRevertToInv =
true;
5865 if (!fRevertToInv && !vHeaders.empty()) {
5866 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5870 vHeaders.front().GetHash().ToString(), pto->
GetId());
5872 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5874 LOCK(m_most_recent_block_mutex);
5875 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5879 if (cached_cmpctblock_msg.has_value()) {
5880 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5888 state.pindexBestHeaderSent = pBestIndex;
5889 }
else if (peer->m_prefers_headers) {
5890 if (vHeaders.size() > 1) {
5893 vHeaders.front().GetHash().ToString(),
5894 vHeaders.back().GetHash().ToString(), pto->
GetId());
5897 vHeaders.front().GetHash().ToString(), pto->
GetId());
5900 state.pindexBestHeaderSent = pBestIndex;
5902 fRevertToInv =
true;
5908 if (!peer->m_blocks_for_headers_relay.empty()) {
5909 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5922 if (!PeerHasHeader(&state, pindex)) {
5923 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5929 peer->m_blocks_for_headers_relay.clear();
5935 std::vector<CInv> vInv;
5937 LOCK(peer->m_block_inv_mutex);
5941 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5948 peer->m_blocks_for_inv_relay.clear();
5951 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5952 LOCK(tx_relay->m_tx_inventory_mutex);
5955 if (tx_relay->m_next_inv_send_time < current_time) {
5956 fSendTrickle =
true;
5966 LOCK(tx_relay->m_bloom_filter_mutex);
5967 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5971 if (fSendTrickle && tx_relay->m_send_mempool) {
5972 auto vtxinfo = m_mempool.
infoAll();
5973 tx_relay->m_send_mempool =
false;
5974 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5976 LOCK(tx_relay->m_bloom_filter_mutex);
5978 for (
const auto& txinfo : vtxinfo) {
5979 const Txid& txid{txinfo.tx->GetHash()};
5980 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
5981 const auto inv = peer->m_wtxid_relay ?
5984 tx_relay->m_tx_inventory_to_send.erase(wtxid);
5987 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5990 if (tx_relay->m_bloom_filter) {
5991 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5993 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5994 vInv.push_back(inv);
6005 std::vector<std::set<Wtxid>::iterator> vInvTx;
6006 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
6007 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
6008 vInvTx.push_back(it);
6010 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6013 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
6014 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6017 unsigned int nRelayedTransactions = 0;
6018 LOCK(tx_relay->m_bloom_filter_mutex);
6021 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
6023 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6024 std::set<Wtxid>::iterator it = vInvTx.back();
6028 tx_relay->m_tx_inventory_to_send.erase(it);
6030 auto txinfo = m_mempool.
info(wtxid);
6037 const auto inv = peer->m_wtxid_relay ?
6039 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
6041 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
6045 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6048 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6050 vInv.push_back(inv);
6051 nRelayedTransactions++;
6056 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6061 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6068 auto stalling_timeout = m_block_stalling_timeout.load();
6069 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6078 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6088 if (state.vBlocksInFlight.size() > 0) {
6089 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6090 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6098 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
6100 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6101 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6118 state.fSyncStarted =
false;
6120 peer->m_headers_sync_timeout = 0us;
6126 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
6132 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
6137 std::vector<CInv> vGetData;
6139 std::vector<const CBlockIndex*> vToDownload;
6141 auto get_inflight_budget = [&state]() {
6148 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
6149 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
6150 if (historical_blocks && !IsLimitedPeer(*peer)) {
6154 TryDownloadingHistoricalBlocks(
6156 get_inflight_budget(),
6157 vToDownload, from_tip, historical_blocks->second);
6160 uint32_t nFetchFlags = GetFetchFlags(*peer);
6162 BlockRequested(pto->
GetId(), *pindex);
6166 if (state.vBlocksInFlight.empty() && staller != -1) {
6167 if (
State(staller)->m_stalling_since == 0us) {
6168 State(staller)->m_stalling_since = current_time;
6178 LOCK(m_tx_download_mutex);
6179 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
6188 if (!vGetData.empty())
6191 MaybeSendFeefilter(*pto, *peer, current_time);
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
@ BLOCK_VALID_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous.
@ BLOCK_HAVE_DATA
full block available in blk*.dat
arith_uint256 GetBlockProof(const CBlockIndex &block)
Compute how much work a block index entry corresponds to.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< CTransactionRef > txn
std::vector< uint16_t > indexes
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
static constexpr SerParams V1_NETWORK
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V2_NETWORK
size_t BlockTxCount() const
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
unsigned int nTx
Number of transactions in this block.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
An in-memory indexed chain of blocks.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const HeadersSyncParams & HeadersSync() const
const Consensus::Params & GetConsensus() const
void NumToOpenAdd(size_t n)
Increment the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
size_t NumToOpenSub(size_t n)
Decrement the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::microseconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetTryNewOutboundPeer() const
class CConnman::PrivateBroadcast m_private_broadcast
std::vector< CAddress > GetAddresses(CNode &requestor, size_t max_addresses, size_t max_pct)
Return addresses from the per-requestor cache.
void SetTryNewOutboundPeer(bool flag)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
bool DisconnectNode(std::string_view node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return randomly selected addresses.
bool CheckIncomingNonce(uint64_t nonce)
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, Txid > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
const std::string m_addr_name
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
std::atomic< bool > m_bip152_highbandwidth_from
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
const uint64_t m_network_key
Network key used to prevent fingerprinting our node across networks.
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
bool IsPrivateBroadcastConn() const
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
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::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
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.
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
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(const CBlockIndex * FindForkInGlobalIndex(const CBlockLocator &locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Find the last common block of this chain and a locator.
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 bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
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 ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from 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 ProcessMessage(CNode &pfrom, const std::string &msg_type, DataStream &vRecv, std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
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...
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) 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...
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
#define LogDebug(category,...)
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
TRACEPOINT_SEMAPHORE(net, inbound_message)
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr size_t NUM_PRIVATE_BROADCAST_PER_TX
For private broadcast, send a transaction to this many peers.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto PRIVATE_BROADCAST_MAX_CONNECTION_LIFETIME
Private broadcast connections must complete within this time.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" message type for wtxid-based relay starts with this version
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" message type and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
std::chrono::seconds time_offset
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
@ DIFFERENT_WITNESS
Valid, transaction was already in the mempool.
@ INVALID
Fully validated, valid.
const std::list< CTransactionRef > m_replaced_transactions
Mempool transactions replaced by the tx.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
Validation result for package mempool acceptance.
PackageValidationState m_state
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
std::chrono::seconds median_outbound_time_offset
Information about chainstate that notifications are sent from.
bool historical
Whether this is a historical chainstate downloading old blocks to validate an assumeutxo snapshot,...
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
std::vector< NodeId > m_senders
std::string ToString() const
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
#define TRACEPOINT(context,...)
consteval auto _(util::TranslatedLiteral str)
ReconciliationRegisterResult
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
constexpr int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
bool HasValidProofOfWork(std::span< const CBlockHeader > headers, const Consensus::Params &consensusParams)
Check that the proof of work on each blockheader matches the value in nBits.
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...
@ UNVALIDATED
Blocks after an assumeutxo snapshot have been validated but the snapshot itself has not been validate...