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;
558 void ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv, std::chrono::microseconds time_received,
559 const std::atomic<bool>& interruptMsgProc)
560 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
572 void ReattemptPrivateBroadcast(
CScheduler& scheduler);
584 void Misbehaving(Peer& peer,
const std::string& message);
595 bool via_compact_block,
const std::string& message =
"")
604 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
618 bool first_time_failure)
643 bool ProcessOrphanTx(Peer& peer)
653 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
655 bool via_compact_block)
659 bool CheckHeadersPoW(const
std::vector<
CBlockHeader>& headers, Peer& peer);
667 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
686 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
700 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
715 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
717 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
724 template <
typename... Args>
725 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
731 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
737 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
780 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
783 std::atomic<int> m_best_height{-1};
785 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
793 const Options m_opts;
795 bool RejectIncomingTxs(
const CNode& peer)
const;
803 mutable Mutex m_peer_mutex;
810 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
820 uint32_t GetFetchFlags(
const Peer& peer)
const;
822 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
839 std::atomic<int> m_wtxid_relay_peers{0};
857 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
858 std::chrono::seconds average_interval,
863 Mutex m_most_recent_block_mutex;
864 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
865 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
867 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
871 Mutex m_headers_presync_mutex;
879 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
881 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
885 std::atomic_bool m_headers_presync_should_signal{
false};
955 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
961 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
966 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
999 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
1001 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1013 int64_t ApproximateBestBlockDepth() const;
1023 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1041 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1043 const
uint256& stop_hash, uint32_t max_height_diff,
1091 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1097const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const
1099 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1100 if (it == m_node_states.end())
1107 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1115static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1120void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1122 assert(peer.m_addr_known);
1123 peer.m_addr_known->insert(addr.
GetKey());
1126void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1131 assert(peer.m_addr_known);
1132 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1134 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1136 peer.m_addrs_to_send.push_back(addr);
1141static void AddKnownTx(Peer& peer,
const uint256& hash)
1143 auto tx_relay = peer.GetTxRelay();
1144 if (!tx_relay)
return;
1146 LOCK(tx_relay->m_tx_inventory_mutex);
1147 tx_relay->m_tx_inventory_known_filter.insert(hash);
1151static bool CanServeBlocks(
const Peer& peer)
1158static bool IsLimitedPeer(
const Peer& peer)
1165static bool CanServeWitnesses(
const Peer& peer)
1170std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1171 std::chrono::seconds average_interval,
1172 uint64_t network_key)
1174 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1175 auto& timer{it->second};
1177 timer = now + m_rng.rand_exp_duration(average_interval);
1182bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1184 return mapBlocksInFlight.contains(hash);
1187bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1189 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1190 auto [nodeid, block_it] = range.first->second;
1191 PeerRef peer{GetPeerRef(nodeid)};
1192 if (peer && !peer->m_is_inbound)
return true;
1198void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1200 auto range = mapBlocksInFlight.equal_range(hash);
1201 if (range.first == range.second) {
1209 while (range.first != range.second) {
1210 const auto& [node_id, list_it]{range.first->second};
1212 if (from_peer && *from_peer != node_id) {
1219 if (state.vBlocksInFlight.begin() == list_it) {
1221 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1223 state.vBlocksInFlight.erase(list_it);
1225 if (state.vBlocksInFlight.empty()) {
1227 m_peers_downloading_from--;
1229 state.m_stalling_since = 0us;
1231 range.first = mapBlocksInFlight.erase(range.first);
1235bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1239 CNodeState *state =
State(nodeid);
1240 assert(state !=
nullptr);
1245 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1246 if (range.first->second.first == nodeid) {
1248 *pit = &range.first->second.second;
1255 RemoveBlockRequest(hash, nodeid);
1257 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1258 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1259 if (state->vBlocksInFlight.size() == 1) {
1261 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1262 m_peers_downloading_from++;
1264 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1266 *pit = &itInFlight->second.second;
1271void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1278 if (m_opts.ignore_incoming_txs)
return;
1280 CNodeState* nodestate =
State(nodeid);
1281 PeerRef peer{GetPeerRef(nodeid)};
1282 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1287 int num_outbound_hb_peers = 0;
1288 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1289 if (*it == nodeid) {
1290 lNodesAnnouncingHeaderAndIDs.erase(it);
1291 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1294 PeerRef peer_ref{GetPeerRef(*it)};
1295 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1297 if (peer && peer->m_is_inbound) {
1300 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1301 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1302 if (remove_peer && !remove_peer->m_is_inbound) {
1305 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1311 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1314 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1315 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1317 pnodeStop->m_bip152_highbandwidth_to = false;
1320 lNodesAnnouncingHeaderAndIDs.pop_front();
1325 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1330bool PeerManagerImpl::TipMayBeStale()
1334 if (m_last_tip_update.load() == 0
s) {
1335 m_last_tip_update = GetTime<std::chrono::seconds>();
1337 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1340int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1345bool PeerManagerImpl::CanDirectFetch()
1352 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1354 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1359void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1360 CNodeState *state =
State(nodeid);
1361 assert(state !=
nullptr);
1363 if (!state->hashLastUnknownBlock.IsNull()) {
1366 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1367 state->pindexBestKnownBlock = pindex;
1369 state->hashLastUnknownBlock.SetNull();
1374void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1375 CNodeState *state =
State(nodeid);
1376 assert(state !=
nullptr);
1378 ProcessBlockAvailability(nodeid);
1383 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1384 state->pindexBestKnownBlock = pindex;
1388 state->hashLastUnknownBlock = hash;
1393void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1398 vBlocks.reserve(vBlocks.size() +
count);
1399 CNodeState *state =
State(peer.m_id);
1400 assert(state !=
nullptr);
1403 ProcessBlockAvailability(peer.m_id);
1405 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1416 state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1417 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1426 if (state->pindexLastCommonBlock ==
nullptr ||
1427 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1428 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1429 state->pindexLastCommonBlock = fork_point;
1431 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1434 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1440 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1443void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1448 if (vBlocks.size() >=
count) {
1452 vBlocks.reserve(
count);
1455 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1472void 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)
1474 std::vector<const CBlockIndex*> vToFetch;
1475 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1476 bool is_limited_peer = IsLimitedPeer(peer);
1478 while (pindexWalk->
nHeight < nMaxHeight) {
1482 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1483 vToFetch.resize(nToFetch);
1484 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1485 vToFetch[nToFetch - 1] = pindexWalk;
1486 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1487 vToFetch[i - 1] = vToFetch[i]->
pprev;
1507 state->pindexLastCommonBlock = pindex;
1514 if (waitingfor == -1) {
1516 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1522 if (pindex->
nHeight > nWindowEnd) {
1524 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1526 if (nodeStaller) *nodeStaller = waitingfor;
1536 vBlocks.push_back(pindex);
1537 if (vBlocks.size() ==
count) {
1546void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1548 uint64_t my_services;
1550 uint64_t your_services;
1552 std::string my_user_agent;
1560 my_user_agent =
"/pynode:0.0.1/";
1562 my_tx_relay =
false;
1565 my_services = peer.m_our_services;
1570 my_height = m_best_height;
1571 my_tx_relay = !RejectIncomingTxs(pnode);
1590 BCLog::NET,
"send version message: version=%d, blocks=%d%s, txrelay=%d, peer=%d\n",
1593 my_tx_relay, pnode.
GetId());
1596void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1600 if (state) state->m_last_block_announcement = time_in_seconds;
1608 m_node_states.try_emplace(m_node_states.end(), nodeid);
1610 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1616 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1619 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1623void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1627 for (
const auto& txid : unbroadcast_txids) {
1630 if (tx !=
nullptr) {
1631 InitiateTxBroadcastToAll(txid, tx->GetWitnessHash());
1640 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1643void PeerManagerImpl::ReattemptPrivateBroadcast(
CScheduler& scheduler)
1647 size_t num_for_rebroadcast{0};
1648 const auto stale_txs = m_tx_for_private_broadcast.
GetStale();
1649 if (!stale_txs.empty()) {
1651 for (
const auto& stale_tx : stale_txs) {
1655 "Reattempting broadcast of stale txid=%s wtxid=%s",
1656 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString());
1657 ++num_for_rebroadcast;
1660 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString(),
1661 mempool_acceptable.m_state.ToString());
1662 m_tx_for_private_broadcast.
Remove(stale_tx);
1671 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, delta);
1674void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1685 PeerRef peer = RemovePeer(nodeid);
1687 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1688 assert(m_wtxid_relay_peers >= 0);
1690 CNodeState *state =
State(nodeid);
1691 assert(state !=
nullptr);
1693 if (state->fSyncStarted)
1696 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1697 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1698 while (range.first != range.second) {
1699 auto [node_id, list_it] = range.first->second;
1700 if (node_id != nodeid) {
1703 range.first = mapBlocksInFlight.erase(range.first);
1708 LOCK(m_tx_download_mutex);
1709 m_txdownloadman.DisconnectedPeer(nodeid);
1711 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1712 m_num_preferred_download_peers -= state->fPreferredDownload;
1713 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1714 assert(m_peers_downloading_from >= 0);
1715 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1716 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1718 m_node_states.erase(nodeid);
1720 if (m_node_states.empty()) {
1722 assert(mapBlocksInFlight.empty());
1723 assert(m_num_preferred_download_peers == 0);
1724 assert(m_peers_downloading_from == 0);
1725 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1726 assert(m_wtxid_relay_peers == 0);
1727 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1730 if (
node.fSuccessfullyConnected &&
1731 !
node.IsBlockOnlyConn() && !
node.IsPrivateBroadcastConn() && !
node.IsInboundConn()) {
1739 LOCK(m_headers_presync_mutex);
1740 m_headers_presync_stats.erase(nodeid);
1742 if (
node.IsPrivateBroadcastConn() &&
1751bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1754 return !(GetDesirableServiceFlags(services) & (~services));
1768PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1771 auto it = m_peer_map.find(
id);
1772 return it != m_peer_map.end() ? it->second :
nullptr;
1775PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1779 auto it = m_peer_map.find(
id);
1780 if (it != m_peer_map.end()) {
1781 ret = std::move(it->second);
1782 m_peer_map.erase(it);
1791 const CNodeState* state =
State(nodeid);
1792 if (state ==
nullptr)
1794 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1795 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1796 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1802 PeerRef peer = GetPeerRef(nodeid);
1803 if (peer ==
nullptr)
return false;
1812 auto ping_wait{0us};
1813 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1814 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1817 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1820 LOCK(tx_relay->m_tx_inventory_mutex);
1822 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1834 LOCK(peer->m_headers_sync_mutex);
1835 if (peer->m_headers_sync) {
1844std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1846 LOCK(m_tx_download_mutex);
1847 return m_txdownloadman.GetOrphanTransactions();
1854 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1858void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1860 if (m_opts.max_extra_txs <= 0)
1862 if (!vExtraTxnForCompact.size())
1863 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1864 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1865 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1868void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1870 LOCK(peer.m_misbehavior_mutex);
1872 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1873 peer.m_should_discourage =
true;
1882 bool via_compact_block,
const std::string& message)
1884 PeerRef peer{GetPeerRef(nodeid)};
1895 if (!via_compact_block) {
1896 if (peer) Misbehaving(*peer, message);
1904 if (peer && !via_compact_block && !peer->m_is_inbound) {
1905 if (peer) Misbehaving(*peer, message);
1912 if (peer) Misbehaving(*peer, message);
1916 if (peer) Misbehaving(*peer, message);
1921 if (message !=
"") {
1926bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex& block_index)
1940 PeerRef peer = GetPeerRef(peer_id);
1949 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1952 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
1975 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1981 : m_rng{opts.deterministic_rng},
1983 m_chainparams(chainman.GetParams()),
1987 m_chainman(chainman),
1989 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
1990 m_warnings{warnings},
1995 if (opts.reconcile_txs) {
2000void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2011 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2013 if (m_opts.private_broadcast) {
2014 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2018void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2026 LOCK(m_tx_download_mutex);
2030 m_txdownloadman.ActiveTipChange();
2040void PeerManagerImpl::BlockConnected(
2042 const std::shared_ptr<const CBlock>& pblock,
2047 m_last_tip_update = GetTime<std::chrono::seconds>();
2050 auto stalling_timeout = m_block_stalling_timeout.load();
2054 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2064 LOCK(m_tx_download_mutex);
2065 m_txdownloadman.BlockConnected(pblock);
2068void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2070 LOCK(m_tx_download_mutex);
2071 m_txdownloadman.BlockDisconnected();
2078void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2080 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2084 if (pindex->
nHeight <= m_highest_fast_announce)
2086 m_highest_fast_announce = pindex->
nHeight;
2090 uint256 hashBlock(pblock->GetHash());
2091 const std::shared_future<CSerializedNetMsg> lazy_ser{
2095 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2096 for (
const auto& tx : pblock->vtx) {
2097 most_recent_block_txs->emplace(tx->GetHash(), tx);
2098 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2101 LOCK(m_most_recent_block_mutex);
2102 m_most_recent_block_hash = hashBlock;
2103 m_most_recent_block = pblock;
2104 m_most_recent_compact_block = pcmpctblock;
2105 m_most_recent_block_txs = std::move(most_recent_block_txs);
2113 ProcessBlockAvailability(pnode->
GetId());
2117 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2119 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2120 hashBlock.ToString(), pnode->
GetId());
2123 PushMessage(*pnode, ser_cmpctblock.Copy());
2124 state.pindexBestHeaderSent = pindex;
2133void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2135 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2138 if (fInitialDownload)
return;
2141 std::vector<uint256> vHashes;
2143 while (pindexToAnnounce != pindexFork) {
2145 pindexToAnnounce = pindexToAnnounce->
pprev;
2155 for (
auto& it : m_peer_map) {
2156 Peer& peer = *it.second;
2157 LOCK(peer.m_block_inv_mutex);
2158 for (
const uint256& hash : vHashes | std::views::reverse) {
2159 peer.m_blocks_for_headers_relay.push_back(hash);
2171void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2175 const uint256 hash(block->GetHash());
2176 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2181 it != mapBlockSource.end() &&
2182 State(it->second.first)) {
2183 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2193 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2194 if (it != mapBlockSource.end()) {
2195 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2198 if (it != mapBlockSource.end())
2199 mapBlockSource.erase(it);
2207bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2212void PeerManagerImpl::SendPings()
2215 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2218void PeerManagerImpl::InitiateTxBroadcastToAll(
const Txid& txid,
const Wtxid& wtxid)
2221 for(
auto& it : m_peer_map) {
2222 Peer& peer = *it.second;
2223 auto tx_relay = peer.GetTxRelay();
2224 if (!tx_relay)
continue;
2226 LOCK(tx_relay->m_tx_inventory_mutex);
2232 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2235 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2236 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2241void PeerManagerImpl::InitiateTxBroadcastPrivate(
const CTransactionRef& tx)
2243 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2244 if (m_tx_for_private_broadcast.
Add(tx)) {
2252void PeerManagerImpl::RelayAddress(
NodeId originator,
2268 const auto current_time{GetTime<std::chrono::seconds>()};
2276 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2278 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2279 assert(nRelayNodes <= best.size());
2283 for (
auto& [
id, peer] : m_peer_map) {
2284 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2286 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2287 if (hashKey > best[i].first) {
2288 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2289 best[i] = std::make_pair(hashKey, peer.get());
2296 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2297 PushAddress(*best[i].second, addr);
2301void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2303 std::shared_ptr<const CBlock> a_recent_block;
2304 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2306 LOCK(m_most_recent_block_mutex);
2307 a_recent_block = m_most_recent_block;
2308 a_recent_compact_block = m_most_recent_compact_block;
2311 bool need_activate_chain =
false;
2323 need_activate_chain =
true;
2327 if (need_activate_chain) {
2329 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2336 bool can_direct_fetch{
false};
2344 if (!BlockRequestAllowed(*pindex)) {
2345 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2372 can_direct_fetch = CanDirectFetch();
2376 std::shared_ptr<const CBlock> pblock;
2377 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2378 pblock = a_recent_block;
2396 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2406 pblock = pblockRead;
2414 bool sendMerkleBlock =
false;
2416 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2417 LOCK(tx_relay->m_bloom_filter_mutex);
2418 if (tx_relay->m_bloom_filter) {
2419 sendMerkleBlock =
true;
2420 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2423 if (sendMerkleBlock) {
2431 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2442 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2455 LOCK(peer.m_block_inv_mutex);
2457 if (inv.
hash == peer.m_continuation_block) {
2461 std::vector<CInv> vInv;
2462 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2464 peer.m_continuation_block.SetNull();
2472 auto txinfo{std::visit(
2473 [&](
const auto&
id) {
2474 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2478 return std::move(txinfo.tx);
2483 LOCK(m_most_recent_block_mutex);
2484 if (m_most_recent_block_txs !=
nullptr) {
2485 auto it = m_most_recent_block_txs->find(gtxid);
2486 if (it != m_most_recent_block_txs->end())
return it->second;
2493void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2497 auto tx_relay = peer.GetTxRelay();
2499 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2500 std::vector<CInv> vNotFound;
2505 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2506 if (interruptMsgProc)
return;
2511 const CInv &inv = *it++;
2513 if (tx_relay ==
nullptr) {
2519 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2522 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2525 vNotFound.push_back(inv);
2531 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2532 const CInv &inv = *it++;
2534 ProcessGetBlockData(pfrom, peer, inv);
2543 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2545 if (!vNotFound.empty()) {
2564uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2566 uint32_t nFetchFlags = 0;
2567 if (CanServeWitnesses(peer)) {
2576 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2578 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2585 uint32_t tx_requested_size{0};
2586 for (
const auto& tx : resp.txn) tx_requested_size += tx->ComputeTotalSize();
2592bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2596 Misbehaving(peer,
"header with invalid proof of work");
2601 if (!CheckHeadersAreContinuous(headers)) {
2602 Misbehaving(peer,
"non-continuous headers sequence");
2627void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2628 const std::vector<CBlockHeader>& headers)
2632 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2633 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2635 headers[0].hashPrevBlock.ToString(),
2636 best_header->nHeight,
2646bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2650 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2653 hashLastBlock = header.GetHash();
2658bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2660 if (peer.m_headers_sync) {
2661 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2663 if (result.success) peer.m_last_getheaders_timestamp = {};
2664 if (result.request_more) {
2665 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2667 Assume(!locator.vHave.empty());
2670 if (!locator.vHave.empty()) {
2673 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2676 locator.vHave.front().ToString(), pfrom.
GetId());
2681 peer.m_headers_sync.reset(
nullptr);
2686 LOCK(m_headers_presync_mutex);
2687 m_headers_presync_stats.erase(pfrom.
GetId());
2690 HeadersPresyncStats stats;
2691 stats.first = peer.m_headers_sync->GetPresyncWork();
2693 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2694 peer.m_headers_sync->GetPresyncTime()};
2698 LOCK(m_headers_presync_mutex);
2699 m_headers_presync_stats[pfrom.
GetId()] = stats;
2700 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2701 bool best_updated =
false;
2702 if (best_it == m_headers_presync_stats.end()) {
2706 const HeadersPresyncStats* stat_best{
nullptr};
2707 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2708 if (!stat_best || stat > *stat_best) {
2713 m_headers_presync_bestpeer = peer_best;
2714 best_updated = (peer_best == pfrom.
GetId());
2715 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2717 m_headers_presync_bestpeer = pfrom.
GetId();
2718 best_updated =
true;
2720 if (best_updated && stats.second.has_value()) {
2722 m_headers_presync_should_signal =
true;
2726 if (result.success) {
2729 headers.swap(result.pow_validated_headers);
2732 return result.success;
2740bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
2747 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2751 if (total_work < minimum_chain_work) {
2755 if (headers.size() == m_opts.max_headers_result) {
2765 LOCK(peer.m_headers_sync_mutex);
2767 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2772 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2786bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2788 if (header ==
nullptr) {
2790 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2798bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2806 peer.m_last_getheaders_timestamp = current_time;
2817void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2820 CNodeState *nodestate =
State(pfrom.
GetId());
2823 std::vector<const CBlockIndex*> vToFetch;
2831 vToFetch.push_back(pindexWalk);
2833 pindexWalk = pindexWalk->
pprev;
2844 std::vector<CInv> vGetData;
2846 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2851 uint32_t nFetchFlags = GetFetchFlags(peer);
2853 BlockRequested(pfrom.
GetId(), *pindex);
2857 if (vGetData.size() > 1) {
2862 if (vGetData.size() > 0) {
2863 if (!m_opts.ignore_incoming_txs &&
2864 nodestate->m_provides_cmpctblocks &&
2865 vGetData.size() == 1 &&
2866 mapBlocksInFlight.size() == 1 &&
2882void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2883 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2886 CNodeState *nodestate =
State(pfrom.
GetId());
2895 nodestate->m_last_block_announcement =
GetTime();
2903 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2925 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) {
2927 nodestate->m_chain_sync.m_protect =
true;
2928 ++m_outbound_peers_with_protect_from_disconnect;
2933void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2934 std::vector<CBlockHeader>&& headers,
2935 bool via_compact_block)
2937 size_t nCount = headers.size();
2944 LOCK(peer.m_headers_sync_mutex);
2945 if (peer.m_headers_sync) {
2946 peer.m_headers_sync.reset(
nullptr);
2947 LOCK(m_headers_presync_mutex);
2948 m_headers_presync_stats.erase(pfrom.
GetId());
2952 peer.m_last_getheaders_timestamp = {};
2960 if (!CheckHeadersPoW(headers, peer)) {
2975 bool already_validated_work =
false;
2978 bool have_headers_sync =
false;
2980 LOCK(peer.m_headers_sync_mutex);
2982 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2994 if (headers.empty()) {
2998 have_headers_sync = !!peer.m_headers_sync;
3003 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3005 if (!headers_connect_blockindex) {
3009 HandleUnconnectingHeaders(pfrom, peer, headers);
3016 peer.m_last_getheaders_timestamp = {};
3026 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3033 already_validated_work =
true;
3039 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3040 *chain_start_header, headers)) {
3052 bool received_new_header{last_received_header ==
nullptr};
3058 state, &pindexLast)};
3064 "If this happens with all peers, consider database corruption (that -reindex may fix) "
3065 "or a potential consensus incompatibility.",
3068 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3074 if (processed && received_new_header) {
3075 LogBlockHeader(*pindexLast, pfrom,
false);
3079 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3081 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3083 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
3087 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3090 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3096 bool first_time_failure)
3102 PeerRef peer{GetPeerRef(nodeid)};
3105 ptx->GetHash().ToString(),
3106 ptx->GetWitnessHash().ToString(),
3110 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3113 AddToCompactExtraTransactions(ptx);
3115 for (
const Txid& parent_txid : unique_parents) {
3116 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3119 return package_to_validate;
3122void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3128 m_txdownloadman.MempoolAcceptedTx(tx);
3132 tx->GetHash().ToString(),
3133 tx->GetWitnessHash().ToString(),
3136 InitiateTxBroadcastToAll(tx->GetHash(), tx->GetWitnessHash());
3139 AddToCompactExtraTransactions(removedTx);
3149 const auto&
package = package_to_validate.m_txns;
3150 const auto& senders = package_to_validate.
m_senders;
3153 m_txdownloadman.MempoolRejectedPackage(package);
3156 if (!
Assume(package.size() == 2))
return;
3160 auto package_iter = package.rbegin();
3161 auto senders_iter = senders.rbegin();
3162 while (package_iter != package.rend()) {
3163 const auto& tx = *package_iter;
3164 const NodeId nodeid = *senders_iter;
3165 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3169 const auto& tx_result = it_result->second;
3170 switch (tx_result.m_result_type) {
3173 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3183 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3201bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3208 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3211 const Txid& orphanHash = porphanTx->GetHash();
3212 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3229 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3238bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3240 const uint256& stop_hash, uint32_t max_height_diff,
3244 const bool supported_filter_type =
3247 if (!supported_filter_type) {
3249 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg(
fLogIPs));
3250 node.fDisconnect =
true;
3259 if (!stop_index || !BlockRequestAllowed(*stop_index)) {
3262 node.fDisconnect =
true;
3267 uint32_t stop_height = stop_index->
nHeight;
3268 if (start_height > stop_height) {
3270 "start height %d and stop height %d, %s\n",
3271 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3272 node.fDisconnect =
true;
3275 if (stop_height - start_height >= max_height_diff) {
3277 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3278 node.fDisconnect =
true;
3283 if (!filter_index) {
3293 uint8_t filter_type_ser;
3294 uint32_t start_height;
3297 vRecv >> filter_type_ser >> start_height >> stop_hash;
3303 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3308 std::vector<BlockFilter> filters;
3310 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3315 for (
const auto& filter : filters) {
3322 uint8_t filter_type_ser;
3323 uint32_t start_height;
3326 vRecv >> filter_type_ser >> start_height >> stop_hash;
3332 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3338 if (start_height > 0) {
3340 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3342 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3348 std::vector<uint256> filter_hashes;
3350 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3364 uint8_t filter_type_ser;
3367 vRecv >> filter_type_ser >> stop_hash;
3373 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3374 std::numeric_limits<uint32_t>::max(),
3375 stop_index, filter_index)) {
3383 for (
int i = headers.size() - 1; i >= 0; i--) {
3388 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3402 bool new_block{
false};
3403 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3405 node.m_last_block_time = GetTime<std::chrono::seconds>();
3410 RemoveBlockRequest(block->GetHash(), std::nullopt);
3413 mapBlockSource.erase(block->GetHash());
3417void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3419 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3420 bool fBlockRead{
false};
3424 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3425 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3426 bool requested_block_from_this_peer{
false};
3429 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3431 while (range_flight.first != range_flight.second) {
3432 auto [node_id, block_it] = range_flight.first->second;
3433 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3434 requested_block_from_this_peer =
true;
3437 range_flight.first++;
3440 if (!requested_block_from_this_peer) {
3452 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3463 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3466 if (first_in_flight) {
3471 std::vector<CInv> invs;
3476 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3489 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3504void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3516 "Saw new %sheader hash=%s height=%d peer=%d%s",
3517 via_compact_block ?
"cmpctblock " :
"",
3530void PeerManagerImpl::PushPrivateBroadcastTx(
CNode&
node)
3537 node.fDisconnect =
true;
3543 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3549void PeerManagerImpl::ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3550 const std::chrono::microseconds time_received,
3551 const std::atomic<bool>& interruptMsgProc)
3566 uint64_t nNonce = 1;
3569 std::string cleanSubVer;
3570 int starting_height = -1;
3573 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3588 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3590 GetDesirableServiceFlags(nServices),
3603 if (!vRecv.
empty()) {
3611 if (!vRecv.
empty()) {
3612 std::string strSubVer;
3616 if (!vRecv.
empty()) {
3617 vRecv >> starting_height;
3637 PushNodeVersion(pfrom, peer);
3646 peer.m_their_services = nServices;
3650 pfrom.cleanSubVer = cleanSubVer;
3652 peer.m_starting_height = starting_height;
3662 (fRelay || (peer.m_our_services &
NODE_BLOOM))) {
3663 auto*
const tx_relay = peer.SetTxRelay();
3665 LOCK(tx_relay->m_bloom_filter_mutex);
3666 tx_relay->m_relay_txs = fRelay;
3672 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3693 if (greatest_common_version >= 70016) {
3708 const auto* tx_relay = peer.GetTxRelay();
3709 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3711 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3724 m_num_preferred_download_peers += state->fPreferredDownload;
3730 bool send_getaddr{
false};
3732 send_getaddr = SetupAddressRelay(pfrom, peer);
3742 peer.m_getaddr_sent =
true;
3766 peer.m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3770 m_outbound_time_offsets.Add(peer.m_time_offset);
3771 m_outbound_time_offsets.WarnIfOutOfSync();
3775 if (greatest_common_version <= 70012) {
3776 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3777 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3800 auto new_peer_msg = [&]() {
3802 return strprintf(
"New %s peer connected: transport: %s, version: %d, blocks=%d peer=%d%s%s\n",
3805 pfrom.
nVersion.load(), peer.m_starting_height,
3807 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3815 LogInfo(
"%s", new_peer_msg());
3818 if (
auto tx_relay = peer.GetTxRelay()) {
3827 tx_relay->m_tx_inventory_mutex,
3828 return tx_relay->m_tx_inventory_to_send.empty() &&
3829 tx_relay->m_next_inv_send_time == 0
s));
3839 PushPrivateBroadcastTx(pfrom);
3852 if (m_txreconciliation) {
3853 if (!peer.m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3857 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3863 const CNodeState* state =
State(pfrom.
GetId());
3865 .m_preferred = state->fPreferredDownload,
3866 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3867 .m_wtxid_relay = peer.m_wtxid_relay,
3876 peer.m_prefers_headers =
true;
3881 bool sendcmpct_hb{
false};
3882 uint64_t sendcmpct_version{0};
3883 vRecv >> sendcmpct_hb >> sendcmpct_version;
3889 CNodeState* nodestate =
State(pfrom.
GetId());
3890 nodestate->m_provides_cmpctblocks =
true;
3891 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3908 if (!peer.m_wtxid_relay) {
3909 peer.m_wtxid_relay =
true;
3910 m_wtxid_relay_peers++;
3929 peer.m_wants_addrv2 =
true;
3937 if (!m_txreconciliation) {
3938 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3949 if (RejectIncomingTxs(pfrom)) {
3958 const auto* tx_relay = peer.GetTxRelay();
3959 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3965 uint32_t peer_txreconcl_version;
3966 uint64_t remote_salt;
3967 vRecv >> peer_txreconcl_version >> remote_salt;
3970 peer_txreconcl_version, remote_salt);
4002 const auto ser_params{
4010 std::vector<CAddress> vAddr;
4012 vRecv >> ser_params(vAddr);
4014 if (!SetupAddressRelay(pfrom, peer)) {
4021 Misbehaving(peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
4026 std::vector<CAddress> vAddrOk;
4027 const auto current_a_time{Now<NodeSeconds>()};
4030 const auto current_time{GetTime<std::chrono::microseconds>()};
4033 const auto time_diff = std::max(current_time - peer.m_addr_token_timestamp, 0us);
4037 peer.m_addr_token_timestamp = current_time;
4040 uint64_t num_proc = 0;
4041 uint64_t num_rate_limit = 0;
4042 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
4045 if (interruptMsgProc)
4049 if (peer.m_addr_token_bucket < 1.0) {
4055 peer.m_addr_token_bucket -= 1.0;
4064 addr.
nTime = current_a_time - 5 * 24h;
4066 AddAddressKnown(peer, addr);
4073 if (addr.
nTime > current_a_time - 10min && !peer.m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
4075 RelayAddress(pfrom.
GetId(), addr, reachable);
4079 vAddrOk.push_back(addr);
4082 peer.m_addr_processed += num_proc;
4083 peer.m_addr_rate_limited += num_rate_limit;
4084 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
4085 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
4087 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
4088 if (vAddr.size() < 1000) peer.m_getaddr_sent =
false;
4099 std::vector<CInv> vInv;
4103 Misbehaving(peer,
strprintf(
"inv message size = %u", vInv.size()));
4107 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4111 const auto current_time{GetTime<std::chrono::microseconds>()};
4114 for (
CInv& inv : vInv) {
4115 if (interruptMsgProc)
return;
4120 if (peer.m_wtxid_relay) {
4127 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4130 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4138 best_block = &inv.
hash;
4141 if (reject_tx_invs) {
4147 AddKnownTx(peer, inv.
hash);
4150 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4158 if (best_block !=
nullptr) {
4170 if (state.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4171 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer)) {
4173 m_chainman.m_best_header->nHeight, best_block->ToString(),
4176 if (!state.fSyncStarted) {
4177 peer.m_inv_triggered_getheaders_before_sync =
true;
4181 m_last_block_inv_triggering_headers_sync = *best_block;
4190 std::vector<CInv> vInv;
4194 Misbehaving(peer,
strprintf(
"getdata message size = %u", vInv.size()));
4200 if (vInv.size() > 0) {
4205 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4206 if (!pushed_tx_opt) {
4217 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4221 peer.m_ping_queued =
true;
4222 MaybeSendPing(pfrom, peer, GetTime<std::chrono::microseconds>());
4232 LOCK(peer.m_getdata_requests_mutex);
4233 peer.m_getdata_requests.insert(peer.m_getdata_requests.end(), vInv.begin(), vInv.end());
4234 ProcessGetData(pfrom, peer, interruptMsgProc);
4243 vRecv >> locator >> hashStop;
4259 std::shared_ptr<const CBlock> a_recent_block;
4261 LOCK(m_most_recent_block_mutex);
4262 a_recent_block = m_most_recent_block;
4265 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4280 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4295 if (--nLimit <= 0) {
4299 WITH_LOCK(peer.m_block_inv_mutex, {peer.m_continuation_block = pindex->GetBlockHash();});
4311 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4315 std::shared_ptr<const CBlock> recent_block;
4317 LOCK(m_most_recent_block_mutex);
4318 if (m_most_recent_block_hash == req.
blockhash)
4319 recent_block = m_most_recent_block;
4323 SendBlockTransactions(pfrom, peer, *recent_block, req);
4342 if (!block_pos.IsNull()) {
4349 SendBlockTransactions(pfrom, peer, block, req);
4362 WITH_LOCK(peer.m_getdata_requests_mutex, peer.m_getdata_requests.push_back(inv));
4370 vRecv >> locator >> hashStop;
4388 if (m_chainman.
ActiveTip() ==
nullptr ||
4390 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4397 CNodeState *nodestate =
State(pfrom.
GetId());
4406 if (!BlockRequestAllowed(*pindex)) {
4407 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4420 std::vector<CBlock> vHeaders;
4421 int nLimit = m_opts.max_headers_result;
4423 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4426 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4441 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4447 if (RejectIncomingTxs(pfrom)) {
4461 const Txid& txid = ptx->GetHash();
4462 const Wtxid& wtxid = ptx->GetWitnessHash();
4465 AddKnownTx(peer, hash);
4467 if (
const auto num_broadcasted{m_tx_for_private_broadcast.
Remove(ptx)}) {
4469 "network from peer=%d%s; stopping private broadcast attempts",
4480 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4481 if (!should_validate) {
4486 if (!m_mempool.
exists(txid)) {
4487 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4490 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4492 InitiateTxBroadcastToAll(txid, wtxid);
4496 if (package_to_validate) {
4499 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4500 ProcessPackageResult(package_to_validate.value(), package_result);
4506 Assume(!package_to_validate.has_value());
4516 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4519 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4520 ProcessPackageResult(package_to_validate.value(), package_result);
4536 vRecv >> cmpctblock;
4538 bool received_new_header =
false;
4548 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer);
4558 received_new_header =
true;
4566 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4573 if (received_new_header) {
4574 LogBlockHeader(*pindex, pfrom,
true);
4577 bool fProcessBLOCKTXN =
false;
4581 bool fRevertToHeaderProcessing =
false;
4585 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4586 bool fBlockReconstructed =
false;
4592 CNodeState *nodestate =
State(pfrom.
GetId());
4597 nodestate->m_last_block_announcement =
GetTime();
4603 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4604 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4605 bool requested_block_from_this_peer{
false};
4608 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4610 while (range_flight.first != range_flight.second) {
4611 if (range_flight.first->second.first == pfrom.
GetId()) {
4612 requested_block_from_this_peer =
true;
4615 range_flight.first++;
4620 if (requested_block_from_this_peer) {
4623 std::vector<CInv> vInv(1);
4631 if (!already_in_flight && !CanDirectFetch()) {
4639 requested_block_from_this_peer) {
4640 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4641 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4642 if (!(*queuedBlockIt)->partialBlock)
4655 Misbehaving(peer,
"invalid compact block");
4658 if (first_in_flight) {
4660 std::vector<CInv> vInv(1);
4671 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4676 fProcessBLOCKTXN =
true;
4677 }
else if (first_in_flight) {
4684 IsBlockRequestedFromOutbound(blockhash) ||
4703 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4708 std::vector<CTransactionRef> dummy;
4710 status = tempBlock.FillBlock(*pblock, dummy,
4713 fBlockReconstructed =
true;
4717 if (requested_block_from_this_peer) {
4720 std::vector<CInv> vInv(1);
4726 fRevertToHeaderProcessing =
true;
4731 if (fProcessBLOCKTXN) {
4734 return ProcessCompactBlockTxns(pfrom, peer, txn);
4737 if (fRevertToHeaderProcessing) {
4743 return ProcessHeadersMessage(pfrom, peer, {cmpctblock.
header},
true);
4746 if (fBlockReconstructed) {
4751 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4769 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4786 return ProcessCompactBlockTxns(pfrom, peer, resp);
4797 std::vector<CBlockHeader> headers;
4801 if (nCount > m_opts.max_headers_result) {
4802 Misbehaving(peer,
strprintf(
"headers message size = %u", nCount));
4805 headers.resize(nCount);
4806 for (
unsigned int n = 0; n < nCount; n++) {
4807 vRecv >> headers[n];
4811 ProcessHeadersMessage(pfrom, peer, std::move(headers),
false);
4815 if (m_headers_presync_should_signal.exchange(
false)) {
4816 HeadersPresyncStats stats;
4818 LOCK(m_headers_presync_mutex);
4819 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4820 if (it != m_headers_presync_stats.end()) stats = it->second;
4838 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4849 Misbehaving(peer,
"mutated block");
4854 bool forceProcessing =
false;
4855 const uint256 hash(pblock->GetHash());
4856 bool min_pow_checked =
false;
4861 forceProcessing = IsBlockRequested(hash);
4862 RemoveBlockRequest(hash, pfrom.
GetId());
4866 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4870 min_pow_checked =
true;
4873 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4890 Assume(SetupAddressRelay(pfrom, peer));
4894 if (peer.m_getaddr_recvd) {
4898 peer.m_getaddr_recvd =
true;
4900 peer.m_addrs_to_send.clear();
4901 std::vector<CAddress> vAddr;
4907 for (
const CAddress &addr : vAddr) {
4908 PushAddress(peer, addr);
4936 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4937 LOCK(tx_relay->m_tx_inventory_mutex);
4938 tx_relay->m_send_mempool =
true;
4964 const auto ping_end = time_received;
4967 bool bPingFinished =
false;
4968 std::string sProblem;
4970 if (nAvail >=
sizeof(
nonce)) {
4974 if (peer.m_ping_nonce_sent != 0) {
4975 if (
nonce == peer.m_ping_nonce_sent) {
4977 bPingFinished =
true;
4978 const auto ping_time = ping_end - peer.m_ping_start.load();
4979 if (ping_time.count() >= 0) {
4990 sProblem =
"Timing mishap";
4994 sProblem =
"Nonce mismatch";
4997 bPingFinished =
true;
4998 sProblem =
"Nonce zero";
5002 sProblem =
"Unsolicited pong without ping";
5006 bPingFinished =
true;
5007 sProblem =
"Short payload";
5010 if (!(sProblem.empty())) {
5014 peer.m_ping_nonce_sent,
5018 if (bPingFinished) {
5019 peer.m_ping_nonce_sent = 0;
5036 Misbehaving(peer,
"too-large bloom filter");
5037 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5039 LOCK(tx_relay->m_bloom_filter_mutex);
5040 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
5041 tx_relay->m_relay_txs =
true;
5055 std::vector<unsigned char> vData;
5063 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5064 LOCK(tx_relay->m_bloom_filter_mutex);
5065 if (tx_relay->m_bloom_filter) {
5066 tx_relay->m_bloom_filter->insert(vData);
5072 Misbehaving(peer,
"bad filteradd message");
5083 auto tx_relay = peer.GetTxRelay();
5084 if (!tx_relay)
return;
5087 LOCK(tx_relay->m_bloom_filter_mutex);
5088 tx_relay->m_bloom_filter =
nullptr;
5089 tx_relay->m_relay_txs =
true;
5098 vRecv >> newFeeFilter;
5100 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5101 tx_relay->m_fee_filter_received = newFeeFilter;
5109 ProcessGetCFilters(pfrom, peer, vRecv);
5114 ProcessGetCFHeaders(pfrom, peer, vRecv);
5119 ProcessGetCFCheckPt(pfrom, peer, vRecv);
5124 std::vector<CInv> vInv;
5126 std::vector<GenTxid> tx_invs;
5128 for (
CInv &inv : vInv) {
5134 LOCK(m_tx_download_mutex);
5135 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5144bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5147 LOCK(peer.m_misbehavior_mutex);
5150 if (!peer.m_should_discourage)
return false;
5152 peer.m_should_discourage =
false;
5157 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5163 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5183bool PeerManagerImpl::ProcessMessages(
CNode&
node, std::atomic<bool>& interruptMsgProc)
5188 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5189 if (maybe_peer ==
nullptr)
return false;
5190 Peer& peer{*maybe_peer};
5194 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent)
return false;
5197 LOCK(peer.m_getdata_requests_mutex);
5198 if (!peer.m_getdata_requests.empty()) {
5199 ProcessGetData(
node, peer, interruptMsgProc);
5203 const bool processed_orphan = ProcessOrphanTx(peer);
5205 if (
node.fDisconnect)
5208 if (processed_orphan)
return true;
5213 LOCK(peer.m_getdata_requests_mutex);
5214 if (!peer.m_getdata_requests.empty())
return true;
5218 if (
node.fPauseSend)
return false;
5220 auto poll_result{
node.PollMessage()};
5227 bool fMoreWork = poll_result->second;
5231 node.m_addr_name.c_str(),
5232 node.ConnectionTypeAsString().c_str(),
5238 if (m_opts.capture_messages) {
5243 ProcessMessage(peer,
node,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5244 if (interruptMsgProc)
return false;
5246 LOCK(peer.m_getdata_requests_mutex);
5247 if (!peer.m_getdata_requests.empty()) fMoreWork =
true;
5254 LOCK(m_tx_download_mutex);
5255 if (m_txdownloadman.HaveMoreWork(peer.m_id)) fMoreWork =
true;
5256 }
catch (
const std::exception& e) {
5265void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5278 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5280 if (state.m_chain_sync.m_timeout != 0
s) {
5281 state.m_chain_sync.m_timeout = 0
s;
5282 state.m_chain_sync.m_work_header =
nullptr;
5283 state.m_chain_sync.m_sent_getheaders =
false;
5285 }
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)) {
5293 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5294 state.m_chain_sync.m_sent_getheaders =
false;
5295 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5299 if (state.m_chain_sync.m_sent_getheaders) {
5301 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5304 assert(state.m_chain_sync.m_work_header);
5309 MaybeSendGetHeaders(pto,
5310 GetLocator(state.m_chain_sync.m_work_header->pprev),
5312 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());
5313 state.m_chain_sync.m_sent_getheaders =
true;
5325void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5334 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5338 if (pnode->
GetId() > youngest_peer.first) {
5339 next_youngest_peer = youngest_peer;
5340 youngest_peer.first = pnode->GetId();
5341 youngest_peer.second = pnode->m_last_block_time;
5344 NodeId to_disconnect = youngest_peer.first;
5345 if (youngest_peer.second > next_youngest_peer.second) {
5348 to_disconnect = next_youngest_peer.first;
5357 CNodeState *node_state =
State(pnode->
GetId());
5358 if (node_state ==
nullptr ||
5361 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5365 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5381 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5384 AssertLockHeld(::cs_main);
5388 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5389 CNodeState *state = State(pnode->GetId());
5390 if (state == nullptr) return;
5392 if (state->m_chain_sync.m_protect) return;
5395 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5396 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5397 worst_peer = pnode->GetId();
5398 oldest_block_announcement = state->m_last_block_announcement;
5401 if (worst_peer != -1) {
5412 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5416 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5433void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5437 auto now{GetTime<std::chrono::seconds>()};
5439 EvictExtraOutboundPeers(now);
5441 if (now > m_stale_tip_check_time) {
5445 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5454 if (!m_initial_sync_finished && CanDirectFetch()) {
5456 m_initial_sync_finished =
true;
5460void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5463 peer.m_ping_nonce_sent &&
5473 bool pingSend =
false;
5475 if (peer.m_ping_queued) {
5480 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5489 }
while (
nonce == 0);
5490 peer.m_ping_queued =
false;
5491 peer.m_ping_start = now;
5493 peer.m_ping_nonce_sent =
nonce;
5497 peer.m_ping_nonce_sent = 0;
5503void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5506 if (!peer.m_addr_relay_enabled)
return;
5508 LOCK(peer.m_addr_send_times_mutex);
5511 peer.m_next_local_addr_send < current_time) {
5518 if (peer.m_next_local_addr_send != 0us) {
5519 peer.m_addr_known->reset();
5522 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5523 if (peer.m_next_local_addr_send == 0us) {
5527 if (IsAddrCompatible(peer, local_addr)) {
5528 std::vector<CAddress> self_announcement{local_addr};
5529 if (peer.m_wants_addrv2) {
5537 PushAddress(peer, local_addr);
5544 if (current_time <= peer.m_next_addr_send)
return;
5557 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5558 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5561 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5562 peer.m_addrs_to_send.end());
5565 if (peer.m_addrs_to_send.empty())
return;
5567 if (peer.m_wants_addrv2) {
5572 peer.m_addrs_to_send.clear();
5575 if (peer.m_addrs_to_send.capacity() > 40) {
5576 peer.m_addrs_to_send.shrink_to_fit();
5580void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5588 CNodeState &state = *
State(
node.GetId());
5589 if (state.pindexBestKnownBlock !=
nullptr &&
5596 peer.m_sent_sendheaders =
true;
5601void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5603 if (m_opts.ignore_incoming_txs)
return;
5619 if (peer.m_fee_filter_sent == MAX_FILTER) {
5622 peer.m_next_send_feefilter = 0us;
5625 if (current_time > peer.m_next_send_feefilter) {
5626 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5629 if (filterToSend != peer.m_fee_filter_sent) {
5631 peer.m_fee_filter_sent = filterToSend;
5638 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5644class CompareInvMempoolOrder
5648 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5650 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5659bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5669bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5674 if (
node.IsBlockOnlyConn())
return false;
5676 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5680 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5686bool PeerManagerImpl::SendMessages(
CNode&
node)
5691 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5692 if (!maybe_peer)
return false;
5693 Peer& peer{*maybe_peer};
5698 if (MaybeDiscourageAndDisconnect(
node, peer))
return true;
5701 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent) {
5702 PushNodeVersion(
node, peer);
5703 peer.m_outbound_version_message_sent =
true;
5707 if (!
node.fSuccessfullyConnected ||
node.fDisconnect)
5710 const auto current_time{GetTime<std::chrono::microseconds>()};
5715 if (
node.IsPrivateBroadcastConn()) {
5719 node.fDisconnect =
true;
5726 node.fDisconnect =
true;
5730 MaybeSendPing(
node, peer, current_time);
5733 if (
node.fDisconnect)
return true;
5735 MaybeSendAddr(
node, peer, current_time);
5737 MaybeSendSendHeaders(
node, peer);
5742 CNodeState &state = *
State(
node.GetId());
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;
5755 }
else if (CanServeBlocks(peer) && !
node.IsAddrFetchConn()) {
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;
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(
node.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(),
node.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(
node, 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(),
node.GetId());
5897 vHeaders.front().GetHash().ToString(),
node.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;
5957 if (
node.IsInboundConn()) {
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) {
6074 node.fDisconnect =
true;
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;
6092 LogInfo(
"Timeout downloading block %s, %s\n", queuedBlock.pindex->GetBlockHash().ToString(),
node.DisconnectMsg(
fLogIPs));
6093 node.fDisconnect =
true;
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)) {
6109 node.fDisconnect =
true;
6112 LogInfo(
"Timeout downloading headers from noban peer, not %s\n",
node.DisconnectMsg(
fLogIPs));
6118 state.fSyncStarted =
false;
6120 peer.m_headers_sync_timeout = 0us;
6126 peer.m_headers_sync_timeout = std::chrono::microseconds::max();
6132 ConsiderEviction(
node, 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(
node.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(
node.GetId(), current_time)) {
6188 if (!vGetData.empty())
6191 MaybeSendFeefilter(
node, peer, current_time);
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
@ BLOCK_VALID_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous.
@ BLOCK_HAVE_DATA
full block available in blk*.dat
arith_uint256 GetBlockProof(const CBlockIndex &block)
Compute how much work a block index entry corresponds to.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< CTransactionRef > txn
std::vector< uint16_t > indexes
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
static constexpr SerParams V1_NETWORK
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V2_NETWORK
size_t BlockTxCount() const
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
unsigned int nTx
Number of transactions in this block.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
An in-memory indexed chain of blocks.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const HeadersSyncParams & HeadersSync() const
const Consensus::Params & GetConsensus() const
void NumToOpenAdd(size_t n)
Increment the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
size_t NumToOpenSub(size_t n)
Decrement the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::microseconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetTryNewOutboundPeer() const
class CConnman::PrivateBroadcast m_private_broadcast
std::vector< CAddress > GetAddresses(CNode &requestor, size_t max_addresses, size_t max_pct)
Return addresses from the per-requestor cache.
void SetTryNewOutboundPeer(bool flag)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
bool DisconnectNode(std::string_view node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return randomly selected addresses.
bool CheckIncomingNonce(uint64_t nonce)
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, Txid > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
std::atomic< bool > m_bip152_highbandwidth_from
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
std::atomic_bool fPauseSend
std::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 void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual bool ProcessMessages(CNode &node, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
virtual bool SendMessages(CNode &node) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing, bool segwit_active)
bool IsTxAvailable(size_t index) const
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< Wtxid, CTransactionRef > > &extra_txn)
virtual util::Expected< void, std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
virtual std::vector< node::TxOrphanage::OrphanInfo > GetOrphanTransactions()=0
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
virtual void UnitTestMisbehaving(NodeId peer_id)=0
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests....
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
Store a list of transactions to be broadcast privately.
void NodeConfirmedReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Mark that the node has confirmed reception of the transaction we sent it by responding with PONG to o...
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...
#define LogDebug(category,...)
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
TRACEPOINT_SEMAPHORE(net, inbound_message)
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr size_t NUM_PRIVATE_BROADCAST_PER_TX
For private broadcast, send a transaction to this many peers.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto PRIVATE_BROADCAST_MAX_CONNECTION_LIFETIME
Private broadcast connections must complete within this time.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" message type for wtxid-based relay starts with this version
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" message type and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
std::chrono::seconds time_offset
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
@ DIFFERENT_WITNESS
Valid, transaction was already in the mempool.
@ INVALID
Fully validated, valid.
const std::list< CTransactionRef > m_replaced_transactions
Mempool transactions replaced by the tx.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
Validation result for package mempool acceptance.
PackageValidationState m_state
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
std::chrono::seconds median_outbound_time_offset
Information about chainstate that notifications are sent from.
bool historical
Whether this is a historical chainstate downloading old blocks to validate an assumeutxo snapshot,...
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
std::vector< NodeId > m_senders
std::string ToString() const
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
#define TRACEPOINT(context,...)
consteval auto _(util::TranslatedLiteral str)
ReconciliationRegisterResult
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
constexpr int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
bool HasValidProofOfWork(std::span< const CBlockHeader > headers, const Consensus::Params &consensusParams)
Check that the proof of work on each blockheader matches the value in nBits.
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...
@ UNVALIDATED
Blocks after an assumeutxo snapshot have been validated but the snapshot itself has not been validate...