176 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
210 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
213 const bool m_is_inbound;
216 Mutex m_misbehavior_mutex;
218 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
221 Mutex m_block_inv_mutex;
225 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
229 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
240 std::atomic<int> m_starting_height{-1};
243 std::atomic<uint64_t> m_ping_nonce_sent{0};
245 std::atomic<std::chrono::microseconds> m_ping_start{0us};
247 std::atomic<bool> m_ping_queued{
false};
250 std::atomic<bool> m_wtxid_relay{
false};
262 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
264 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
275 std::set<uint256> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
279 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
282 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
288 std::atomic<CAmount> m_fee_filter_received{0};
294 LOCK(m_tx_relay_mutex);
296 m_tx_relay = std::make_unique<Peer::TxRelay>();
297 return m_tx_relay.get();
302 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
331 std::atomic_bool m_addr_relay_enabled{
false};
335 mutable Mutex m_addr_send_times_mutex;
337 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
339 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
342 std::atomic_bool m_wants_addrv2{
false};
351 std::atomic<uint64_t> m_addr_rate_limited{0};
353 std::atomic<uint64_t> m_addr_processed{0};
359 Mutex m_getdata_requests_mutex;
361 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
367 Mutex m_headers_sync_mutex;
370 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
373 std::atomic<bool> m_sent_sendheaders{
false};
383 std::atomic<std::chrono::seconds> m_time_offset{0
s};
387 , m_our_services{our_services}
388 , m_is_inbound{is_inbound}
392 mutable Mutex m_tx_relay_mutex;
395 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
398using PeerRef = std::shared_ptr<Peer>;
410 uint256 hashLastUnknownBlock{};
416 bool fSyncStarted{
false};
418 std::chrono::microseconds m_stalling_since{0us};
419 std::list<QueuedBlock> vBlocksInFlight;
421 std::chrono::microseconds m_downloading_since{0us};
423 bool fPreferredDownload{
false};
425 bool m_requested_hb_cmpctblocks{
false};
427 bool m_provides_cmpctblocks{
false};
453 struct ChainSyncTimeoutState {
455 std::chrono::seconds m_timeout{0
s};
459 bool m_sent_getheaders{
false};
461 bool m_protect{
false};
464 ChainSyncTimeoutState m_chain_sync;
467 int64_t m_last_block_announcement{0};
496 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
510 void SetBestBlock(
int height,
std::chrono::seconds time)
override
512 m_best_height = height;
513 m_best_block_time = time;
517 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
518 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
542 void Misbehaving(Peer& peer,
const std::string& message);
553 bool via_compact_block,
const std::string& message =
"")
568 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
582 bool first_time_failure)
607 bool ProcessOrphanTx(Peer& peer)
617 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
619 bool via_compact_block)
631 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
650 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
664 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
679 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
681 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
688 template <
typename... Args>
689 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
695 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
701 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
744 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
747 std::atomic<int> m_best_height{-1};
749 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
757 const Options m_opts;
759 bool RejectIncomingTxs(
const CNode& peer)
const;
767 mutable Mutex m_peer_mutex;
774 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
784 uint32_t GetFetchFlags(
const Peer& peer)
const;
786 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
803 std::atomic<int> m_wtxid_relay_peers{0};
820 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
825 Mutex m_most_recent_block_mutex;
826 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
827 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
829 std::unique_ptr<const std::map<uint256, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
833 Mutex m_headers_presync_mutex;
841 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
843 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
847 std::atomic_bool m_headers_presync_should_signal{
false};
917 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
923 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
928 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
953 std::vector<CTransactionRef> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
955 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
967 int64_t ApproximateBestBlockDepth() const;
977 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
995 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
997 const
uint256& stop_hash, uint32_t max_height_diff,
1046const CNodeState* PeerManagerImpl::State(
NodeId pnode)
const
1048 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1049 if (it == m_node_states.end())
1054CNodeState* PeerManagerImpl::State(
NodeId pnode)
1056 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1064static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1069void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1071 assert(peer.m_addr_known);
1072 peer.m_addr_known->insert(addr.
GetKey());
1075void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1080 assert(peer.m_addr_known);
1081 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1083 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1085 peer.m_addrs_to_send.push_back(addr);
1090static void AddKnownTx(Peer& peer,
const uint256& hash)
1092 auto tx_relay = peer.GetTxRelay();
1093 if (!tx_relay)
return;
1095 LOCK(tx_relay->m_tx_inventory_mutex);
1096 tx_relay->m_tx_inventory_known_filter.insert(hash);
1100static bool CanServeBlocks(
const Peer& peer)
1107static bool IsLimitedPeer(
const Peer& peer)
1114static bool CanServeWitnesses(
const Peer& peer)
1119std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1120 std::chrono::seconds average_interval)
1122 if (m_next_inv_to_inbounds.load() < now) {
1126 m_next_inv_to_inbounds = now + m_rng.rand_exp_duration(average_interval);
1128 return m_next_inv_to_inbounds;
1131bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1133 return mapBlocksInFlight.count(hash);
1136bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1138 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1139 auto [nodeid, block_it] = range.first->second;
1140 PeerRef peer{GetPeerRef(nodeid)};
1141 if (peer && !peer->m_is_inbound)
return true;
1147void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1149 auto range = mapBlocksInFlight.equal_range(hash);
1150 if (range.first == range.second) {
1158 while (range.first != range.second) {
1159 auto [node_id, list_it] = range.first->second;
1161 if (from_peer && *from_peer != node_id) {
1166 CNodeState& state = *
Assert(State(node_id));
1168 if (state.vBlocksInFlight.begin() == list_it) {
1170 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1172 state.vBlocksInFlight.erase(list_it);
1174 if (state.vBlocksInFlight.empty()) {
1176 m_peers_downloading_from--;
1178 state.m_stalling_since = 0us;
1180 range.first = mapBlocksInFlight.erase(range.first);
1184bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1188 CNodeState *state = State(nodeid);
1189 assert(state !=
nullptr);
1194 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1195 if (range.first->second.first == nodeid) {
1197 *pit = &range.first->second.second;
1204 RemoveBlockRequest(hash, nodeid);
1206 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1207 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1208 if (state->vBlocksInFlight.size() == 1) {
1210 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1211 m_peers_downloading_from++;
1213 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1215 *pit = &itInFlight->second.second;
1220void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1227 if (m_opts.ignore_incoming_txs)
return;
1229 CNodeState* nodestate = State(nodeid);
1230 PeerRef peer{GetPeerRef(nodeid)};
1231 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1236 int num_outbound_hb_peers = 0;
1237 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1238 if (*it == nodeid) {
1239 lNodesAnnouncingHeaderAndIDs.erase(it);
1240 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1243 PeerRef peer_ref{GetPeerRef(*it)};
1244 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1246 if (peer && peer->m_is_inbound) {
1249 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1250 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1251 if (remove_peer && !remove_peer->m_is_inbound) {
1254 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1260 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1263 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1264 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1266 pnodeStop->m_bip152_highbandwidth_to = false;
1269 lNodesAnnouncingHeaderAndIDs.pop_front();
1274 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1279bool PeerManagerImpl::TipMayBeStale()
1283 if (m_last_tip_update.load() == 0
s) {
1284 m_last_tip_update = GetTime<std::chrono::seconds>();
1286 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1289int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1294bool PeerManagerImpl::CanDirectFetch()
1301 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1303 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1308void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1309 CNodeState *state = State(nodeid);
1310 assert(state !=
nullptr);
1312 if (!state->hashLastUnknownBlock.IsNull()) {
1315 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1316 state->pindexBestKnownBlock = pindex;
1318 state->hashLastUnknownBlock.SetNull();
1323void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1324 CNodeState *state = State(nodeid);
1325 assert(state !=
nullptr);
1327 ProcessBlockAvailability(nodeid);
1332 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1333 state->pindexBestKnownBlock = pindex;
1337 state->hashLastUnknownBlock = hash;
1342void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1347 vBlocks.reserve(vBlocks.size() +
count);
1348 CNodeState *state = State(peer.m_id);
1349 assert(state !=
nullptr);
1352 ProcessBlockAvailability(peer.m_id);
1354 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1362 const CBlockIndex* snap_base{m_chainman.GetSnapshotBaseBlock()};
1363 if (snap_base && state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1364 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1371 if (state->pindexLastCommonBlock ==
nullptr ||
1372 (snap_base && state->pindexLastCommonBlock->nHeight < snap_base->nHeight)) {
1373 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1378 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1379 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1382 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1388 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1391void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1396 if (vBlocks.size() >=
count) {
1400 vBlocks.reserve(
count);
1401 CNodeState *state =
Assert(State(peer.m_id));
1403 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1420void 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)
1422 std::vector<const CBlockIndex*> vToFetch;
1423 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1424 bool is_limited_peer = IsLimitedPeer(peer);
1426 while (pindexWalk->
nHeight < nMaxHeight) {
1430 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1431 vToFetch.resize(nToFetch);
1432 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1433 vToFetch[nToFetch - 1] = pindexWalk;
1434 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1435 vToFetch[i - 1] = vToFetch[i]->
pprev;
1455 state->pindexLastCommonBlock = pindex;
1462 if (waitingfor == -1) {
1464 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1470 if (pindex->
nHeight > nWindowEnd) {
1472 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1474 if (nodeStaller) *nodeStaller = waitingfor;
1484 vBlocks.push_back(pindex);
1485 if (vBlocks.size() ==
count) {
1494void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1496 uint64_t my_services{peer.m_our_services};
1497 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1499 const int nNodeStartingHeight{m_best_height};
1506 const bool tx_relay{!RejectIncomingTxs(pnode)};
1513 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);
1519void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1522 CNodeState *state = State(
node);
1523 if (state) state->m_last_block_announcement = time_in_seconds;
1531 m_node_states.try_emplace(m_node_states.end(), nodeid);
1533 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1539 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1542 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1546void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1550 for (
const auto& txid : unbroadcast_txids) {
1553 if (tx !=
nullptr) {
1554 RelayTransaction(txid, tx->GetWitnessHash());
1563 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1566void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1577 PeerRef peer = RemovePeer(nodeid);
1579 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1580 assert(m_wtxid_relay_peers >= 0);
1582 CNodeState *state = State(nodeid);
1583 assert(state !=
nullptr);
1585 if (state->fSyncStarted)
1588 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1589 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1590 while (range.first != range.second) {
1591 auto [node_id, list_it] = range.first->second;
1592 if (node_id != nodeid) {
1595 range.first = mapBlocksInFlight.erase(range.first);
1600 LOCK(m_tx_download_mutex);
1601 m_txdownloadman.DisconnectedPeer(nodeid);
1603 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1604 m_num_preferred_download_peers -= state->fPreferredDownload;
1605 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1606 assert(m_peers_downloading_from >= 0);
1607 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1608 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1610 m_node_states.erase(nodeid);
1612 if (m_node_states.empty()) {
1614 assert(mapBlocksInFlight.empty());
1615 assert(m_num_preferred_download_peers == 0);
1616 assert(m_peers_downloading_from == 0);
1617 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1618 assert(m_wtxid_relay_peers == 0);
1619 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1622 if (
node.fSuccessfullyConnected &&
1623 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1630 LOCK(m_headers_presync_mutex);
1631 m_headers_presync_stats.erase(nodeid);
1636bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1639 return !(GetDesirableServiceFlags(services) & (~services));
1653PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1656 auto it = m_peer_map.find(
id);
1657 return it != m_peer_map.end() ? it->second :
nullptr;
1660PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1664 auto it = m_peer_map.find(
id);
1665 if (it != m_peer_map.end()) {
1666 ret = std::move(it->second);
1667 m_peer_map.erase(it);
1676 const CNodeState* state = State(nodeid);
1677 if (state ==
nullptr)
1679 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1680 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1681 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1687 PeerRef peer = GetPeerRef(nodeid);
1688 if (peer ==
nullptr)
return false;
1697 auto ping_wait{0us};
1698 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1699 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1702 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1715 LOCK(peer->m_headers_sync_mutex);
1716 if (peer->m_headers_sync) {
1725std::vector<TxOrphanage::OrphanTxBase> PeerManagerImpl::GetOrphanTransactions()
1727 LOCK(m_tx_download_mutex);
1728 return m_txdownloadman.GetOrphanTransactions();
1735 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1739void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1741 if (m_opts.max_extra_txs <= 0)
1743 if (!vExtraTxnForCompact.size())
1744 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1745 vExtraTxnForCompact[vExtraTxnForCompactIt] = tx;
1746 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1749void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1751 LOCK(peer.m_misbehavior_mutex);
1753 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1754 peer.m_should_discourage =
true;
1763 bool via_compact_block,
const std::string& message)
1765 PeerRef peer{GetPeerRef(nodeid)};
1776 if (!via_compact_block) {
1777 if (peer) Misbehaving(*peer, message);
1785 if (peer && !via_compact_block && !peer->m_is_inbound) {
1786 if (peer) Misbehaving(*peer, message);
1794 if (peer) Misbehaving(*peer, message);
1798 if (peer) Misbehaving(*peer, message);
1803 if (message !=
"") {
1810 PeerRef peer{GetPeerRef(nodeid)};
1816 if (peer) Misbehaving(*peer,
"");
1834bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1843std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1848 PeerRef peer = GetPeerRef(peer_id);
1849 if (peer ==
nullptr)
return "Peer does not exist";
1852 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1857 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1860 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1872 if (!success)
return "Peer not fully connected";
1876 return std::nullopt;
1883 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1889 : m_rng{opts.deterministic_rng},
1891 m_chainparams(chainman.GetParams()),
1895 m_chainman(chainman),
1897 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.max_orphan_txs, opts.deterministic_rng}),
1898 m_warnings{warnings},
1903 if (opts.reconcile_txs) {
1908void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1919 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1922void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
1930 LOCK(m_tx_download_mutex);
1934 m_txdownloadman.ActiveTipChange();
1944void PeerManagerImpl::BlockConnected(
1946 const std::shared_ptr<const CBlock>& pblock,
1951 m_last_tip_update = GetTime<std::chrono::seconds>();
1954 auto stalling_timeout = m_block_stalling_timeout.load();
1958 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1968 LOCK(m_tx_download_mutex);
1969 m_txdownloadman.BlockConnected(pblock);
1972void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1974 LOCK(m_tx_download_mutex);
1975 m_txdownloadman.BlockDisconnected();
1982void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1984 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
1988 if (pindex->
nHeight <= m_highest_fast_announce)
1990 m_highest_fast_announce = pindex->
nHeight;
1994 uint256 hashBlock(pblock->GetHash());
1995 const std::shared_future<CSerializedNetMsg> lazy_ser{
1999 auto most_recent_block_txs = std::make_unique<std::map<uint256, CTransactionRef>>();
2000 for (
const auto& tx : pblock->vtx) {
2001 most_recent_block_txs->emplace(tx->GetHash(), tx);
2002 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2005 LOCK(m_most_recent_block_mutex);
2006 m_most_recent_block_hash = hashBlock;
2007 m_most_recent_block = pblock;
2008 m_most_recent_compact_block = pcmpctblock;
2009 m_most_recent_block_txs = std::move(most_recent_block_txs);
2017 ProcessBlockAvailability(pnode->
GetId());
2018 CNodeState &state = *State(pnode->
GetId());
2021 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2023 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2024 hashBlock.ToString(), pnode->
GetId());
2027 PushMessage(*pnode, ser_cmpctblock.Copy());
2028 state.pindexBestHeaderSent = pindex;
2037void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2039 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2042 if (fInitialDownload)
return;
2045 std::vector<uint256> vHashes;
2047 while (pindexToAnnounce != pindexFork) {
2049 pindexToAnnounce = pindexToAnnounce->
pprev;
2059 for (
auto& it : m_peer_map) {
2060 Peer& peer = *it.second;
2061 LOCK(peer.m_block_inv_mutex);
2062 for (
const uint256& hash : vHashes | std::views::reverse) {
2063 peer.m_blocks_for_headers_relay.push_back(hash);
2080 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2085 it != mapBlockSource.end() &&
2086 State(it->second.first)) {
2087 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2097 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2098 if (it != mapBlockSource.end()) {
2099 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2102 if (it != mapBlockSource.end())
2103 mapBlockSource.erase(it);
2111bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2116void PeerManagerImpl::SendPings()
2119 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2122void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2125 for(
auto& it : m_peer_map) {
2126 Peer& peer = *it.second;
2127 auto tx_relay = peer.GetTxRelay();
2128 if (!tx_relay)
continue;
2130 LOCK(tx_relay->m_tx_inventory_mutex);
2136 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2138 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2139 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2140 tx_relay->m_tx_inventory_to_send.insert(hash);
2145void PeerManagerImpl::RelayAddress(
NodeId originator,
2161 const auto current_time{GetTime<std::chrono::seconds>()};
2169 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2171 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2172 assert(nRelayNodes <= best.size());
2176 for (
auto& [
id, peer] : m_peer_map) {
2177 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2179 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2180 if (hashKey > best[i].first) {
2181 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2182 best[i] = std::make_pair(hashKey, peer.get());
2189 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2190 PushAddress(*best[i].second, addr);
2194void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2196 std::shared_ptr<const CBlock> a_recent_block;
2197 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2199 LOCK(m_most_recent_block_mutex);
2200 a_recent_block = m_most_recent_block;
2201 a_recent_compact_block = m_most_recent_compact_block;
2204 bool need_activate_chain =
false;
2216 need_activate_chain =
true;
2220 if (need_activate_chain) {
2222 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2229 bool can_direct_fetch{
false};
2237 if (!BlockRequestAllowed(pindex)) {
2238 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2265 can_direct_fetch = CanDirectFetch();
2269 std::shared_ptr<const CBlock> pblock;
2270 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2271 pblock = a_recent_block;
2275 std::vector<uint8_t> block_data;
2289 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2299 pblock = pblockRead;
2307 bool sendMerkleBlock =
false;
2309 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2310 LOCK(tx_relay->m_bloom_filter_mutex);
2311 if (tx_relay->m_bloom_filter) {
2312 sendMerkleBlock =
true;
2313 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2316 if (sendMerkleBlock) {
2324 typedef std::pair<unsigned int, uint256> PairType;
2336 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2349 LOCK(peer.m_block_inv_mutex);
2351 if (inv.
hash == peer.m_continuation_block) {
2355 std::vector<CInv> vInv;
2356 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2358 peer.m_continuation_block.SetNull();
2366 auto txinfo = m_mempool.
info_for_relay(gtxid, tx_relay.m_last_inv_sequence);
2368 return std::move(txinfo.tx);
2373 LOCK(m_most_recent_block_mutex);
2374 if (m_most_recent_block_txs !=
nullptr) {
2375 auto it = m_most_recent_block_txs->find(gtxid.
GetHash());
2376 if (it != m_most_recent_block_txs->end())
return it->second;
2383void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2387 auto tx_relay = peer.GetTxRelay();
2389 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2390 std::vector<CInv> vNotFound;
2395 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2396 if (interruptMsgProc)
return;
2401 const CInv &inv = *it++;
2403 if (tx_relay ==
nullptr) {
2413 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2416 vNotFound.push_back(inv);
2422 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2423 const CInv &inv = *it++;
2425 ProcessGetBlockData(pfrom, peer, inv);
2431 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2433 if (!vNotFound.empty()) {
2452uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2454 uint32_t nFetchFlags = 0;
2455 if (CanServeWitnesses(peer)) {
2464 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2466 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2475bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2479 Misbehaving(peer,
"header with invalid proof of work");
2484 if (!CheckHeadersAreContinuous(headers)) {
2485 Misbehaving(peer,
"non-continuous headers sequence");
2510void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2511 const std::vector<CBlockHeader>& headers)
2515 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2516 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2518 headers[0].hashPrevBlock.ToString(),
2519 best_header->nHeight,
2529bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2533 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2536 hashLastBlock = header.GetHash();
2541bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2543 if (peer.m_headers_sync) {
2544 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2546 if (result.success) peer.m_last_getheaders_timestamp = {};
2547 if (result.request_more) {
2548 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2550 Assume(!locator.vHave.empty());
2553 if (!locator.vHave.empty()) {
2556 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2559 locator.vHave.front().ToString(), pfrom.
GetId());
2564 peer.m_headers_sync.reset(
nullptr);
2569 LOCK(m_headers_presync_mutex);
2570 m_headers_presync_stats.erase(pfrom.
GetId());
2573 HeadersPresyncStats stats;
2574 stats.first = peer.m_headers_sync->GetPresyncWork();
2576 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2577 peer.m_headers_sync->GetPresyncTime()};
2581 LOCK(m_headers_presync_mutex);
2582 m_headers_presync_stats[pfrom.
GetId()] = stats;
2583 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2584 bool best_updated =
false;
2585 if (best_it == m_headers_presync_stats.end()) {
2589 const HeadersPresyncStats* stat_best{
nullptr};
2590 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2591 if (!stat_best || stat > *stat_best) {
2596 m_headers_presync_bestpeer = peer_best;
2597 best_updated = (peer_best == pfrom.
GetId());
2598 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2600 m_headers_presync_bestpeer = pfrom.
GetId();
2601 best_updated =
true;
2603 if (best_updated && stats.second.has_value()) {
2605 m_headers_presync_should_signal =
true;
2609 if (result.success) {
2612 headers.swap(result.pow_validated_headers);
2615 return result.success;
2623bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2630 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2634 if (total_work < minimum_chain_work) {
2638 if (headers.size() == m_opts.max_headers_result) {
2648 LOCK(peer.m_headers_sync_mutex);
2650 chain_start_header, minimum_chain_work));
2655 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2669bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2671 if (header ==
nullptr) {
2673 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2681bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2689 peer.m_last_getheaders_timestamp = current_time;
2700void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2703 CNodeState *nodestate = State(pfrom.
GetId());
2706 std::vector<const CBlockIndex*> vToFetch;
2714 vToFetch.push_back(pindexWalk);
2716 pindexWalk = pindexWalk->
pprev;
2727 std::vector<CInv> vGetData;
2729 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2734 uint32_t nFetchFlags = GetFetchFlags(peer);
2736 BlockRequested(pfrom.
GetId(), *pindex);
2740 if (vGetData.size() > 1) {
2745 if (vGetData.size() > 0) {
2746 if (!m_opts.ignore_incoming_txs &&
2747 nodestate->m_provides_cmpctblocks &&
2748 vGetData.size() == 1 &&
2749 mapBlocksInFlight.size() == 1 &&
2765void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2766 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2769 CNodeState *nodestate = State(pfrom.
GetId());
2778 nodestate->m_last_block_announcement =
GetTime();
2786 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2808 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) {
2810 nodestate->m_chain_sync.m_protect =
true;
2811 ++m_outbound_peers_with_protect_from_disconnect;
2816void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2817 std::vector<CBlockHeader>&& headers,
2818 bool via_compact_block)
2820 size_t nCount = headers.size();
2827 LOCK(peer.m_headers_sync_mutex);
2828 if (peer.m_headers_sync) {
2829 peer.m_headers_sync.reset(
nullptr);
2830 LOCK(m_headers_presync_mutex);
2831 m_headers_presync_stats.erase(pfrom.
GetId());
2835 peer.m_last_getheaders_timestamp = {};
2843 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2858 bool already_validated_work =
false;
2861 bool have_headers_sync =
false;
2863 LOCK(peer.m_headers_sync_mutex);
2865 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2877 if (headers.empty()) {
2881 have_headers_sync = !!peer.m_headers_sync;
2886 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2888 if (!headers_connect_blockindex) {
2892 HandleUnconnectingHeaders(pfrom, peer, headers);
2899 peer.m_last_getheaders_timestamp = {};
2909 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2910 already_validated_work =
true;
2918 already_validated_work =
true;
2924 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2925 chain_start_header, headers)) {
2937 bool received_new_header{last_received_header ==
nullptr};
2943 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2950 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
2952 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2954 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2958 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
2961 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
2967 bool first_time_failure)
2973 PeerRef peer{GetPeerRef(nodeid)};
2976 ptx->GetHash().ToString(),
2977 ptx->GetWitnessHash().ToString(),
2981 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
2984 AddToCompactExtraTransactions(ptx);
2986 for (
const Txid& parent_txid : unique_parents) {
2987 if (peer) AddKnownTx(*peer, parent_txid);
2990 MaybePunishNodeForTx(nodeid, state);
2992 return package_to_validate;
2995void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3001 m_txdownloadman.MempoolAcceptedTx(tx);
3005 tx->GetHash().ToString(),
3006 tx->GetWitnessHash().ToString(),
3009 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3012 AddToCompactExtraTransactions(removedTx);
3022 const auto&
package = package_to_validate.m_txns;
3023 const auto& senders = package_to_validate.
m_senders;
3026 m_txdownloadman.MempoolRejectedPackage(package);
3029 if (!
Assume(package.size() == 2))
return;
3033 auto package_iter = package.rbegin();
3034 auto senders_iter = senders.rbegin();
3035 while (package_iter != package.rend()) {
3036 const auto& tx = *package_iter;
3037 const NodeId nodeid = *senders_iter;
3038 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3042 const auto& tx_result = it_result->second;
3043 switch (tx_result.m_result_type) {
3046 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3056 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3072bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3079 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3082 const Txid& orphanHash = porphanTx->GetHash();
3083 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3100 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3109bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3111 const uint256& stop_hash, uint32_t max_height_diff,
3115 const bool supported_filter_type =
3118 if (!supported_filter_type) {
3120 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg(
fLogIPs));
3121 node.fDisconnect =
true;
3130 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3133 node.fDisconnect =
true;
3138 uint32_t stop_height = stop_index->
nHeight;
3139 if (start_height > stop_height) {
3141 "start height %d and stop height %d, %s\n",
3142 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3143 node.fDisconnect =
true;
3146 if (stop_height - start_height >= max_height_diff) {
3148 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3149 node.fDisconnect =
true;
3154 if (!filter_index) {
3164 uint8_t filter_type_ser;
3165 uint32_t start_height;
3168 vRecv >> filter_type_ser >> start_height >> stop_hash;
3174 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3179 std::vector<BlockFilter> filters;
3181 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3186 for (
const auto& filter : filters) {
3193 uint8_t filter_type_ser;
3194 uint32_t start_height;
3197 vRecv >> filter_type_ser >> start_height >> stop_hash;
3203 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3209 if (start_height > 0) {
3211 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3213 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3219 std::vector<uint256> filter_hashes;
3221 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3235 uint8_t filter_type_ser;
3238 vRecv >> filter_type_ser >> stop_hash;
3244 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3245 std::numeric_limits<uint32_t>::max(),
3246 stop_index, filter_index)) {
3254 for (
int i = headers.size() - 1; i >= 0; i--) {
3259 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3271void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked)
3273 bool new_block{
false};
3274 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3276 node.m_last_block_time = GetTime<std::chrono::seconds>();
3281 RemoveBlockRequest(block->GetHash(), std::nullopt);
3284 mapBlockSource.erase(block->GetHash());
3288void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3290 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3291 bool fBlockRead{
false};
3295 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3296 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3297 bool requested_block_from_this_peer{
false};
3300 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3302 while (range_flight.first != range_flight.second) {
3303 auto [node_id, block_it] = range_flight.first->second;
3304 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3305 requested_block_from_this_peer =
true;
3308 range_flight.first++;
3311 if (!requested_block_from_this_peer) {
3320 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3323 if (first_in_flight) {
3325 std::vector<CInv> invs;
3330 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3359 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3369 ProcessBlock(pfrom, pblock,
true,
true);
3374void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3375 const std::chrono::microseconds time_received,
3376 const std::atomic<bool>& interruptMsgProc)
3382 PeerRef peer = GetPeerRef(pfrom.
GetId());
3383 if (peer ==
nullptr)
return;
3393 uint64_t nNonce = 1;
3396 std::string cleanSubVer;
3397 int starting_height = -1;
3400 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3415 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3417 GetDesirableServiceFlags(nServices),
3430 if (!vRecv.
empty()) {
3438 if (!vRecv.
empty()) {
3439 std::string strSubVer;
3443 if (!vRecv.
empty()) {
3444 vRecv >> starting_height;
3464 PushNodeVersion(pfrom, *peer);
3477 if (greatest_common_version >= 70016) {
3486 peer->m_their_services = nServices;
3490 pfrom.cleanSubVer = cleanSubVer;
3492 peer->m_starting_height = starting_height;
3502 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3503 auto*
const tx_relay = peer->SetTxRelay();
3505 LOCK(tx_relay->m_bloom_filter_mutex);
3506 tx_relay->m_relay_txs = fRelay;
3518 const auto* tx_relay = peer->GetTxRelay();
3519 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3521 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3532 CNodeState* state = State(pfrom.
GetId());
3534 m_num_preferred_download_peers += state->fPreferredDownload;
3540 bool send_getaddr{
false};
3542 send_getaddr = SetupAddressRelay(pfrom, *peer);
3552 peer->m_getaddr_sent =
true;
3577 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3582 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3586 m_outbound_time_offsets.Add(peer->m_time_offset);
3587 m_outbound_time_offsets.WarnIfOutOfSync();
3591 if (greatest_common_version <= 70012) {
3592 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3593 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3620 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3623 pfrom.
nVersion.load(), peer->m_starting_height,
3625 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3637 if (m_txreconciliation) {
3638 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3642 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3646 if (
auto tx_relay = peer->GetTxRelay()) {
3655 tx_relay->m_tx_inventory_mutex,
3656 return tx_relay->m_tx_inventory_to_send.empty() &&
3657 tx_relay->m_next_inv_send_time == 0
s));
3662 const CNodeState* state = State(pfrom.
GetId());
3664 .m_preferred = state->fPreferredDownload,
3665 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3666 .m_wtxid_relay = peer->m_wtxid_relay,
3675 peer->m_prefers_headers =
true;
3680 bool sendcmpct_hb{
false};
3681 uint64_t sendcmpct_version{0};
3682 vRecv >> sendcmpct_hb >> sendcmpct_version;
3688 CNodeState* nodestate = State(pfrom.
GetId());
3689 nodestate->m_provides_cmpctblocks =
true;
3690 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3707 if (!peer->m_wtxid_relay) {
3708 peer->m_wtxid_relay =
true;
3709 m_wtxid_relay_peers++;
3728 peer->m_wants_addrv2 =
true;
3736 if (!m_txreconciliation) {
3737 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3748 if (RejectIncomingTxs(pfrom)) {
3757 const auto* tx_relay = peer->GetTxRelay();
3758 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3764 uint32_t peer_txreconcl_version;
3765 uint64_t remote_salt;
3766 vRecv >> peer_txreconcl_version >> remote_salt;
3769 peer_txreconcl_version, remote_salt);
3794 const auto ser_params{
3802 std::vector<CAddress> vAddr;
3804 vRecv >> ser_params(vAddr);
3806 if (!SetupAddressRelay(pfrom, *peer)) {
3813 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3818 std::vector<CAddress> vAddrOk;
3819 const auto current_a_time{Now<NodeSeconds>()};
3822 const auto current_time{GetTime<std::chrono::microseconds>()};
3825 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3829 peer->m_addr_token_timestamp = current_time;
3832 uint64_t num_proc = 0;
3833 uint64_t num_rate_limit = 0;
3834 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
3837 if (interruptMsgProc)
3841 if (peer->m_addr_token_bucket < 1.0) {
3847 peer->m_addr_token_bucket -= 1.0;
3856 addr.
nTime = current_a_time - 5 * 24h;
3858 AddAddressKnown(*peer, addr);
3865 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3867 RelayAddress(pfrom.
GetId(), addr, reachable);
3871 vAddrOk.push_back(addr);
3874 peer->m_addr_processed += num_proc;
3875 peer->m_addr_rate_limited += num_rate_limit;
3876 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3877 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3879 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3880 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3891 std::vector<CInv> vInv;
3895 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
3899 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3903 const auto current_time{GetTime<std::chrono::microseconds>()};
3906 for (
CInv& inv : vInv) {
3907 if (interruptMsgProc)
return;
3912 if (peer->m_wtxid_relay) {
3919 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3922 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3930 best_block = &inv.
hash;
3933 if (reject_tx_invs) {
3939 AddKnownTx(*peer, inv.
hash);
3942 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
3950 if (best_block !=
nullptr) {
3962 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
3963 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
3965 m_chainman.m_best_header->nHeight, best_block->ToString(),
3968 if (!state.fSyncStarted) {
3969 peer->m_inv_triggered_getheaders_before_sync =
true;
3973 m_last_block_inv_triggering_headers_sync = *best_block;
3982 std::vector<CInv> vInv;
3986 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
3992 if (vInv.size() > 0) {
3997 LOCK(peer->m_getdata_requests_mutex);
3998 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
3999 ProcessGetData(pfrom, *peer, interruptMsgProc);
4008 vRecv >> locator >> hashStop;
4024 std::shared_ptr<const CBlock> a_recent_block;
4026 LOCK(m_most_recent_block_mutex);
4027 a_recent_block = m_most_recent_block;
4030 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4045 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4060 if (--nLimit <= 0) {
4064 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4075 std::shared_ptr<const CBlock> recent_block;
4077 LOCK(m_most_recent_block_mutex);
4078 if (m_most_recent_block_hash == req.
blockhash)
4079 recent_block = m_most_recent_block;
4083 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4102 if (!block_pos.IsNull()) {
4109 SendBlockTransactions(pfrom, *peer, block, req);
4122 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4130 vRecv >> locator >> hashStop;
4152 if (m_chainman.
ActiveTip() ==
nullptr ||
4154 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4161 CNodeState *nodestate = State(pfrom.
GetId());
4171 if (!BlockRequestAllowed(pindex)) {
4172 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4185 std::vector<CBlock> vHeaders;
4186 int nLimit = m_opts.max_headers_result;
4188 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4191 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4206 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4212 if (RejectIncomingTxs(pfrom)) {
4227 const uint256& txid = ptx->GetHash();
4228 const uint256& wtxid = ptx->GetWitnessHash();
4230 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4231 AddKnownTx(*peer, hash);
4235 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4236 if (!should_validate) {
4242 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4245 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4251 if (package_to_validate) {
4254 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4255 ProcessPackageResult(package_to_validate.value(), package_result);
4261 Assume(!package_to_validate.has_value());
4271 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4274 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4275 ProcessPackageResult(package_to_validate.value(), package_result);
4291 vRecv >> cmpctblock;
4293 bool received_new_header =
false;
4303 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4313 received_new_header =
true;
4321 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4326 if (received_new_header) {
4327 LogInfo(
"Saw new cmpctblock header hash=%s peer=%d\n",
4328 blockhash.ToString(), pfrom.
GetId());
4331 bool fProcessBLOCKTXN =
false;
4335 bool fRevertToHeaderProcessing =
false;
4339 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4340 bool fBlockReconstructed =
false;
4348 CNodeState *nodestate = State(pfrom.
GetId());
4353 nodestate->m_last_block_announcement =
GetTime();
4359 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4360 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4361 bool requested_block_from_this_peer{
false};
4364 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4366 while (range_flight.first != range_flight.second) {
4367 if (range_flight.first->second.first == pfrom.
GetId()) {
4368 requested_block_from_this_peer =
true;
4371 range_flight.first++;
4376 if (requested_block_from_this_peer) {
4379 std::vector<CInv> vInv(1);
4380 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4387 if (!already_in_flight && !CanDirectFetch()) {
4395 requested_block_from_this_peer) {
4396 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4397 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4398 if (!(*queuedBlockIt)->partialBlock)
4411 Misbehaving(*peer,
"invalid compact block");
4414 if (first_in_flight) {
4416 std::vector<CInv> vInv(1);
4417 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4427 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4432 fProcessBLOCKTXN =
true;
4433 }
else if (first_in_flight) {
4440 IsBlockRequestedFromOutbound(blockhash) ||
4459 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4464 std::vector<CTransactionRef> dummy;
4465 status = tempBlock.FillBlock(*pblock, dummy);
4467 fBlockReconstructed =
true;
4471 if (requested_block_from_this_peer) {
4474 std::vector<CInv> vInv(1);
4475 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4480 fRevertToHeaderProcessing =
true;
4485 if (fProcessBLOCKTXN) {
4488 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4491 if (fRevertToHeaderProcessing) {
4497 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4500 if (fBlockReconstructed) {
4505 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4516 ProcessBlock(pfrom, pblock,
true,
true);
4523 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4540 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4551 std::vector<CBlockHeader> headers;
4555 if (nCount > m_opts.max_headers_result) {
4556 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4559 headers.resize(nCount);
4560 for (
unsigned int n = 0; n < nCount; n++) {
4561 vRecv >> headers[n];
4565 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4569 if (m_headers_presync_should_signal.exchange(
false)) {
4570 HeadersPresyncStats stats;
4572 LOCK(m_headers_presync_mutex);
4573 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4574 if (it != m_headers_presync_stats.end()) stats = it->second;
4592 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4603 Misbehaving(*peer,
"mutated block");
4608 bool forceProcessing =
false;
4609 const uint256 hash(pblock->GetHash());
4610 bool min_pow_checked =
false;
4615 forceProcessing = IsBlockRequested(hash);
4616 RemoveBlockRequest(hash, pfrom.
GetId());
4620 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4624 min_pow_checked =
true;
4627 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4644 Assume(SetupAddressRelay(pfrom, *peer));
4648 if (peer->m_getaddr_recvd) {
4652 peer->m_getaddr_recvd =
true;
4654 peer->m_addrs_to_send.clear();
4655 std::vector<CAddress> vAddr;
4661 for (
const CAddress &addr : vAddr) {
4662 PushAddress(*peer, addr);
4690 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4691 LOCK(tx_relay->m_tx_inventory_mutex);
4692 tx_relay->m_send_mempool =
true;
4718 const auto ping_end = time_received;
4721 bool bPingFinished =
false;
4722 std::string sProblem;
4724 if (nAvail >=
sizeof(
nonce)) {
4728 if (peer->m_ping_nonce_sent != 0) {
4729 if (
nonce == peer->m_ping_nonce_sent) {
4731 bPingFinished =
true;
4732 const auto ping_time = ping_end - peer->m_ping_start.load();
4733 if (ping_time.count() >= 0) {
4738 sProblem =
"Timing mishap";
4742 sProblem =
"Nonce mismatch";
4745 bPingFinished =
true;
4746 sProblem =
"Nonce zero";
4750 sProblem =
"Unsolicited pong without ping";
4754 bPingFinished =
true;
4755 sProblem =
"Short payload";
4758 if (!(sProblem.empty())) {
4762 peer->m_ping_nonce_sent,
4766 if (bPingFinished) {
4767 peer->m_ping_nonce_sent = 0;
4784 Misbehaving(*peer,
"too-large bloom filter");
4785 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4787 LOCK(tx_relay->m_bloom_filter_mutex);
4788 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4789 tx_relay->m_relay_txs =
true;
4803 std::vector<unsigned char> vData;
4811 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4812 LOCK(tx_relay->m_bloom_filter_mutex);
4813 if (tx_relay->m_bloom_filter) {
4814 tx_relay->m_bloom_filter->insert(vData);
4820 Misbehaving(*peer,
"bad filteradd message");
4831 auto tx_relay = peer->GetTxRelay();
4832 if (!tx_relay)
return;
4835 LOCK(tx_relay->m_bloom_filter_mutex);
4836 tx_relay->m_bloom_filter =
nullptr;
4837 tx_relay->m_relay_txs =
true;
4846 vRecv >> newFeeFilter;
4848 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4849 tx_relay->m_fee_filter_received = newFeeFilter;
4857 ProcessGetCFilters(pfrom, *peer, vRecv);
4862 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4867 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4872 std::vector<CInv> vInv;
4874 std::vector<uint256> tx_invs;
4876 for (
CInv &inv : vInv) {
4878 tx_invs.emplace_back(inv.
hash);
4882 LOCK(m_tx_download_mutex);
4883 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
4892bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4895 LOCK(peer.m_misbehavior_mutex);
4898 if (!peer.m_should_discourage)
return false;
4900 peer.m_should_discourage =
false;
4905 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
4911 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
4931bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4936 PeerRef peer = GetPeerRef(pfrom->
GetId());
4937 if (peer ==
nullptr)
return false;
4941 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
4944 LOCK(peer->m_getdata_requests_mutex);
4945 if (!peer->m_getdata_requests.empty()) {
4946 ProcessGetData(*pfrom, *peer, interruptMsgProc);
4950 const bool processed_orphan = ProcessOrphanTx(*peer);
4955 if (processed_orphan)
return true;
4960 LOCK(peer->m_getdata_requests_mutex);
4961 if (!peer->m_getdata_requests.empty())
return true;
4974 bool fMoreWork = poll_result->second;
4985 if (m_opts.capture_messages) {
4990 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
4991 if (interruptMsgProc)
return false;
4993 LOCK(peer->m_getdata_requests_mutex);
4994 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5001 LOCK(m_tx_download_mutex);
5002 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
5003 }
catch (
const std::exception& e) {
5012void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5016 CNodeState &state = *State(pto.
GetId());
5025 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5027 if (state.m_chain_sync.m_timeout != 0
s) {
5028 state.m_chain_sync.m_timeout = 0
s;
5029 state.m_chain_sync.m_work_header =
nullptr;
5030 state.m_chain_sync.m_sent_getheaders =
false;
5032 }
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)) {
5040 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5041 state.m_chain_sync.m_sent_getheaders =
false;
5042 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5046 if (state.m_chain_sync.m_sent_getheaders) {
5048 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5051 assert(state.m_chain_sync.m_work_header);
5056 MaybeSendGetHeaders(pto,
5057 GetLocator(state.m_chain_sync.m_work_header->pprev),
5059 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());
5060 state.m_chain_sync.m_sent_getheaders =
true;
5072void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5081 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5085 if (pnode->
GetId() > youngest_peer.first) {
5086 next_youngest_peer = youngest_peer;
5087 youngest_peer.first = pnode->GetId();
5088 youngest_peer.second = pnode->m_last_block_time;
5091 NodeId to_disconnect = youngest_peer.first;
5092 if (youngest_peer.second > next_youngest_peer.second) {
5095 to_disconnect = next_youngest_peer.first;
5104 CNodeState *node_state = State(pnode->
GetId());
5105 if (node_state ==
nullptr ||
5108 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5112 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5128 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5131 AssertLockHeld(::cs_main);
5135 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5136 CNodeState *state = State(pnode->GetId());
5137 if (state == nullptr) return;
5139 if (state->m_chain_sync.m_protect) return;
5142 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5143 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5144 worst_peer = pnode->GetId();
5145 oldest_block_announcement = state->m_last_block_announcement;
5148 if (worst_peer != -1) {
5157 CNodeState &state = *State(pnode->
GetId());
5159 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5163 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5180void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5184 auto now{GetTime<std::chrono::seconds>()};
5186 EvictExtraOutboundPeers(now);
5188 if (now > m_stale_tip_check_time) {
5192 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5201 if (!m_initial_sync_finished && CanDirectFetch()) {
5203 m_initial_sync_finished =
true;
5207void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5210 peer.m_ping_nonce_sent &&
5220 bool pingSend =
false;
5222 if (peer.m_ping_queued) {
5227 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5236 }
while (
nonce == 0);
5237 peer.m_ping_queued =
false;
5238 peer.m_ping_start = now;
5240 peer.m_ping_nonce_sent =
nonce;
5244 peer.m_ping_nonce_sent = 0;
5250void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5253 if (!peer.m_addr_relay_enabled)
return;
5255 LOCK(peer.m_addr_send_times_mutex);
5258 peer.m_next_local_addr_send < current_time) {
5265 if (peer.m_next_local_addr_send != 0us) {
5266 peer.m_addr_known->reset();
5269 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5270 PushAddress(peer, local_addr);
5276 if (current_time <= peer.m_next_addr_send)
return;
5289 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5290 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5293 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5294 peer.m_addrs_to_send.end());
5297 if (peer.m_addrs_to_send.empty())
return;
5299 if (peer.m_wants_addrv2) {
5304 peer.m_addrs_to_send.clear();
5307 if (peer.m_addrs_to_send.capacity() > 40) {
5308 peer.m_addrs_to_send.shrink_to_fit();
5312void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5320 CNodeState &state = *State(
node.GetId());
5321 if (state.pindexBestKnownBlock !=
nullptr &&
5328 peer.m_sent_sendheaders =
true;
5333void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5335 if (m_opts.ignore_incoming_txs)
return;
5351 if (peer.m_fee_filter_sent == MAX_FILTER) {
5354 peer.m_next_send_feefilter = 0us;
5357 if (current_time > peer.m_next_send_feefilter) {
5358 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5361 if (filterToSend != peer.m_fee_filter_sent) {
5363 peer.m_fee_filter_sent = filterToSend;
5370 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5376class CompareInvMempoolOrder
5381 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5384 m_wtxid_relay = use_wtxid;
5387 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5391 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5396bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5406bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5411 if (
node.IsBlockOnlyConn())
return false;
5413 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5417 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5423bool PeerManagerImpl::SendMessages(
CNode* pto)
5428 PeerRef peer = GetPeerRef(pto->
GetId());
5429 if (!peer)
return false;
5434 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5437 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5438 PushNodeVersion(*pto, *peer);
5439 peer->m_outbound_version_message_sent =
true;
5446 const auto current_time{GetTime<std::chrono::microseconds>()};
5454 MaybeSendPing(*pto, *peer, current_time);
5459 MaybeSendAddr(*pto, *peer, current_time);
5461 MaybeSendSendHeaders(*pto, *peer);
5466 CNodeState &state = *State(pto->
GetId());
5469 if (m_chainman.m_best_header ==
nullptr) {
5476 bool sync_blocks_and_headers_from_peer =
false;
5477 if (state.fPreferredDownload) {
5478 sync_blocks_and_headers_from_peer =
true;
5489 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5490 sync_blocks_and_headers_from_peer =
true;
5496 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5497 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5505 if (pindexStart->
pprev)
5506 pindexStart = pindexStart->
pprev;
5507 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5510 state.fSyncStarted =
true;
5534 LOCK(peer->m_block_inv_mutex);
5535 std::vector<CBlock> vHeaders;
5536 bool fRevertToInv = ((!peer->m_prefers_headers &&
5537 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5540 ProcessBlockAvailability(pto->
GetId());
5542 if (!fRevertToInv) {
5543 bool fFoundStartingHeader =
false;
5547 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5552 fRevertToInv =
true;
5555 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5567 fRevertToInv =
true;
5570 pBestIndex = pindex;
5571 if (fFoundStartingHeader) {
5574 }
else if (PeerHasHeader(&state, pindex)) {
5576 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5579 fFoundStartingHeader =
true;
5584 fRevertToInv =
true;
5589 if (!fRevertToInv && !vHeaders.empty()) {
5590 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5594 vHeaders.front().GetHash().ToString(), pto->
GetId());
5596 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5598 LOCK(m_most_recent_block_mutex);
5599 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5603 if (cached_cmpctblock_msg.has_value()) {
5604 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5612 state.pindexBestHeaderSent = pBestIndex;
5613 }
else if (peer->m_prefers_headers) {
5614 if (vHeaders.size() > 1) {
5617 vHeaders.front().GetHash().ToString(),
5618 vHeaders.back().GetHash().ToString(), pto->
GetId());
5621 vHeaders.front().GetHash().ToString(), pto->
GetId());
5624 state.pindexBestHeaderSent = pBestIndex;
5626 fRevertToInv =
true;
5632 if (!peer->m_blocks_for_headers_relay.empty()) {
5633 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5646 if (!PeerHasHeader(&state, pindex)) {
5647 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5653 peer->m_blocks_for_headers_relay.clear();
5659 std::vector<CInv> vInv;
5661 LOCK(peer->m_block_inv_mutex);
5665 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5672 peer->m_blocks_for_inv_relay.clear();
5675 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5676 LOCK(tx_relay->m_tx_inventory_mutex);
5679 if (tx_relay->m_next_inv_send_time < current_time) {
5680 fSendTrickle =
true;
5690 LOCK(tx_relay->m_bloom_filter_mutex);
5691 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5695 if (fSendTrickle && tx_relay->m_send_mempool) {
5696 auto vtxinfo = m_mempool.
infoAll();
5697 tx_relay->m_send_mempool =
false;
5698 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5700 LOCK(tx_relay->m_bloom_filter_mutex);
5702 for (
const auto& txinfo : vtxinfo) {
5705 peer->m_wtxid_relay ?
5706 txinfo.tx->GetWitnessHash().ToUint256() :
5707 txinfo.tx->GetHash().ToUint256(),
5709 tx_relay->m_tx_inventory_to_send.erase(inv.
hash);
5712 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5715 if (tx_relay->m_bloom_filter) {
5716 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5718 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5719 vInv.push_back(inv);
5730 std::vector<std::set<uint256>::iterator> vInvTx;
5731 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5732 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5733 vInvTx.push_back(it);
5735 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5738 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
5739 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5742 unsigned int nRelayedTransactions = 0;
5743 LOCK(tx_relay->m_bloom_filter_mutex);
5746 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5748 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5749 std::set<uint256>::iterator it = vInvTx.back();
5754 tx_relay->m_tx_inventory_to_send.erase(it);
5756 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
5765 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5768 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5770 vInv.push_back(inv);
5771 nRelayedTransactions++;
5776 tx_relay->m_tx_inventory_known_filter.insert(hash);
5781 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5788 auto stalling_timeout = m_block_stalling_timeout.load();
5789 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5798 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5808 if (state.vBlocksInFlight.size() > 0) {
5809 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5810 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5818 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5820 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5821 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5838 state.fSyncStarted =
false;
5840 peer->m_headers_sync_timeout = 0us;
5846 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5852 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5857 std::vector<CInv> vGetData;
5859 std::vector<const CBlockIndex*> vToDownload;
5861 auto get_inflight_budget = [&state]() {
5867 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5872 TryDownloadingHistoricalBlocks(
5874 get_inflight_budget(),
5875 vToDownload, from_tip,
5876 Assert(m_chainman.GetSnapshotBaseBlock()));
5879 uint32_t nFetchFlags = GetFetchFlags(*peer);
5881 BlockRequested(pto->
GetId(), *pindex);
5885 if (state.vBlocksInFlight.empty() && staller != -1) {
5886 if (State(staller)->m_stalling_since == 0us) {
5887 State(staller)->m_stalling_since = current_time;
5897 LOCK(m_tx_download_mutex);
5898 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
5907 if (!vGetData.empty())
5910 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, checkpoint.
@ 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,...
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.
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
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 Consensus::Params & GetConsensus() const
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool GetTryNewOutboundPeer() const
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(const std::string &node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return all or many randomly selected addresses, optionally by network.
bool CheckIncomingNonce(uint64_t nonce)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
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, uint256 > > 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
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
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 It is treated as if this was the little-endian interpretation of ...
The basic transaction that is broadcasted on the network and contained in blocks.
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
const Txid & GetHash() const LIFETIMEBOUND
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
std::set< uint256 > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
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 uint256 &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
TxMempoolInfo info(const GenTxid >xid) const
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
bool exists(const GenTxid >xid) const
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 BlockConnected(ChainstateRole role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
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.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
const CBlockIndex * GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The tip of the background sync chain.
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())
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 BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
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.
A generic txid reference (txid or wtxid).
const uint256 & GetHash() const LIFETIMEBOUND
static GenTxid Txid(const uint256 &hash)
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 InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< CTransactionRef > &extra_txn)
bool IsTxAvailable(size_t index) const
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
virtual std::optional< std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
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 std::vector< TxOrphanage::OrphanTxBase > GetOrphanTransactions()=0
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.
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)
A Span is an object that can refer to a contiguous sequence of objects.
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 ReadRawBlock(std::vector< uint8_t > &block, const FlatFilePos &pos) const
bool LoadingBlocks() const
bool IsPruneMode() const
Whether running in -prune mode.
bool ReadBlock(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
Manages warning messages within a node.
std::string ToString() const
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
@ BLOCK_CHECKPOINT
the block failed to meet one of our checkpoints
@ 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_MEMPOOL_POLICY
violated mempool's fee/size/descendant/RBF/etc limits
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_PREMATURE_SPEND
transaction spends a coinbase too early, or violates locktime/sequence locks
@ TX_INPUTS_NOT_STANDARD
inputs (covered by txid) failed policy rules
@ TX_WITNESS_STRIPPED
Transaction is missing a witness.
@ TX_CONFLICT
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
@ TX_WITNESS_MUTATED
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
@ 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
@ TX_CONSENSUS
invalid by consensus rules
@ TX_RECONSIDERABLE
fails some policy, but might be acceptable if submitted in a (different) package
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.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
#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...
Functions to serialize / deserialize common bitcoin types.
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, 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(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the 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
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.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
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
#define TRACEPOINT(context,...)
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
ReconciliationRegisterResult
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
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...