73#include <initializer_list>
207 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
241 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
244 const bool m_is_inbound;
247 Mutex m_misbehavior_mutex;
249 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
252 Mutex m_block_inv_mutex;
256 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
260 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
271 std::atomic<int> m_starting_height{-1};
274 std::atomic<uint64_t> m_ping_nonce_sent{0};
276 std::atomic<std::chrono::microseconds> m_ping_start{0us};
278 std::atomic<bool> m_ping_queued{
false};
281 std::atomic<bool> m_wtxid_relay{
false};
293 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
295 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
306 std::set<Wtxid> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
310 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
313 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
316 uint64_t m_last_inv_sequence
GUARDED_BY(m_tx_inventory_mutex){1};
319 std::atomic<CAmount> m_fee_filter_received{0};
325 LOCK(m_tx_relay_mutex);
327 m_tx_relay = std::make_unique<Peer::TxRelay>();
328 return m_tx_relay.get();
333 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
362 std::atomic_bool m_addr_relay_enabled{
false};
366 mutable Mutex m_addr_send_times_mutex;
368 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
370 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
373 std::atomic_bool m_wants_addrv2{
false};
382 std::atomic<uint64_t> m_addr_rate_limited{0};
384 std::atomic<uint64_t> m_addr_processed{0};
390 Mutex m_getdata_requests_mutex;
392 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
398 Mutex m_headers_sync_mutex;
401 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
404 std::atomic<bool> m_sent_sendheaders{
false};
414 std::atomic<std::chrono::seconds> m_time_offset{0
s};
418 , m_our_services{our_services}
419 , m_is_inbound{is_inbound}
423 mutable Mutex m_tx_relay_mutex;
426 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
429using PeerRef = std::shared_ptr<Peer>;
441 uint256 hashLastUnknownBlock{};
447 bool fSyncStarted{
false};
449 std::chrono::microseconds m_stalling_since{0us};
450 std::list<QueuedBlock> vBlocksInFlight;
452 std::chrono::microseconds m_downloading_since{0us};
454 bool fPreferredDownload{
false};
456 bool m_requested_hb_cmpctblocks{
false};
458 bool m_provides_cmpctblocks{
false};
484 struct ChainSyncTimeoutState {
486 std::chrono::seconds m_timeout{0
s};
490 bool m_sent_getheaders{
false};
492 bool m_protect{
false};
495 ChainSyncTimeoutState m_chain_sync;
498 int64_t m_last_block_announcement{0};
527 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
541 void SetBestBlock(
int height,
std::chrono::seconds time)
override
543 m_best_height = height;
544 m_best_block_time = time;
548 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
549 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
573 void Misbehaving(Peer& peer,
const std::string& message);
584 bool via_compact_block,
const std::string& message =
"")
593 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
607 bool first_time_failure)
632 bool ProcessOrphanTx(Peer& peer)
642 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
644 bool via_compact_block)
656 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
675 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
689 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
704 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
706 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
713 template <
typename... Args>
714 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
720 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
726 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
769 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
772 std::atomic<int> m_best_height{-1};
774 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
782 const Options m_opts;
784 bool RejectIncomingTxs(
const CNode& peer)
const;
792 mutable Mutex m_peer_mutex;
799 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
809 uint32_t GetFetchFlags(
const Peer& peer)
const;
811 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
828 std::atomic<int> m_wtxid_relay_peers{0};
846 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
847 std::chrono::seconds average_interval,
852 Mutex m_most_recent_block_mutex;
853 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
854 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
856 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
860 Mutex m_headers_presync_mutex;
868 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
870 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
874 std::atomic_bool m_headers_presync_should_signal{
false};
944 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
950 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
955 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
980 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
982 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
994 int64_t ApproximateBestBlockDepth() const;
1004 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1022 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1024 const
uint256& stop_hash, uint32_t max_height_diff,
1072 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1075const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const
1077 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1078 if (it == m_node_states.end())
1085 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1093static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1098void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1100 assert(peer.m_addr_known);
1101 peer.m_addr_known->insert(addr.
GetKey());
1104void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1109 assert(peer.m_addr_known);
1110 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1112 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1114 peer.m_addrs_to_send.push_back(addr);
1119static void AddKnownTx(Peer& peer,
const uint256& hash)
1121 auto tx_relay = peer.GetTxRelay();
1122 if (!tx_relay)
return;
1124 LOCK(tx_relay->m_tx_inventory_mutex);
1125 tx_relay->m_tx_inventory_known_filter.insert(hash);
1129static bool CanServeBlocks(
const Peer& peer)
1136static bool IsLimitedPeer(
const Peer& peer)
1143static bool CanServeWitnesses(
const Peer& peer)
1148std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1149 std::chrono::seconds average_interval,
1150 uint64_t network_key)
1152 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1153 auto& timer{it->second};
1155 timer = now + m_rng.rand_exp_duration(average_interval);
1160bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1162 return mapBlocksInFlight.contains(hash);
1165bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1167 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1168 auto [nodeid, block_it] = range.first->second;
1169 PeerRef peer{GetPeerRef(nodeid)};
1170 if (peer && !peer->m_is_inbound)
return true;
1176void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1178 auto range = mapBlocksInFlight.equal_range(hash);
1179 if (range.first == range.second) {
1187 while (range.first != range.second) {
1188 const auto& [node_id, list_it]{range.first->second};
1190 if (from_peer && *from_peer != node_id) {
1197 if (state.vBlocksInFlight.begin() == list_it) {
1199 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1201 state.vBlocksInFlight.erase(list_it);
1203 if (state.vBlocksInFlight.empty()) {
1205 m_peers_downloading_from--;
1207 state.m_stalling_since = 0us;
1209 range.first = mapBlocksInFlight.erase(range.first);
1213bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1217 CNodeState *state =
State(nodeid);
1218 assert(state !=
nullptr);
1223 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1224 if (range.first->second.first == nodeid) {
1226 *pit = &range.first->second.second;
1233 RemoveBlockRequest(hash, nodeid);
1235 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1236 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1237 if (state->vBlocksInFlight.size() == 1) {
1239 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1240 m_peers_downloading_from++;
1242 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1244 *pit = &itInFlight->second.second;
1249void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1256 if (m_opts.ignore_incoming_txs)
return;
1258 CNodeState* nodestate =
State(nodeid);
1259 PeerRef peer{GetPeerRef(nodeid)};
1260 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1265 int num_outbound_hb_peers = 0;
1266 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1267 if (*it == nodeid) {
1268 lNodesAnnouncingHeaderAndIDs.erase(it);
1269 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1272 PeerRef peer_ref{GetPeerRef(*it)};
1273 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1275 if (peer && peer->m_is_inbound) {
1278 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1279 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1280 if (remove_peer && !remove_peer->m_is_inbound) {
1283 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1289 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1292 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1293 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1295 pnodeStop->m_bip152_highbandwidth_to = false;
1298 lNodesAnnouncingHeaderAndIDs.pop_front();
1303 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1308bool PeerManagerImpl::TipMayBeStale()
1312 if (m_last_tip_update.load() == 0
s) {
1313 m_last_tip_update = GetTime<std::chrono::seconds>();
1315 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1318int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1323bool PeerManagerImpl::CanDirectFetch()
1330 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1332 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1337void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1338 CNodeState *state =
State(nodeid);
1339 assert(state !=
nullptr);
1341 if (!state->hashLastUnknownBlock.IsNull()) {
1344 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1345 state->pindexBestKnownBlock = pindex;
1347 state->hashLastUnknownBlock.SetNull();
1352void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1353 CNodeState *state =
State(nodeid);
1354 assert(state !=
nullptr);
1356 ProcessBlockAvailability(nodeid);
1361 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1362 state->pindexBestKnownBlock = pindex;
1366 state->hashLastUnknownBlock = hash;
1371void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1376 vBlocks.reserve(vBlocks.size() +
count);
1377 CNodeState *state =
State(peer.m_id);
1378 assert(state !=
nullptr);
1381 ProcessBlockAvailability(peer.m_id);
1383 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1392 if (snap_base && state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1393 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1402 if (state->pindexLastCommonBlock ==
nullptr ||
1403 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1404 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1405 state->pindexLastCommonBlock = fork_point;
1407 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1410 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1416 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1419void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1424 if (vBlocks.size() >=
count) {
1428 vBlocks.reserve(
count);
1431 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1448void 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)
1450 std::vector<const CBlockIndex*> vToFetch;
1451 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1452 bool is_limited_peer = IsLimitedPeer(peer);
1454 while (pindexWalk->
nHeight < nMaxHeight) {
1458 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1459 vToFetch.resize(nToFetch);
1460 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1461 vToFetch[nToFetch - 1] = pindexWalk;
1462 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1463 vToFetch[i - 1] = vToFetch[i]->
pprev;
1483 state->pindexLastCommonBlock = pindex;
1490 if (waitingfor == -1) {
1492 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1498 if (pindex->
nHeight > nWindowEnd) {
1500 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1502 if (nodeStaller) *nodeStaller = waitingfor;
1512 vBlocks.push_back(pindex);
1513 if (vBlocks.size() ==
count) {
1522void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1524 uint64_t my_services{peer.m_our_services};
1525 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1527 const int nNodeStartingHeight{m_best_height};
1534 const bool tx_relay{!RejectIncomingTxs(pnode)};
1541 LogDebug(
BCLog::NET,
"send version message: version %d, blocks=%d, them=%s, txrelay=%d, peer=%d\n",
PROTOCOL_VERSION, nNodeStartingHeight, addr_you.
ToStringAddrPort(), tx_relay, nodeid);
1547void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1551 if (state) state->m_last_block_announcement = time_in_seconds;
1559 m_node_states.try_emplace(m_node_states.end(), nodeid);
1561 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1567 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1570 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1574void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1578 for (
const auto& txid : unbroadcast_txids) {
1581 if (tx !=
nullptr) {
1582 RelayTransaction(txid, tx->GetWitnessHash());
1591 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1594void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1605 PeerRef peer = RemovePeer(nodeid);
1607 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1608 assert(m_wtxid_relay_peers >= 0);
1610 CNodeState *state =
State(nodeid);
1611 assert(state !=
nullptr);
1613 if (state->fSyncStarted)
1616 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1617 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1618 while (range.first != range.second) {
1619 auto [node_id, list_it] = range.first->second;
1620 if (node_id != nodeid) {
1623 range.first = mapBlocksInFlight.erase(range.first);
1628 LOCK(m_tx_download_mutex);
1629 m_txdownloadman.DisconnectedPeer(nodeid);
1631 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1632 m_num_preferred_download_peers -= state->fPreferredDownload;
1633 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1634 assert(m_peers_downloading_from >= 0);
1635 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1636 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1638 m_node_states.erase(nodeid);
1640 if (m_node_states.empty()) {
1642 assert(mapBlocksInFlight.empty());
1643 assert(m_num_preferred_download_peers == 0);
1644 assert(m_peers_downloading_from == 0);
1645 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1646 assert(m_wtxid_relay_peers == 0);
1647 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1650 if (
node.fSuccessfullyConnected &&
1651 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1658 LOCK(m_headers_presync_mutex);
1659 m_headers_presync_stats.erase(nodeid);
1664bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1667 return !(GetDesirableServiceFlags(services) & (~services));
1681PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1684 auto it = m_peer_map.find(
id);
1685 return it != m_peer_map.end() ? it->second :
nullptr;
1688PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1692 auto it = m_peer_map.find(
id);
1693 if (it != m_peer_map.end()) {
1694 ret = std::move(it->second);
1695 m_peer_map.erase(it);
1704 const CNodeState* state =
State(nodeid);
1705 if (state ==
nullptr)
1707 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1708 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1709 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1715 PeerRef peer = GetPeerRef(nodeid);
1716 if (peer ==
nullptr)
return false;
1725 auto ping_wait{0us};
1726 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1727 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1730 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1733 LOCK(tx_relay->m_tx_inventory_mutex);
1735 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1747 LOCK(peer->m_headers_sync_mutex);
1748 if (peer->m_headers_sync) {
1757std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1759 LOCK(m_tx_download_mutex);
1760 return m_txdownloadman.GetOrphanTransactions();
1767 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1771void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1773 if (m_opts.max_extra_txs <= 0)
1775 if (!vExtraTxnForCompact.size())
1776 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1777 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1778 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1781void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1783 LOCK(peer.m_misbehavior_mutex);
1785 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1786 peer.m_should_discourage =
true;
1795 bool via_compact_block,
const std::string& message)
1797 PeerRef peer{GetPeerRef(nodeid)};
1808 if (!via_compact_block) {
1809 if (peer) Misbehaving(*peer, message);
1817 if (peer && !via_compact_block && !peer->m_is_inbound) {
1818 if (peer) Misbehaving(*peer, message);
1825 if (peer) Misbehaving(*peer, message);
1829 if (peer) Misbehaving(*peer, message);
1834 if (message !=
"") {
1839bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1853 PeerRef peer = GetPeerRef(peer_id);
1862 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1865 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
1888 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1894 : m_rng{opts.deterministic_rng},
1896 m_chainparams(chainman.GetParams()),
1900 m_chainman(chainman),
1902 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
1903 m_warnings{warnings},
1908 if (opts.reconcile_txs) {
1913void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1924 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1927void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
1935 LOCK(m_tx_download_mutex);
1939 m_txdownloadman.ActiveTipChange();
1949void PeerManagerImpl::BlockConnected(
1951 const std::shared_ptr<const CBlock>& pblock,
1956 m_last_tip_update = GetTime<std::chrono::seconds>();
1959 auto stalling_timeout = m_block_stalling_timeout.load();
1963 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1973 LOCK(m_tx_download_mutex);
1974 m_txdownloadman.BlockConnected(pblock);
1977void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1979 LOCK(m_tx_download_mutex);
1980 m_txdownloadman.BlockDisconnected();
1987void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1989 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
1993 if (pindex->
nHeight <= m_highest_fast_announce)
1995 m_highest_fast_announce = pindex->
nHeight;
1999 uint256 hashBlock(pblock->GetHash());
2000 const std::shared_future<CSerializedNetMsg> lazy_ser{
2004 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2005 for (
const auto& tx : pblock->vtx) {
2006 most_recent_block_txs->emplace(tx->GetHash(), tx);
2007 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2010 LOCK(m_most_recent_block_mutex);
2011 m_most_recent_block_hash = hashBlock;
2012 m_most_recent_block = pblock;
2013 m_most_recent_compact_block = pcmpctblock;
2014 m_most_recent_block_txs = std::move(most_recent_block_txs);
2022 ProcessBlockAvailability(pnode->
GetId());
2026 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2028 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2029 hashBlock.ToString(), pnode->
GetId());
2032 PushMessage(*pnode, ser_cmpctblock.Copy());
2033 state.pindexBestHeaderSent = pindex;
2042void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2044 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2047 if (fInitialDownload)
return;
2050 std::vector<uint256> vHashes;
2052 while (pindexToAnnounce != pindexFork) {
2054 pindexToAnnounce = pindexToAnnounce->
pprev;
2064 for (
auto& it : m_peer_map) {
2065 Peer& peer = *it.second;
2066 LOCK(peer.m_block_inv_mutex);
2067 for (
const uint256& hash : vHashes | std::views::reverse) {
2068 peer.m_blocks_for_headers_relay.push_back(hash);
2080void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2084 const uint256 hash(block->GetHash());
2085 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2090 it != mapBlockSource.end() &&
2091 State(it->second.first)) {
2092 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2102 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2103 if (it != mapBlockSource.end()) {
2104 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2107 if (it != mapBlockSource.end())
2108 mapBlockSource.erase(it);
2116bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2121void PeerManagerImpl::SendPings()
2124 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2127void PeerManagerImpl::RelayTransaction(
const Txid& txid,
const Wtxid& wtxid)
2130 for(
auto& it : m_peer_map) {
2131 Peer& peer = *it.second;
2132 auto tx_relay = peer.GetTxRelay();
2133 if (!tx_relay)
continue;
2135 LOCK(tx_relay->m_tx_inventory_mutex);
2141 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2144 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2145 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2150void PeerManagerImpl::RelayAddress(
NodeId originator,
2166 const auto current_time{GetTime<std::chrono::seconds>()};
2174 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2176 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2177 assert(nRelayNodes <= best.size());
2181 for (
auto& [
id, peer] : m_peer_map) {
2182 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2184 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2185 if (hashKey > best[i].first) {
2186 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2187 best[i] = std::make_pair(hashKey, peer.get());
2194 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2195 PushAddress(*best[i].second, addr);
2199void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2201 std::shared_ptr<const CBlock> a_recent_block;
2202 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2204 LOCK(m_most_recent_block_mutex);
2205 a_recent_block = m_most_recent_block;
2206 a_recent_compact_block = m_most_recent_compact_block;
2209 bool need_activate_chain =
false;
2221 need_activate_chain =
true;
2225 if (need_activate_chain) {
2227 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2234 bool can_direct_fetch{
false};
2242 if (!BlockRequestAllowed(pindex)) {
2243 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2270 can_direct_fetch = CanDirectFetch();
2274 std::shared_ptr<const CBlock> pblock;
2275 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2276 pblock = a_recent_block;
2294 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2304 pblock = pblockRead;
2312 bool sendMerkleBlock =
false;
2314 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2315 LOCK(tx_relay->m_bloom_filter_mutex);
2316 if (tx_relay->m_bloom_filter) {
2317 sendMerkleBlock =
true;
2318 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2321 if (sendMerkleBlock) {
2329 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2340 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2353 LOCK(peer.m_block_inv_mutex);
2355 if (inv.
hash == peer.m_continuation_block) {
2359 std::vector<CInv> vInv;
2360 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2362 peer.m_continuation_block.SetNull();
2370 auto txinfo{std::visit(
2371 [&](
const auto&
id) {
2372 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2376 return std::move(txinfo.tx);
2381 LOCK(m_most_recent_block_mutex);
2382 if (m_most_recent_block_txs !=
nullptr) {
2383 auto it = m_most_recent_block_txs->find(gtxid);
2384 if (it != m_most_recent_block_txs->end())
return it->second;
2391void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2395 auto tx_relay = peer.GetTxRelay();
2397 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2398 std::vector<CInv> vNotFound;
2403 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2404 if (interruptMsgProc)
return;
2409 const CInv &inv = *it++;
2411 if (tx_relay ==
nullptr) {
2417 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2420 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2423 vNotFound.push_back(inv);
2429 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2430 const CInv &inv = *it++;
2432 ProcessGetBlockData(pfrom, peer, inv);
2441 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2443 if (!vNotFound.empty()) {
2462uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2464 uint32_t nFetchFlags = 0;
2465 if (CanServeWitnesses(peer)) {
2474 unsigned int tx_requested_size = 0;
2475 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2477 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2481 tx_requested_size += resp.txn[i]->GetTotalSize();
2488bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2492 Misbehaving(peer,
"header with invalid proof of work");
2497 if (!CheckHeadersAreContinuous(headers)) {
2498 Misbehaving(peer,
"non-continuous headers sequence");
2523void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2524 const std::vector<CBlockHeader>& headers)
2528 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2529 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2531 headers[0].hashPrevBlock.ToString(),
2532 best_header->nHeight,
2542bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2546 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2549 hashLastBlock = header.GetHash();
2554bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2556 if (peer.m_headers_sync) {
2557 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2559 if (result.success) peer.m_last_getheaders_timestamp = {};
2560 if (result.request_more) {
2561 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2563 Assume(!locator.vHave.empty());
2566 if (!locator.vHave.empty()) {
2569 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2572 locator.vHave.front().ToString(), pfrom.
GetId());
2577 peer.m_headers_sync.reset(
nullptr);
2582 LOCK(m_headers_presync_mutex);
2583 m_headers_presync_stats.erase(pfrom.
GetId());
2586 HeadersPresyncStats stats;
2587 stats.first = peer.m_headers_sync->GetPresyncWork();
2589 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2590 peer.m_headers_sync->GetPresyncTime()};
2594 LOCK(m_headers_presync_mutex);
2595 m_headers_presync_stats[pfrom.
GetId()] = stats;
2596 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2597 bool best_updated =
false;
2598 if (best_it == m_headers_presync_stats.end()) {
2602 const HeadersPresyncStats* stat_best{
nullptr};
2603 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2604 if (!stat_best || stat > *stat_best) {
2609 m_headers_presync_bestpeer = peer_best;
2610 best_updated = (peer_best == pfrom.
GetId());
2611 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2613 m_headers_presync_bestpeer = pfrom.
GetId();
2614 best_updated =
true;
2616 if (best_updated && stats.second.has_value()) {
2618 m_headers_presync_should_signal =
true;
2622 if (result.success) {
2625 headers.swap(result.pow_validated_headers);
2628 return result.success;
2636bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2643 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2647 if (total_work < minimum_chain_work) {
2651 if (headers.size() == m_opts.max_headers_result) {
2661 LOCK(peer.m_headers_sync_mutex);
2663 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2668 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2682bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2684 if (header ==
nullptr) {
2686 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2694bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2702 peer.m_last_getheaders_timestamp = current_time;
2713void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2716 CNodeState *nodestate =
State(pfrom.
GetId());
2719 std::vector<const CBlockIndex*> vToFetch;
2727 vToFetch.push_back(pindexWalk);
2729 pindexWalk = pindexWalk->
pprev;
2740 std::vector<CInv> vGetData;
2742 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2747 uint32_t nFetchFlags = GetFetchFlags(peer);
2749 BlockRequested(pfrom.
GetId(), *pindex);
2753 if (vGetData.size() > 1) {
2758 if (vGetData.size() > 0) {
2759 if (!m_opts.ignore_incoming_txs &&
2760 nodestate->m_provides_cmpctblocks &&
2761 vGetData.size() == 1 &&
2762 mapBlocksInFlight.size() == 1 &&
2778void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2779 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2782 CNodeState *nodestate =
State(pfrom.
GetId());
2791 nodestate->m_last_block_announcement =
GetTime();
2799 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2821 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) {
2823 nodestate->m_chain_sync.m_protect =
true;
2824 ++m_outbound_peers_with_protect_from_disconnect;
2829void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2830 std::vector<CBlockHeader>&& headers,
2831 bool via_compact_block)
2833 size_t nCount = headers.size();
2840 LOCK(peer.m_headers_sync_mutex);
2841 if (peer.m_headers_sync) {
2842 peer.m_headers_sync.reset(
nullptr);
2843 LOCK(m_headers_presync_mutex);
2844 m_headers_presync_stats.erase(pfrom.
GetId());
2848 peer.m_last_getheaders_timestamp = {};
2856 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2871 bool already_validated_work =
false;
2874 bool have_headers_sync =
false;
2876 LOCK(peer.m_headers_sync_mutex);
2878 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2890 if (headers.empty()) {
2894 have_headers_sync = !!peer.m_headers_sync;
2899 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2901 if (!headers_connect_blockindex) {
2905 HandleUnconnectingHeaders(pfrom, peer, headers);
2912 peer.m_last_getheaders_timestamp = {};
2922 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2923 already_validated_work =
true;
2931 already_validated_work =
true;
2937 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2938 chain_start_header, headers)) {
2950 bool received_new_header{last_received_header ==
nullptr};
2956 state, &pindexLast)};
2962 "If this happens with all peers, consider database corruption (that -reindex may fix) "
2963 "or a potential consensus incompatibility.",
2966 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2972 if (processed && received_new_header) {
2973 LogBlockHeader(*pindexLast, pfrom,
false);
2977 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
2979 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2981 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2985 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
2988 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
2994 bool first_time_failure)
3000 PeerRef peer{GetPeerRef(nodeid)};
3003 ptx->GetHash().ToString(),
3004 ptx->GetWitnessHash().ToString(),
3008 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3011 AddToCompactExtraTransactions(ptx);
3013 for (
const Txid& parent_txid : unique_parents) {
3014 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3017 return package_to_validate;
3020void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3026 m_txdownloadman.MempoolAcceptedTx(tx);
3030 tx->GetHash().ToString(),
3031 tx->GetWitnessHash().ToString(),
3034 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3037 AddToCompactExtraTransactions(removedTx);
3047 const auto&
package = package_to_validate.m_txns;
3048 const auto& senders = package_to_validate.
m_senders;
3051 m_txdownloadman.MempoolRejectedPackage(package);
3054 if (!
Assume(package.size() == 2))
return;
3058 auto package_iter = package.rbegin();
3059 auto senders_iter = senders.rbegin();
3060 while (package_iter != package.rend()) {
3061 const auto& tx = *package_iter;
3062 const NodeId nodeid = *senders_iter;
3063 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3067 const auto& tx_result = it_result->second;
3068 switch (tx_result.m_result_type) {
3071 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3081 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3099bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3106 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3109 const Txid& orphanHash = porphanTx->GetHash();
3110 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3127 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3136bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3138 const uint256& stop_hash, uint32_t max_height_diff,
3142 const bool supported_filter_type =
3145 if (!supported_filter_type) {
3147 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg(
fLogIPs));
3148 node.fDisconnect =
true;
3157 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3160 node.fDisconnect =
true;
3165 uint32_t stop_height = stop_index->
nHeight;
3166 if (start_height > stop_height) {
3168 "start height %d and stop height %d, %s\n",
3169 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3170 node.fDisconnect =
true;
3173 if (stop_height - start_height >= max_height_diff) {
3175 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3176 node.fDisconnect =
true;
3181 if (!filter_index) {
3191 uint8_t filter_type_ser;
3192 uint32_t start_height;
3195 vRecv >> filter_type_ser >> start_height >> stop_hash;
3201 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3206 std::vector<BlockFilter> filters;
3208 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3213 for (
const auto& filter : filters) {
3220 uint8_t filter_type_ser;
3221 uint32_t start_height;
3224 vRecv >> filter_type_ser >> start_height >> stop_hash;
3230 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3236 if (start_height > 0) {
3238 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3240 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3246 std::vector<uint256> filter_hashes;
3248 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3262 uint8_t filter_type_ser;
3265 vRecv >> filter_type_ser >> stop_hash;
3271 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3272 std::numeric_limits<uint32_t>::max(),
3273 stop_index, filter_index)) {
3281 for (
int i = headers.size() - 1; i >= 0; i--) {
3286 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3300 bool new_block{
false};
3301 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3303 node.m_last_block_time = GetTime<std::chrono::seconds>();
3308 RemoveBlockRequest(block->GetHash(), std::nullopt);
3311 mapBlockSource.erase(block->GetHash());
3315void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3317 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3318 bool fBlockRead{
false};
3322 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3323 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3324 bool requested_block_from_this_peer{
false};
3327 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3329 while (range_flight.first != range_flight.second) {
3330 auto [node_id, block_it] = range_flight.first->second;
3331 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3332 requested_block_from_this_peer =
true;
3335 range_flight.first++;
3338 if (!requested_block_from_this_peer) {
3350 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3361 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3364 if (first_in_flight) {
3369 std::vector<CInv> invs;
3374 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3387 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3402void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3414 "Saw new %sheader hash=%s height=%d peer=%d%s",
3415 via_compact_block ?
"cmpctblock " :
"",
3428void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3429 const std::chrono::microseconds time_received,
3430 const std::atomic<bool>& interruptMsgProc)
3436 PeerRef peer = GetPeerRef(pfrom.
GetId());
3437 if (peer ==
nullptr)
return;
3447 uint64_t nNonce = 1;
3450 std::string cleanSubVer;
3451 int starting_height = -1;
3454 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3469 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3471 GetDesirableServiceFlags(nServices),
3484 if (!vRecv.
empty()) {
3492 if (!vRecv.
empty()) {
3493 std::string strSubVer;
3497 if (!vRecv.
empty()) {
3498 vRecv >> starting_height;
3518 PushNodeVersion(pfrom, *peer);
3531 if (greatest_common_version >= 70016) {
3540 peer->m_their_services = nServices;
3544 pfrom.cleanSubVer = cleanSubVer;
3546 peer->m_starting_height = starting_height;
3556 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3557 auto*
const tx_relay = peer->SetTxRelay();
3559 LOCK(tx_relay->m_bloom_filter_mutex);
3560 tx_relay->m_relay_txs = fRelay;
3572 const auto* tx_relay = peer->GetTxRelay();
3573 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3575 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3588 m_num_preferred_download_peers += state->fPreferredDownload;
3594 bool send_getaddr{
false};
3596 send_getaddr = SetupAddressRelay(pfrom, *peer);
3606 peer->m_getaddr_sent =
true;
3631 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3636 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3640 m_outbound_time_offsets.Add(peer->m_time_offset);
3641 m_outbound_time_offsets.WarnIfOutOfSync();
3645 if (greatest_common_version <= 70012) {
3646 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3647 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3670 auto new_peer_msg = [&]() {
3672 return strprintf(
"New %s peer connected: transport: %s, version: %d, blocks=%d peer=%d%s%s\n",
3675 pfrom.
nVersion.load(), peer->m_starting_height,
3677 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3685 LogInfo(
"%s", new_peer_msg());
3697 if (m_txreconciliation) {
3698 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3702 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3706 if (
auto tx_relay = peer->GetTxRelay()) {
3715 tx_relay->m_tx_inventory_mutex,
3716 return tx_relay->m_tx_inventory_to_send.empty() &&
3717 tx_relay->m_next_inv_send_time == 0
s));
3722 const CNodeState* state =
State(pfrom.
GetId());
3724 .m_preferred = state->fPreferredDownload,
3725 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3726 .m_wtxid_relay = peer->m_wtxid_relay,
3735 peer->m_prefers_headers =
true;
3740 bool sendcmpct_hb{
false};
3741 uint64_t sendcmpct_version{0};
3742 vRecv >> sendcmpct_hb >> sendcmpct_version;
3748 CNodeState* nodestate =
State(pfrom.
GetId());
3749 nodestate->m_provides_cmpctblocks =
true;
3750 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3767 if (!peer->m_wtxid_relay) {
3768 peer->m_wtxid_relay =
true;
3769 m_wtxid_relay_peers++;
3788 peer->m_wants_addrv2 =
true;
3796 if (!m_txreconciliation) {
3797 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3808 if (RejectIncomingTxs(pfrom)) {
3817 const auto* tx_relay = peer->GetTxRelay();
3818 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3824 uint32_t peer_txreconcl_version;
3825 uint64_t remote_salt;
3826 vRecv >> peer_txreconcl_version >> remote_salt;
3829 peer_txreconcl_version, remote_salt);
3854 const auto ser_params{
3862 std::vector<CAddress> vAddr;
3864 vRecv >> ser_params(vAddr);
3866 if (!SetupAddressRelay(pfrom, *peer)) {
3873 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3878 std::vector<CAddress> vAddrOk;
3879 const auto current_a_time{Now<NodeSeconds>()};
3882 const auto current_time{GetTime<std::chrono::microseconds>()};
3885 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3889 peer->m_addr_token_timestamp = current_time;
3892 uint64_t num_proc = 0;
3893 uint64_t num_rate_limit = 0;
3894 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
3897 if (interruptMsgProc)
3901 if (peer->m_addr_token_bucket < 1.0) {
3907 peer->m_addr_token_bucket -= 1.0;
3916 addr.
nTime = current_a_time - 5 * 24h;
3918 AddAddressKnown(*peer, addr);
3925 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3927 RelayAddress(pfrom.
GetId(), addr, reachable);
3931 vAddrOk.push_back(addr);
3934 peer->m_addr_processed += num_proc;
3935 peer->m_addr_rate_limited += num_rate_limit;
3936 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3937 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3939 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3940 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3951 std::vector<CInv> vInv;
3955 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
3959 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3963 const auto current_time{GetTime<std::chrono::microseconds>()};
3966 for (
CInv& inv : vInv) {
3967 if (interruptMsgProc)
return;
3972 if (peer->m_wtxid_relay) {
3979 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3982 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3990 best_block = &inv.
hash;
3993 if (reject_tx_invs) {
3999 AddKnownTx(*peer, inv.
hash);
4002 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4010 if (best_block !=
nullptr) {
4022 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4023 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
4025 m_chainman.m_best_header->nHeight, best_block->ToString(),
4028 if (!state.fSyncStarted) {
4029 peer->m_inv_triggered_getheaders_before_sync =
true;
4033 m_last_block_inv_triggering_headers_sync = *best_block;
4042 std::vector<CInv> vInv;
4046 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
4052 if (vInv.size() > 0) {
4057 LOCK(peer->m_getdata_requests_mutex);
4058 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
4059 ProcessGetData(pfrom, *peer, interruptMsgProc);
4068 vRecv >> locator >> hashStop;
4084 std::shared_ptr<const CBlock> a_recent_block;
4086 LOCK(m_most_recent_block_mutex);
4087 a_recent_block = m_most_recent_block;
4090 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4105 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4120 if (--nLimit <= 0) {
4124 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4136 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4140 std::shared_ptr<const CBlock> recent_block;
4142 LOCK(m_most_recent_block_mutex);
4143 if (m_most_recent_block_hash == req.
blockhash)
4144 recent_block = m_most_recent_block;
4148 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4167 if (!block_pos.IsNull()) {
4174 SendBlockTransactions(pfrom, *peer, block, req);
4187 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4195 vRecv >> locator >> hashStop;
4213 if (m_chainman.
ActiveTip() ==
nullptr ||
4215 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4222 CNodeState *nodestate =
State(pfrom.
GetId());
4232 if (!BlockRequestAllowed(pindex)) {
4233 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4246 std::vector<CBlock> vHeaders;
4247 int nLimit = m_opts.max_headers_result;
4249 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4252 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4267 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4273 if (RejectIncomingTxs(pfrom)) {
4287 const Txid& txid = ptx->GetHash();
4288 const Wtxid& wtxid = ptx->GetWitnessHash();
4291 AddKnownTx(*peer, hash);
4295 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4296 if (!should_validate) {
4301 if (!m_mempool.
exists(txid)) {
4302 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4305 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4307 RelayTransaction(txid, wtxid);
4311 if (package_to_validate) {
4314 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4315 ProcessPackageResult(package_to_validate.value(), package_result);
4321 Assume(!package_to_validate.has_value());
4331 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4334 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4335 ProcessPackageResult(package_to_validate.value(), package_result);
4351 vRecv >> cmpctblock;
4353 bool received_new_header =
false;
4363 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4373 received_new_header =
true;
4381 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4388 if (received_new_header) {
4389 LogBlockHeader(*pindex, pfrom,
true);
4392 bool fProcessBLOCKTXN =
false;
4396 bool fRevertToHeaderProcessing =
false;
4400 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4401 bool fBlockReconstructed =
false;
4407 CNodeState *nodestate =
State(pfrom.
GetId());
4412 nodestate->m_last_block_announcement =
GetTime();
4418 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4419 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4420 bool requested_block_from_this_peer{
false};
4423 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4425 while (range_flight.first != range_flight.second) {
4426 if (range_flight.first->second.first == pfrom.
GetId()) {
4427 requested_block_from_this_peer =
true;
4430 range_flight.first++;
4435 if (requested_block_from_this_peer) {
4438 std::vector<CInv> vInv(1);
4439 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4446 if (!already_in_flight && !CanDirectFetch()) {
4454 requested_block_from_this_peer) {
4455 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4456 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4457 if (!(*queuedBlockIt)->partialBlock)
4470 Misbehaving(*peer,
"invalid compact block");
4473 if (first_in_flight) {
4475 std::vector<CInv> vInv(1);
4476 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4486 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4491 fProcessBLOCKTXN =
true;
4492 }
else if (first_in_flight) {
4499 IsBlockRequestedFromOutbound(blockhash) ||
4518 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4523 std::vector<CTransactionRef> dummy;
4525 status = tempBlock.FillBlock(*pblock, dummy,
4528 fBlockReconstructed =
true;
4532 if (requested_block_from_this_peer) {
4535 std::vector<CInv> vInv(1);
4536 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4541 fRevertToHeaderProcessing =
true;
4546 if (fProcessBLOCKTXN) {
4549 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4552 if (fRevertToHeaderProcessing) {
4558 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4561 if (fBlockReconstructed) {
4566 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4584 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4601 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4612 std::vector<CBlockHeader> headers;
4616 if (nCount > m_opts.max_headers_result) {
4617 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4620 headers.resize(nCount);
4621 for (
unsigned int n = 0; n < nCount; n++) {
4622 vRecv >> headers[n];
4626 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4630 if (m_headers_presync_should_signal.exchange(
false)) {
4631 HeadersPresyncStats stats;
4633 LOCK(m_headers_presync_mutex);
4634 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4635 if (it != m_headers_presync_stats.end()) stats = it->second;
4653 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4664 Misbehaving(*peer,
"mutated block");
4669 bool forceProcessing =
false;
4670 const uint256 hash(pblock->GetHash());
4671 bool min_pow_checked =
false;
4676 forceProcessing = IsBlockRequested(hash);
4677 RemoveBlockRequest(hash, pfrom.
GetId());
4681 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4685 min_pow_checked =
true;
4688 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4705 Assume(SetupAddressRelay(pfrom, *peer));
4709 if (peer->m_getaddr_recvd) {
4713 peer->m_getaddr_recvd =
true;
4715 peer->m_addrs_to_send.clear();
4716 std::vector<CAddress> vAddr;
4722 for (
const CAddress &addr : vAddr) {
4723 PushAddress(*peer, addr);
4751 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4752 LOCK(tx_relay->m_tx_inventory_mutex);
4753 tx_relay->m_send_mempool =
true;
4779 const auto ping_end = time_received;
4782 bool bPingFinished =
false;
4783 std::string sProblem;
4785 if (nAvail >=
sizeof(
nonce)) {
4789 if (peer->m_ping_nonce_sent != 0) {
4790 if (
nonce == peer->m_ping_nonce_sent) {
4792 bPingFinished =
true;
4793 const auto ping_time = ping_end - peer->m_ping_start.load();
4794 if (ping_time.count() >= 0) {
4799 sProblem =
"Timing mishap";
4803 sProblem =
"Nonce mismatch";
4806 bPingFinished =
true;
4807 sProblem =
"Nonce zero";
4811 sProblem =
"Unsolicited pong without ping";
4815 bPingFinished =
true;
4816 sProblem =
"Short payload";
4819 if (!(sProblem.empty())) {
4823 peer->m_ping_nonce_sent,
4827 if (bPingFinished) {
4828 peer->m_ping_nonce_sent = 0;
4845 Misbehaving(*peer,
"too-large bloom filter");
4846 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4848 LOCK(tx_relay->m_bloom_filter_mutex);
4849 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4850 tx_relay->m_relay_txs =
true;
4864 std::vector<unsigned char> vData;
4872 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4873 LOCK(tx_relay->m_bloom_filter_mutex);
4874 if (tx_relay->m_bloom_filter) {
4875 tx_relay->m_bloom_filter->insert(vData);
4881 Misbehaving(*peer,
"bad filteradd message");
4892 auto tx_relay = peer->GetTxRelay();
4893 if (!tx_relay)
return;
4896 LOCK(tx_relay->m_bloom_filter_mutex);
4897 tx_relay->m_bloom_filter =
nullptr;
4898 tx_relay->m_relay_txs =
true;
4907 vRecv >> newFeeFilter;
4909 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4910 tx_relay->m_fee_filter_received = newFeeFilter;
4918 ProcessGetCFilters(pfrom, *peer, vRecv);
4923 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4928 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4933 std::vector<CInv> vInv;
4935 std::vector<GenTxid> tx_invs;
4937 for (
CInv &inv : vInv) {
4943 LOCK(m_tx_download_mutex);
4944 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
4953bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4956 LOCK(peer.m_misbehavior_mutex);
4959 if (!peer.m_should_discourage)
return false;
4961 peer.m_should_discourage =
false;
4966 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
4972 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
4992bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4997 PeerRef peer = GetPeerRef(pfrom->
GetId());
4998 if (peer ==
nullptr)
return false;
5002 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
5005 LOCK(peer->m_getdata_requests_mutex);
5006 if (!peer->m_getdata_requests.empty()) {
5007 ProcessGetData(*pfrom, *peer, interruptMsgProc);
5011 const bool processed_orphan = ProcessOrphanTx(*peer);
5016 if (processed_orphan)
return true;
5021 LOCK(peer->m_getdata_requests_mutex);
5022 if (!peer->m_getdata_requests.empty())
return true;
5035 bool fMoreWork = poll_result->second;
5046 if (m_opts.capture_messages) {
5051 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5052 if (interruptMsgProc)
return false;
5054 LOCK(peer->m_getdata_requests_mutex);
5055 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5062 LOCK(m_tx_download_mutex);
5063 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
5064 }
catch (
const std::exception& e) {
5073void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5086 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5088 if (state.m_chain_sync.m_timeout != 0
s) {
5089 state.m_chain_sync.m_timeout = 0
s;
5090 state.m_chain_sync.m_work_header =
nullptr;
5091 state.m_chain_sync.m_sent_getheaders =
false;
5093 }
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)) {
5101 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5102 state.m_chain_sync.m_sent_getheaders =
false;
5103 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5107 if (state.m_chain_sync.m_sent_getheaders) {
5109 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5112 assert(state.m_chain_sync.m_work_header);
5117 MaybeSendGetHeaders(pto,
5118 GetLocator(state.m_chain_sync.m_work_header->pprev),
5120 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());
5121 state.m_chain_sync.m_sent_getheaders =
true;
5133void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5142 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5146 if (pnode->
GetId() > youngest_peer.first) {
5147 next_youngest_peer = youngest_peer;
5148 youngest_peer.first = pnode->GetId();
5149 youngest_peer.second = pnode->m_last_block_time;
5152 NodeId to_disconnect = youngest_peer.first;
5153 if (youngest_peer.second > next_youngest_peer.second) {
5156 to_disconnect = next_youngest_peer.first;
5165 CNodeState *node_state =
State(pnode->
GetId());
5166 if (node_state ==
nullptr ||
5169 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5173 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5189 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5192 AssertLockHeld(::cs_main);
5196 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5197 CNodeState *state = State(pnode->GetId());
5198 if (state == nullptr) return;
5200 if (state->m_chain_sync.m_protect) return;
5203 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5204 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5205 worst_peer = pnode->GetId();
5206 oldest_block_announcement = state->m_last_block_announcement;
5209 if (worst_peer != -1) {
5220 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5224 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5241void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5245 auto now{GetTime<std::chrono::seconds>()};
5247 EvictExtraOutboundPeers(now);
5249 if (now > m_stale_tip_check_time) {
5253 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5262 if (!m_initial_sync_finished && CanDirectFetch()) {
5264 m_initial_sync_finished =
true;
5268void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5271 peer.m_ping_nonce_sent &&
5281 bool pingSend =
false;
5283 if (peer.m_ping_queued) {
5288 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5297 }
while (
nonce == 0);
5298 peer.m_ping_queued =
false;
5299 peer.m_ping_start = now;
5301 peer.m_ping_nonce_sent =
nonce;
5305 peer.m_ping_nonce_sent = 0;
5311void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5314 if (!peer.m_addr_relay_enabled)
return;
5316 LOCK(peer.m_addr_send_times_mutex);
5319 peer.m_next_local_addr_send < current_time) {
5326 if (peer.m_next_local_addr_send != 0us) {
5327 peer.m_addr_known->reset();
5330 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5331 PushAddress(peer, local_addr);
5337 if (current_time <= peer.m_next_addr_send)
return;
5350 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5351 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5354 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5355 peer.m_addrs_to_send.end());
5358 if (peer.m_addrs_to_send.empty())
return;
5360 if (peer.m_wants_addrv2) {
5365 peer.m_addrs_to_send.clear();
5368 if (peer.m_addrs_to_send.capacity() > 40) {
5369 peer.m_addrs_to_send.shrink_to_fit();
5373void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5381 CNodeState &state = *
State(
node.GetId());
5382 if (state.pindexBestKnownBlock !=
nullptr &&
5389 peer.m_sent_sendheaders =
true;
5394void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5396 if (m_opts.ignore_incoming_txs)
return;
5412 if (peer.m_fee_filter_sent == MAX_FILTER) {
5415 peer.m_next_send_feefilter = 0us;
5418 if (current_time > peer.m_next_send_feefilter) {
5419 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5422 if (filterToSend != peer.m_fee_filter_sent) {
5424 peer.m_fee_filter_sent = filterToSend;
5431 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5437class CompareInvMempoolOrder
5441 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5443 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5452bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5462bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5467 if (
node.IsBlockOnlyConn())
return false;
5469 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5473 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5479bool PeerManagerImpl::SendMessages(
CNode* pto)
5484 PeerRef peer = GetPeerRef(pto->
GetId());
5485 if (!peer)
return false;
5490 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5493 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5494 PushNodeVersion(*pto, *peer);
5495 peer->m_outbound_version_message_sent =
true;
5502 const auto current_time{GetTime<std::chrono::microseconds>()};
5510 MaybeSendPing(*pto, *peer, current_time);
5515 MaybeSendAddr(*pto, *peer, current_time);
5517 MaybeSendSendHeaders(*pto, *peer);
5525 if (m_chainman.m_best_header ==
nullptr) {
5532 bool sync_blocks_and_headers_from_peer =
false;
5533 if (state.fPreferredDownload) {
5534 sync_blocks_and_headers_from_peer =
true;
5545 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5546 sync_blocks_and_headers_from_peer =
true;
5552 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5553 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5561 if (pindexStart->
pprev)
5562 pindexStart = pindexStart->
pprev;
5563 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5566 state.fSyncStarted =
true;
5590 LOCK(peer->m_block_inv_mutex);
5591 std::vector<CBlock> vHeaders;
5592 bool fRevertToInv = ((!peer->m_prefers_headers &&
5593 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5596 ProcessBlockAvailability(pto->
GetId());
5598 if (!fRevertToInv) {
5599 bool fFoundStartingHeader =
false;
5603 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5608 fRevertToInv =
true;
5611 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5623 fRevertToInv =
true;
5626 pBestIndex = pindex;
5627 if (fFoundStartingHeader) {
5630 }
else if (PeerHasHeader(&state, pindex)) {
5632 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5635 fFoundStartingHeader =
true;
5640 fRevertToInv =
true;
5645 if (!fRevertToInv && !vHeaders.empty()) {
5646 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5650 vHeaders.front().GetHash().ToString(), pto->
GetId());
5652 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5654 LOCK(m_most_recent_block_mutex);
5655 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5659 if (cached_cmpctblock_msg.has_value()) {
5660 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5668 state.pindexBestHeaderSent = pBestIndex;
5669 }
else if (peer->m_prefers_headers) {
5670 if (vHeaders.size() > 1) {
5673 vHeaders.front().GetHash().ToString(),
5674 vHeaders.back().GetHash().ToString(), pto->
GetId());
5677 vHeaders.front().GetHash().ToString(), pto->
GetId());
5680 state.pindexBestHeaderSent = pBestIndex;
5682 fRevertToInv =
true;
5688 if (!peer->m_blocks_for_headers_relay.empty()) {
5689 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5702 if (!PeerHasHeader(&state, pindex)) {
5703 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5709 peer->m_blocks_for_headers_relay.clear();
5715 std::vector<CInv> vInv;
5717 LOCK(peer->m_block_inv_mutex);
5721 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5728 peer->m_blocks_for_inv_relay.clear();
5731 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5732 LOCK(tx_relay->m_tx_inventory_mutex);
5735 if (tx_relay->m_next_inv_send_time < current_time) {
5736 fSendTrickle =
true;
5746 LOCK(tx_relay->m_bloom_filter_mutex);
5747 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5751 if (fSendTrickle && tx_relay->m_send_mempool) {
5752 auto vtxinfo = m_mempool.
infoAll();
5753 tx_relay->m_send_mempool =
false;
5754 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5756 LOCK(tx_relay->m_bloom_filter_mutex);
5758 for (
const auto& txinfo : vtxinfo) {
5759 const Txid& txid{txinfo.tx->GetHash()};
5760 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
5761 const auto inv = peer->m_wtxid_relay ?
5764 tx_relay->m_tx_inventory_to_send.erase(wtxid);
5767 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5770 if (tx_relay->m_bloom_filter) {
5771 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5773 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5774 vInv.push_back(inv);
5785 std::vector<std::set<Wtxid>::iterator> vInvTx;
5786 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5787 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5788 vInvTx.push_back(it);
5790 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5793 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
5794 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5797 unsigned int nRelayedTransactions = 0;
5798 LOCK(tx_relay->m_bloom_filter_mutex);
5801 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5803 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5804 std::set<Wtxid>::iterator it = vInvTx.back();
5808 tx_relay->m_tx_inventory_to_send.erase(it);
5810 auto txinfo = m_mempool.
info(wtxid);
5817 const auto inv = peer->m_wtxid_relay ?
5819 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
5821 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
5825 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5828 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5830 vInv.push_back(inv);
5831 nRelayedTransactions++;
5836 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5841 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5848 auto stalling_timeout = m_block_stalling_timeout.load();
5849 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5858 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5868 if (state.vBlocksInFlight.size() > 0) {
5869 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5870 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5878 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5880 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5881 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5898 state.fSyncStarted =
false;
5900 peer->m_headers_sync_timeout = 0us;
5906 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5912 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5917 std::vector<CInv> vGetData;
5919 std::vector<const CBlockIndex*> vToDownload;
5921 auto get_inflight_budget = [&state]() {
5928 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5929 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
5930 if (historical_blocks && !IsLimitedPeer(*peer)) {
5934 TryDownloadingHistoricalBlocks(
5936 get_inflight_budget(),
5937 vToDownload, from_tip, historical_blocks->second);
5940 uint32_t nFetchFlags = GetFetchFlags(*peer);
5942 BlockRequested(pto->
GetId(), *pindex);
5946 if (state.vBlocksInFlight.empty() && staller != -1) {
5947 if (
State(staller)->m_stalling_since == 0us) {
5948 State(staller)->m_stalling_since = current_time;
5958 LOCK(m_tx_download_mutex);
5959 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
5968 if (!vGetData.empty())
5971 MaybeSendFeefilter(*pto, *peer, current_time);
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
arith_uint256 GetBlockProof(const CBlockIndex &block)
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
const CChainParams & Params()
Return the currently selected parameters.
#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 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
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return randomly selected addresses.
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
bool CheckIncomingNonce(uint64_t nonce)
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, Txid > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
const std::string m_addr_name
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
std::atomic< bool > m_bip152_highbandwidth_from
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
const uint64_t m_network_key
Network key used to prevent fingerprinting our node across networks.
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
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
void RemoveUnbroadcastTx(const Txid &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
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
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...
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
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(const arith_uint256 &work, int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Double ended buffer combining vector and stream-like interfaces.
void ignore(size_t num_ignore)
uint64_t rand64() noexcept
Generate a random 64-bit integer.
const uint256 & ToUint256() const LIFETIMEBOUND
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing, bool segwit_active)
bool IsTxAvailable(size_t index) const
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< Wtxid, CTransactionRef > > &extra_txn)
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, DataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
virtual 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.
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,...)
Transaction validation functions.
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 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 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" command 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" command 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(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with 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...