61 #include <util/time.h> 74 #include <initializer_list> 212 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
246 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
249 const bool m_is_inbound;
252 Mutex m_misbehavior_mutex;
254 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
257 Mutex m_block_inv_mutex;
261 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
265 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
277 std::atomic<int> m_starting_height{-1};
280 std::atomic<uint64_t> m_ping_nonce_sent{0};
282 std::atomic<std::chrono::microseconds> m_ping_start{0us};
284 std::atomic<bool> m_ping_queued{
false};
287 std::atomic<bool> m_wtxid_relay{
false};
299 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
301 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
312 std::set<Wtxid> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
316 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
319 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
322 uint64_t m_last_inv_sequence
GUARDED_BY(m_tx_inventory_mutex){1};
325 std::atomic<CAmount> m_fee_filter_received{0};
331 LOCK(m_tx_relay_mutex);
333 m_tx_relay = std::make_unique<Peer::TxRelay>();
334 return m_tx_relay.get();
339 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
368 std::atomic_bool m_addr_relay_enabled{
false};
372 mutable Mutex m_addr_send_times_mutex;
374 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
376 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
379 std::atomic_bool m_wants_addrv2{
false};
388 std::atomic<uint64_t> m_addr_rate_limited{0};
390 std::atomic<uint64_t> m_addr_processed{0};
396 Mutex m_getdata_requests_mutex;
398 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
404 Mutex m_headers_sync_mutex;
407 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
410 std::atomic<bool> m_sent_sendheaders{
false};
420 std::atomic<std::chrono::seconds> m_time_offset{0
s};
424 , m_our_services{our_services}
425 , m_is_inbound{is_inbound}
429 mutable Mutex m_tx_relay_mutex;
432 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
435 using PeerRef = std::shared_ptr<Peer>;
447 uint256 hashLastUnknownBlock{};
453 bool fSyncStarted{
false};
455 std::chrono::microseconds m_stalling_since{0us};
456 std::list<QueuedBlock> vBlocksInFlight;
458 std::chrono::microseconds m_downloading_since{0us};
460 bool fPreferredDownload{
false};
462 bool m_requested_hb_cmpctblocks{
false};
464 bool m_provides_cmpctblocks{
false};
490 struct ChainSyncTimeoutState {
492 std::chrono::seconds m_timeout{0
s};
496 bool m_sent_getheaders{
false};
498 bool m_protect{
false};
501 ChainSyncTimeoutState m_chain_sync;
504 int64_t m_last_block_announcement{0};
515 void ActiveTipChange(
const CBlockIndex& new_tip,
bool)
override 517 void BlockConnected(
const ChainstateRole& role,
const std::shared_ptr<const CBlock>& pblock,
const CBlockIndex* pindexConnected)
override 519 void BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
override 521 void UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
override 523 void BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
override 525 void NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
override 531 bool HasAllDesirableServiceFlags(
ServiceFlags services)
const override;
532 bool ProcessMessages(
CNode&
node, std::atomic<bool>& interrupt)
override 533 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
538 void StartScheduledTasks(
CScheduler& scheduler)
override;
539 void CheckForStaleTipAndEvictPeers()
override;
543 std::vector<node::TxOrphanage::OrphanInfo> GetOrphanTransactions() override
EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);
550 void SetBestBlock(
int height,
std::chrono::seconds time)
override 552 m_best_height = height;
553 m_best_block_time = time;
556 void UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
override;
560 void ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv, std::chrono::microseconds time_received,
561 const std::atomic<bool>& interruptMsgProc)
562 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
574 void ReattemptPrivateBroadcast(
CScheduler& scheduler);
586 void Misbehaving(Peer& peer,
const std::string& message);
597 bool via_compact_block,
const std::string& message =
"")
606 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
620 bool first_time_failure)
645 bool ProcessOrphanTx(Peer& peer)
655 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
657 bool via_compact_block)
661 bool CheckHeadersPoW(const
std::vector<
CBlockHeader>& headers, Peer& peer);
669 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
688 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
702 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
717 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
719 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
726 template <
typename... Args>
727 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const 733 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
739 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
782 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
785 std::atomic<int> m_best_height{-1};
787 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
795 const Options m_opts;
797 bool RejectIncomingTxs(
const CNode& peer)
const;
805 mutable Mutex m_peer_mutex;
812 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
822 uint32_t GetFetchFlags(
const Peer& peer)
const;
824 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
841 std::atomic<int> m_wtxid_relay_peers{0};
859 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
860 std::chrono::seconds average_interval,
865 Mutex m_most_recent_block_mutex;
866 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
867 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
869 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
873 Mutex m_headers_presync_mutex;
881 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
883 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
887 std::atomic_bool m_headers_presync_should_signal{
false};
957 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
963 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
968 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
1001 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
1003 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1015 int64_t ApproximateBestBlockDepth() const;
1025 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1043 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1045 const
uint256& stop_hash, uint32_t max_height_diff,
1093 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1099 const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const 1101 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1102 if (it == m_node_states.end())
1109 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1117 static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1122 void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1124 assert(peer.m_addr_known);
1125 peer.m_addr_known->insert(addr.
GetKey());
1128 void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1133 assert(peer.m_addr_known);
1134 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1136 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1138 peer.m_addrs_to_send.push_back(addr);
1143 static void AddKnownTx(Peer& peer,
const uint256& hash)
1145 auto tx_relay = peer.GetTxRelay();
1146 if (!tx_relay)
return;
1148 LOCK(tx_relay->m_tx_inventory_mutex);
1149 tx_relay->m_tx_inventory_known_filter.insert(hash);
1153 static bool CanServeBlocks(
const Peer& peer)
1160 static bool IsLimitedPeer(
const Peer& peer)
1167 static bool CanServeWitnesses(
const Peer& peer)
1172 std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1173 std::chrono::seconds average_interval,
1174 uint64_t network_key)
1176 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1177 auto& timer{it->second};
1179 timer = now + m_rng.rand_exp_duration(average_interval);
1184 bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1186 return mapBlocksInFlight.contains(hash);
1189 bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1191 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1192 auto [nodeid, block_it] = range.first->second;
1193 PeerRef peer{GetPeerRef(nodeid)};
1194 if (peer && !peer->m_is_inbound)
return true;
1200 void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1202 auto range = mapBlocksInFlight.equal_range(hash);
1203 if (range.first == range.second) {
1211 while (range.first != range.second) {
1212 const auto& [node_id, list_it]{range.first->second};
1214 if (from_peer && *from_peer != node_id) {
1221 if (state.vBlocksInFlight.begin() == list_it) {
1223 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1225 state.vBlocksInFlight.erase(list_it);
1227 if (state.vBlocksInFlight.empty()) {
1229 m_peers_downloading_from--;
1231 state.m_stalling_since = 0us;
1233 range.first = mapBlocksInFlight.erase(range.first);
1237 bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1241 CNodeState *state =
State(nodeid);
1242 assert(state !=
nullptr);
1247 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1248 if (range.first->second.first == nodeid) {
1250 *pit = &range.first->second.second;
1257 RemoveBlockRequest(hash, nodeid);
1259 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1261 if (state->vBlocksInFlight.size() == 1) {
1263 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1264 m_peers_downloading_from++;
1266 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1268 *pit = &itInFlight->second.second;
1273 void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1280 if (m_opts.ignore_incoming_txs)
return;
1282 CNodeState* nodestate =
State(nodeid);
1283 PeerRef peer{GetPeerRef(nodeid)};
1284 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1289 int num_outbound_hb_peers = 0;
1290 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1291 if (*it == nodeid) {
1292 lNodesAnnouncingHeaderAndIDs.erase(it);
1293 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1296 PeerRef peer_ref{GetPeerRef(*it)};
1297 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1299 if (peer && peer->m_is_inbound) {
1302 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1303 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1304 if (remove_peer && !remove_peer->m_is_inbound) {
1307 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1313 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1316 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1319 pnodeStop->m_bip152_highbandwidth_to =
false;
1322 lNodesAnnouncingHeaderAndIDs.pop_front();
1327 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1332 bool PeerManagerImpl::TipMayBeStale()
1336 if (m_last_tip_update.load() == 0
s) {
1337 m_last_tip_update = GetTime<std::chrono::seconds>();
1339 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1342 int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const 1347 bool PeerManagerImpl::CanDirectFetch()
1354 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1356 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1361 void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1362 CNodeState *state =
State(nodeid);
1363 assert(state !=
nullptr);
1365 if (!state->hashLastUnknownBlock.IsNull()) {
1368 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1369 state->pindexBestKnownBlock = pindex;
1371 state->hashLastUnknownBlock.SetNull();
1376 void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1377 CNodeState *state =
State(nodeid);
1378 assert(state !=
nullptr);
1380 ProcessBlockAvailability(nodeid);
1385 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1386 state->pindexBestKnownBlock = pindex;
1390 state->hashLastUnknownBlock = hash;
1395 void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1400 vBlocks.reserve(vBlocks.size() +
count);
1401 CNodeState *state =
State(peer.m_id);
1402 assert(state !=
nullptr);
1405 ProcessBlockAvailability(peer.m_id);
1407 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1418 state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1419 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1428 if (state->pindexLastCommonBlock ==
nullptr ||
1429 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1430 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1431 state->pindexLastCommonBlock = fork_point;
1433 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1436 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1442 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1445 void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1450 if (vBlocks.size() >=
count) {
1454 vBlocks.reserve(
count);
1457 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1474 void 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)
1476 std::vector<const CBlockIndex*> vToFetch;
1477 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1478 bool is_limited_peer = IsLimitedPeer(peer);
1480 while (pindexWalk->
nHeight < nMaxHeight) {
1484 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1485 vToFetch.resize(nToFetch);
1486 pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->
nHeight + nToFetch);
1487 vToFetch[nToFetch - 1] = pindexWalk;
1488 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1489 vToFetch[i - 1] = vToFetch[i]->
pprev;
1509 state->pindexLastCommonBlock = pindex;
1516 if (waitingfor == -1) {
1518 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1524 if (pindex->
nHeight > nWindowEnd) {
1526 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1528 if (nodeStaller) *nodeStaller = waitingfor;
1538 vBlocks.push_back(pindex);
1539 if (vBlocks.size() ==
count) {
1548 void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1550 uint64_t my_services;
1552 uint64_t your_services;
1554 std::string my_user_agent;
1562 my_user_agent =
"/pynode:0.0.1/";
1564 my_tx_relay =
false;
1567 my_services = peer.m_our_services;
1572 my_height = m_best_height;
1573 my_tx_relay = !RejectIncomingTxs(pnode);
1592 BCLog::NET,
"send version message: version=%d, blocks=%d%s, txrelay=%d, peer=%d\n",
1595 my_tx_relay, pnode.
GetId());
1598 void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1602 if (state) state->m_last_block_announcement = time_in_seconds;
1610 m_node_states.try_emplace(m_node_states.end(), nodeid);
1612 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1618 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1621 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1625 void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1629 for (
const auto& txid : unbroadcast_txids) {
1632 if (tx !=
nullptr) {
1633 InitiateTxBroadcastToAll(txid, tx->GetWitnessHash());
1642 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1645 void PeerManagerImpl::ReattemptPrivateBroadcast(
CScheduler& scheduler)
1649 size_t num_for_rebroadcast{0};
1650 const auto stale_txs = m_tx_for_private_broadcast.
GetStale();
1651 if (!stale_txs.empty()) {
1653 for (
const auto& stale_tx : stale_txs) {
1657 "Reattempting broadcast of stale txid=%s wtxid=%s",
1658 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString());
1659 ++num_for_rebroadcast;
1662 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString(),
1663 mempool_acceptable.m_state.ToString());
1664 m_tx_for_private_broadcast.
Remove(stale_tx);
1673 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, delta);
1676 void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1687 PeerRef peer = RemovePeer(nodeid);
1689 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1690 assert(m_wtxid_relay_peers >= 0);
1692 CNodeState *state =
State(nodeid);
1693 assert(state !=
nullptr);
1695 if (state->fSyncStarted)
1698 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1699 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1700 while (range.first != range.second) {
1701 auto [node_id, list_it] = range.first->second;
1702 if (node_id != nodeid) {
1705 range.first = mapBlocksInFlight.erase(range.first);
1710 LOCK(m_tx_download_mutex);
1711 m_txdownloadman.DisconnectedPeer(nodeid);
1713 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1714 m_num_preferred_download_peers -= state->fPreferredDownload;
1715 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1716 assert(m_peers_downloading_from >= 0);
1717 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1718 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1720 m_node_states.erase(nodeid);
1722 if (m_node_states.empty()) {
1724 assert(mapBlocksInFlight.empty());
1725 assert(m_num_preferred_download_peers == 0);
1726 assert(m_peers_downloading_from == 0);
1727 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1728 assert(m_wtxid_relay_peers == 0);
1729 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1732 if (
node.fSuccessfullyConnected &&
1733 !
node.IsBlockOnlyConn() && !
node.IsPrivateBroadcastConn() && !
node.IsInboundConn()) {
1741 LOCK(m_headers_presync_mutex);
1742 m_headers_presync_stats.erase(nodeid);
1744 if (
node.IsPrivateBroadcastConn() &&
1753 bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const 1756 return !(GetDesirableServiceFlags(services) & (~services));
1770 PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const 1773 auto it = m_peer_map.find(
id);
1774 return it != m_peer_map.end() ? it->second :
nullptr;
1777 PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1781 auto it = m_peer_map.find(
id);
1782 if (it != m_peer_map.end()) {
1783 ret = std::move(it->second);
1784 m_peer_map.erase(it);
1793 const CNodeState* state =
State(nodeid);
1794 if (state ==
nullptr)
1796 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1797 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1798 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1804 PeerRef peer = GetPeerRef(nodeid);
1805 if (peer ==
nullptr)
return false;
1814 auto ping_wait{0us};
1815 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1816 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1819 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1822 LOCK(tx_relay->m_tx_inventory_mutex);
1824 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1836 LOCK(peer->m_headers_sync_mutex);
1837 if (peer->m_headers_sync) {
1846 std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1848 LOCK(m_tx_download_mutex);
1849 return m_txdownloadman.GetOrphanTransactions();
1856 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1860 std::vector<PrivateBroadcast::TxBroadcastInfo> PeerManagerImpl::GetPrivateBroadcastInfo()
const 1865 std::vector<CTransactionRef> PeerManagerImpl::AbortPrivateBroadcast(
const uint256&
id)
1868 std::vector<CTransactionRef> removed_txs;
1870 size_t connections_cancelled{0};
1871 for (
const auto& [tx,
_] : snapshot) {
1872 if (tx->GetHash().ToUint256() !=
id && tx->GetWitnessHash().ToUint256() != id)
continue;
1873 if (
const auto peer_acks{m_tx_for_private_broadcast.
Remove(tx)}) {
1874 removed_txs.push_back(tx);
1885 void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1887 if (m_opts.max_extra_txs <= 0)
1889 if (!vExtraTxnForCompact.size())
1890 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1891 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1892 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1895 void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1897 LOCK(peer.m_misbehavior_mutex);
1899 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1900 peer.m_should_discourage =
true;
1909 bool via_compact_block,
const std::string& message)
1911 PeerRef peer{GetPeerRef(nodeid)};
1922 if (!via_compact_block) {
1923 if (peer) Misbehaving(*peer, message);
1931 if (peer && !via_compact_block && !peer->m_is_inbound) {
1932 if (peer) Misbehaving(*peer, message);
1939 if (peer) Misbehaving(*peer, message);
1943 if (peer) Misbehaving(*peer, message);
1948 if (message !=
"") {
1953 bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex& block_index)
1967 PeerRef peer = GetPeerRef(peer_id);
1976 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1979 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
2002 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
2008 : m_rng{opts.deterministic_rng},
2010 m_chainparams(chainman.GetParams()),
2014 m_chainman(chainman),
2017 m_warnings{warnings},
2022 if (opts.reconcile_txs) {
2027 void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2038 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2040 if (m_opts.private_broadcast) {
2041 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2045 void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2053 LOCK(m_tx_download_mutex);
2057 m_txdownloadman.ActiveTipChange();
2067 void PeerManagerImpl::BlockConnected(
2069 const std::shared_ptr<const CBlock>& pblock,
2074 m_last_tip_update = GetTime<std::chrono::seconds>();
2077 auto stalling_timeout = m_block_stalling_timeout.load();
2081 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2090 LOCK(m_tx_download_mutex);
2091 m_txdownloadman.BlockConnected(pblock);
2095 void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2097 LOCK(m_tx_download_mutex);
2098 m_txdownloadman.BlockDisconnected();
2105 void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2111 if (pindex->
nHeight <= m_highest_fast_announce)
2113 m_highest_fast_announce = pindex->
nHeight;
2117 uint256 hashBlock(pblock->GetHash());
2118 const std::shared_future<CSerializedNetMsg> lazy_ser{
2122 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2123 for (
const auto& tx : pblock->vtx) {
2124 most_recent_block_txs->emplace(tx->GetHash(), tx);
2125 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2128 LOCK(m_most_recent_block_mutex);
2129 m_most_recent_block_hash = hashBlock;
2130 m_most_recent_block = pblock;
2131 m_most_recent_compact_block = pcmpctblock;
2132 m_most_recent_block_txs = std::move(most_recent_block_txs);
2140 ProcessBlockAvailability(pnode->
GetId());
2144 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2146 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2147 hashBlock.ToString(), pnode->
GetId());
2150 PushMessage(*pnode, ser_cmpctblock.Copy());
2151 state.pindexBestHeaderSent = pindex;
2160 void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2162 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2165 if (fInitialDownload)
return;
2168 std::vector<uint256> vHashes;
2170 while (pindexToAnnounce != pindexFork) {
2172 pindexToAnnounce = pindexToAnnounce->
pprev;
2182 for (
auto& it : m_peer_map) {
2183 Peer& peer = *it.second;
2184 LOCK(peer.m_block_inv_mutex);
2185 for (
const uint256& hash : vHashes | std::views::reverse) {
2186 peer.m_blocks_for_headers_relay.push_back(hash);
2198 void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2202 const uint256 hash(block->GetHash());
2203 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2208 it != mapBlockSource.end() &&
2209 State(it->second.first)) {
2210 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2220 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2221 if (it != mapBlockSource.end()) {
2222 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2225 if (it != mapBlockSource.end())
2226 mapBlockSource.erase(it);
2234 bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2239 void PeerManagerImpl::SendPings()
2242 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2245 void PeerManagerImpl::InitiateTxBroadcastToAll(
const Txid& txid,
const Wtxid& wtxid)
2248 for(
auto& it : m_peer_map) {
2249 Peer& peer = *it.second;
2250 auto tx_relay = peer.GetTxRelay();
2251 if (!tx_relay)
continue;
2253 LOCK(tx_relay->m_tx_inventory_mutex);
2259 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2262 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2263 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2268 void PeerManagerImpl::InitiateTxBroadcastPrivate(
const CTransactionRef& tx)
2270 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2271 if (m_tx_for_private_broadcast.
Add(tx)) {
2279 void PeerManagerImpl::RelayAddress(
NodeId originator,
2295 const auto current_time{GetTime<std::chrono::seconds>()};
2303 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2305 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2306 assert(nRelayNodes <= best.size());
2310 for (
auto& [
id, peer] : m_peer_map) {
2311 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2313 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2314 if (hashKey > best[i].first) {
2315 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2316 best[i] = std::make_pair(hashKey, peer.get());
2323 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2324 PushAddress(*best[i].second, addr);
2328 void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2330 std::shared_ptr<const CBlock> a_recent_block;
2331 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2333 LOCK(m_most_recent_block_mutex);
2334 a_recent_block = m_most_recent_block;
2335 a_recent_compact_block = m_most_recent_compact_block;
2338 bool need_activate_chain =
false;
2350 need_activate_chain =
true;
2354 if (need_activate_chain) {
2356 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2363 bool can_direct_fetch{
false};
2371 if (!BlockRequestAllowed(*pindex)) {
2372 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2399 can_direct_fetch = CanDirectFetch();
2403 std::shared_ptr<const CBlock> pblock;
2404 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2405 pblock = a_recent_block;
2423 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2433 pblock = pblockRead;
2441 bool sendMerkleBlock =
false;
2443 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2444 LOCK(tx_relay->m_bloom_filter_mutex);
2445 if (tx_relay->m_bloom_filter) {
2446 sendMerkleBlock =
true;
2447 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2450 if (sendMerkleBlock) {
2458 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2469 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2482 LOCK(peer.m_block_inv_mutex);
2484 if (inv.
hash == peer.m_continuation_block) {
2488 std::vector<CInv> vInv;
2489 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2491 peer.m_continuation_block.SetNull();
2499 auto txinfo{std::visit(
2500 [&](
const auto&
id) {
2501 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2505 return std::move(txinfo.tx);
2510 LOCK(m_most_recent_block_mutex);
2511 if (m_most_recent_block_txs !=
nullptr) {
2512 auto it = m_most_recent_block_txs->find(gtxid);
2513 if (it != m_most_recent_block_txs->end())
return it->second;
2520 void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2524 auto tx_relay = peer.GetTxRelay();
2526 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2527 std::vector<CInv> vNotFound;
2532 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2533 if (interruptMsgProc)
return;
2538 const CInv &inv = *it++;
2540 if (tx_relay ==
nullptr) {
2546 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2549 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2552 vNotFound.push_back(inv);
2558 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2559 const CInv &inv = *it++;
2561 ProcessGetBlockData(pfrom, peer, inv);
2570 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2572 if (!vNotFound.empty()) {
2591 uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const 2593 uint32_t nFetchFlags = 0;
2594 if (CanServeWitnesses(peer)) {
2603 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2605 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2612 uint32_t tx_requested_size{0};
2613 for (
const auto& tx : resp.txn) tx_requested_size += tx->ComputeTotalSize();
2619 bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2623 Misbehaving(peer,
"header with invalid proof of work");
2628 if (!CheckHeadersAreContinuous(headers)) {
2629 Misbehaving(peer,
"non-continuous headers sequence");
2654 void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2655 const std::vector<CBlockHeader>& headers)
2659 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2660 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2662 headers[0].hashPrevBlock.ToString(),
2663 best_header->nHeight,
2673 bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const 2677 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2680 hashLastBlock = header.GetHash();
2685 bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2687 if (peer.m_headers_sync) {
2688 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2690 if (
result.success) peer.m_last_getheaders_timestamp = {};
2691 if (
result.request_more) {
2692 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2694 Assume(!locator.vHave.empty());
2697 if (!locator.vHave.empty()) {
2700 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2703 locator.vHave.front().ToString(), pfrom.
GetId());
2708 peer.m_headers_sync.reset(
nullptr);
2713 LOCK(m_headers_presync_mutex);
2714 m_headers_presync_stats.erase(pfrom.
GetId());
2717 HeadersPresyncStats stats;
2718 stats.first = peer.m_headers_sync->GetPresyncWork();
2720 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2721 peer.m_headers_sync->GetPresyncTime()};
2725 LOCK(m_headers_presync_mutex);
2726 m_headers_presync_stats[pfrom.
GetId()] = stats;
2727 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2728 bool best_updated =
false;
2729 if (best_it == m_headers_presync_stats.end()) {
2733 const HeadersPresyncStats* stat_best{
nullptr};
2734 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2735 if (!stat_best || stat > *stat_best) {
2740 m_headers_presync_bestpeer = peer_best;
2741 best_updated = (peer_best == pfrom.
GetId());
2742 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2744 m_headers_presync_bestpeer = pfrom.
GetId();
2745 best_updated =
true;
2747 if (best_updated && stats.second.has_value()) {
2749 m_headers_presync_should_signal =
true;
2756 headers.swap(
result.pow_validated_headers);
2767 bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
2774 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2778 if (total_work < minimum_chain_work) {
2782 if (headers.size() == m_opts.max_headers_result) {
2792 LOCK(peer.m_headers_sync_mutex);
2794 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2799 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2813 bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2815 if (header ==
nullptr) {
2817 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2825 bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2833 peer.m_last_getheaders_timestamp = current_time;
2844 void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2847 CNodeState *nodestate =
State(pfrom.
GetId());
2850 std::vector<const CBlockIndex*> vToFetch;
2858 vToFetch.push_back(pindexWalk);
2860 pindexWalk = pindexWalk->
pprev;
2871 std::vector<CInv> vGetData;
2873 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2878 uint32_t nFetchFlags = GetFetchFlags(peer);
2880 BlockRequested(pfrom.
GetId(), *pindex);
2884 if (vGetData.size() > 1) {
2889 if (vGetData.size() > 0) {
2890 if (!m_opts.ignore_incoming_txs &&
2891 nodestate->m_provides_cmpctblocks &&
2892 vGetData.size() == 1 &&
2893 mapBlocksInFlight.size() == 1 &&
2909 void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2910 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2913 CNodeState *nodestate =
State(pfrom.
GetId());
2922 nodestate->m_last_block_announcement =
GetTime();
2930 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2952 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) {
2954 nodestate->m_chain_sync.m_protect =
true;
2955 ++m_outbound_peers_with_protect_from_disconnect;
2960 void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2961 std::vector<CBlockHeader>&& headers,
2962 bool via_compact_block)
2964 size_t nCount = headers.size();
2971 LOCK(peer.m_headers_sync_mutex);
2972 if (peer.m_headers_sync) {
2973 peer.m_headers_sync.reset(
nullptr);
2974 LOCK(m_headers_presync_mutex);
2975 m_headers_presync_stats.erase(pfrom.
GetId());
2979 peer.m_last_getheaders_timestamp = {};
2987 if (!CheckHeadersPoW(headers, peer)) {
3002 bool already_validated_work =
false;
3005 bool have_headers_sync =
false;
3007 LOCK(peer.m_headers_sync_mutex);
3009 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3021 if (headers.empty()) {
3025 have_headers_sync = !!peer.m_headers_sync;
3030 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3032 if (!headers_connect_blockindex) {
3036 HandleUnconnectingHeaders(pfrom, peer, headers);
3043 peer.m_last_getheaders_timestamp = {};
3053 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3060 already_validated_work =
true;
3066 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3067 *chain_start_header, headers)) {
3079 bool received_new_header{last_received_header ==
nullptr};
3085 state, &pindexLast)};
3091 "If this happens with all peers, consider database corruption (that -reindex may fix) " 3092 "or a potential consensus incompatibility.",
3095 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3101 if (processed && received_new_header) {
3102 LogBlockHeader(*pindexLast, pfrom,
false);
3106 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3108 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3110 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
3114 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3117 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3123 bool first_time_failure)
3129 PeerRef peer{GetPeerRef(nodeid)};
3132 ptx->GetHash().ToString(),
3133 ptx->GetWitnessHash().ToString(),
3137 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3140 AddToCompactExtraTransactions(ptx);
3142 for (
const Txid& parent_txid : unique_parents) {
3143 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3146 return package_to_validate;
3149 void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3155 m_txdownloadman.MempoolAcceptedTx(tx);
3159 tx->GetHash().ToString(),
3160 tx->GetWitnessHash().ToString(),
3163 InitiateTxBroadcastToAll(tx->GetHash(), tx->GetWitnessHash());
3166 AddToCompactExtraTransactions(removedTx);
3176 const auto&
package = package_to_validate.m_txns;
3177 const auto& senders = package_to_validate.
m_senders;
3180 m_txdownloadman.MempoolRejectedPackage(package);
3183 if (!
Assume(package.size() == 2))
return;
3187 auto package_iter = package.rbegin();
3188 auto senders_iter = senders.rbegin();
3189 while (package_iter != package.rend()) {
3190 const auto& tx = *package_iter;
3191 const NodeId nodeid = *senders_iter;
3192 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3196 const auto& tx_result = it_result->second;
3197 switch (tx_result.m_result_type) {
3200 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3210 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3228 bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3235 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3238 const Txid& orphanHash = porphanTx->GetHash();
3239 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3243 ProcessValidTx(peer.m_id, porphanTx,
result.m_replaced_transactions);
3256 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3265 bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3267 const uint256& stop_hash, uint32_t max_height_diff,
3271 const bool supported_filter_type =
3274 if (!supported_filter_type) {
3276 static_cast<uint8_t>(filter_type),
node.DisconnectMsg(
fLogIPs));
3277 node.fDisconnect =
true;
3286 if (!stop_index || !BlockRequestAllowed(*stop_index)) {
3289 node.fDisconnect =
true;
3294 uint32_t stop_height = stop_index->
nHeight;
3295 if (start_height > stop_height) {
3297 "start height %d and stop height %d, %s\n",
3298 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3299 node.fDisconnect =
true;
3302 if (stop_height - start_height >= max_height_diff) {
3304 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3305 node.fDisconnect =
true;
3310 if (!filter_index) {
3320 uint8_t filter_type_ser;
3321 uint32_t start_height;
3324 vRecv >> filter_type_ser >> start_height >> stop_hash;
3330 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3335 std::vector<BlockFilter> filters;
3337 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3342 for (
const auto& filter : filters) {
3349 uint8_t filter_type_ser;
3350 uint32_t start_height;
3353 vRecv >> filter_type_ser >> start_height >> stop_hash;
3359 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3365 if (start_height > 0) {
3367 stop_index->
GetAncestor(static_cast<int>(start_height - 1));
3369 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3375 std::vector<uint256> filter_hashes;
3377 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3391 uint8_t filter_type_ser;
3394 vRecv >> filter_type_ser >> stop_hash;
3400 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3401 std::numeric_limits<uint32_t>::max(),
3402 stop_index, filter_index)) {
3406 std::vector<uint256> headers(stop_index->
nHeight / CFCHECKPT_INTERVAL);
3410 for (
int i = headers.size() - 1; i >= 0; i--) {
3411 int height = (i + 1) * CFCHECKPT_INTERVAL;
3415 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3429 bool new_block{
false};
3430 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3432 node.m_last_block_time = GetTime<std::chrono::seconds>();
3437 RemoveBlockRequest(block->GetHash(), std::nullopt);
3440 mapBlockSource.erase(block->GetHash());
3444 void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3446 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3447 bool fBlockRead{
false};
3451 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3452 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3453 bool requested_block_from_this_peer{
false};
3456 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3458 while (range_flight.first != range_flight.second) {
3459 auto [node_id, block_it] = range_flight.first->second;
3460 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3461 requested_block_from_this_peer =
true;
3464 range_flight.first++;
3467 if (!requested_block_from_this_peer) {
3479 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3490 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3493 if (first_in_flight) {
3498 std::vector<CInv> invs;
3503 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3516 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3531 void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3543 "Saw new %sheader hash=%s height=%d peer=%d%s",
3544 via_compact_block ?
"cmpctblock " :
"",
3557 void PeerManagerImpl::PushPrivateBroadcastTx(
CNode&
node)
3564 node.fDisconnect =
true;
3570 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3576 void PeerManagerImpl::ProcessMessage(Peer& peer,
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3577 const std::chrono::microseconds time_received,
3578 const std::atomic<bool>& interruptMsgProc)
3593 uint64_t nNonce = 1;
3596 std::string cleanSubVer;
3597 int starting_height = -1;
3600 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3615 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3617 GetDesirableServiceFlags(nServices),
3630 if (!vRecv.
empty()) {
3638 if (!vRecv.
empty()) {
3639 std::string strSubVer;
3643 if (!vRecv.
empty()) {
3644 vRecv >> starting_height;
3664 PushNodeVersion(pfrom, peer);
3673 peer.m_their_services = nServices;
3677 pfrom.cleanSubVer = cleanSubVer;
3679 peer.m_starting_height = starting_height;
3689 (fRelay || (peer.m_our_services &
NODE_BLOOM))) {
3690 auto*
const tx_relay = peer.SetTxRelay();
3692 LOCK(tx_relay->m_bloom_filter_mutex);
3693 tx_relay->m_relay_txs = fRelay;
3699 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3720 if (greatest_common_version >= 70016) {
3735 const auto* tx_relay = peer.GetTxRelay();
3736 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3738 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3751 m_num_preferred_download_peers += state->fPreferredDownload;
3757 bool send_getaddr{
false};
3759 send_getaddr = SetupAddressRelay(pfrom, peer);
3769 peer.m_getaddr_sent =
true;
3793 peer.m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3797 m_outbound_time_offsets.Add(peer.m_time_offset);
3798 m_outbound_time_offsets.WarnIfOutOfSync();
3802 if (greatest_common_version <= 70012) {
3803 constexpr
auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3804 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3827 auto new_peer_msg = [&]() {
3829 return strprintf(
"New %s peer connected: transport: %s, version: %d, blocks=%d peer=%d%s%s\n",
3832 pfrom.
nVersion.load(), peer.m_starting_height,
3834 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3842 LogInfo(
"%s", new_peer_msg());
3845 if (
auto tx_relay = peer.GetTxRelay()) {
3854 tx_relay->m_tx_inventory_mutex,
3855 return tx_relay->m_tx_inventory_to_send.empty() &&
3856 tx_relay->m_next_inv_send_time == 0
s));
3866 PushPrivateBroadcastTx(pfrom);
3879 if (m_txreconciliation) {
3880 if (!peer.m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3884 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3890 const CNodeState* state =
State(pfrom.
GetId());
3894 .m_wtxid_relay = peer.m_wtxid_relay,
3903 peer.m_prefers_headers =
true;
3908 bool sendcmpct_hb{
false};
3909 uint64_t sendcmpct_version{0};
3910 vRecv >> sendcmpct_hb >> sendcmpct_version;
3916 CNodeState* nodestate =
State(pfrom.
GetId());
3917 nodestate->m_provides_cmpctblocks =
true;
3918 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3935 if (!peer.m_wtxid_relay) {
3936 peer.m_wtxid_relay =
true;
3937 m_wtxid_relay_peers++;
3956 peer.m_wants_addrv2 =
true;
3964 if (!m_txreconciliation) {
3965 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3976 if (RejectIncomingTxs(pfrom)) {
3985 const auto* tx_relay = peer.GetTxRelay();
3986 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3992 uint32_t peer_txreconcl_version;
3993 uint64_t remote_salt;
3994 vRecv >> peer_txreconcl_version >> remote_salt;
3997 peer_txreconcl_version, remote_salt);
4029 const auto ser_params{
4037 std::vector<CAddress> vAddr;
4039 vRecv >> ser_params(vAddr);
4041 if (!SetupAddressRelay(pfrom, peer)) {
4048 Misbehaving(peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
4053 std::vector<CAddress> vAddrOk;
4054 const auto current_a_time{Now<NodeSeconds>()};
4057 const auto current_time{GetTime<std::chrono::microseconds>()};
4060 const auto time_diff = std::max(current_time - peer.m_addr_token_timestamp, 0us);
4064 peer.m_addr_token_timestamp = current_time;
4067 uint64_t num_proc = 0;
4068 uint64_t num_rate_limit = 0;
4069 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
4072 if (interruptMsgProc)
4076 if (peer.m_addr_token_bucket < 1.0) {
4082 peer.m_addr_token_bucket -= 1.0;
4091 addr.
nTime = current_a_time - 5 * 24h;
4093 AddAddressKnown(peer, addr);
4100 if (addr.
nTime > current_a_time - 10min && !peer.m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
4102 RelayAddress(pfrom.
GetId(), addr, reachable);
4106 vAddrOk.push_back(addr);
4109 peer.m_addr_processed += num_proc;
4110 peer.m_addr_rate_limited += num_rate_limit;
4111 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
4112 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
4114 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
4115 if (vAddr.size() < 1000) peer.m_getaddr_sent =
false;
4126 std::vector<CInv> vInv;
4130 Misbehaving(peer,
strprintf(
"inv message size = %u", vInv.size()));
4134 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4138 const auto current_time{GetTime<std::chrono::microseconds>()};
4141 for (
CInv& inv : vInv) {
4142 if (interruptMsgProc)
return;
4147 if (peer.m_wtxid_relay) {
4154 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4157 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4165 best_block = &inv.
hash;
4168 if (reject_tx_invs) {
4174 AddKnownTx(peer, inv.
hash);
4177 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4185 if (best_block !=
nullptr) {
4197 if (state.fSyncStarted || (!peer.m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4198 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer)) {
4200 m_chainman.m_best_header->nHeight, best_block->ToString(),
4203 if (!state.fSyncStarted) {
4204 peer.m_inv_triggered_getheaders_before_sync =
true;
4208 m_last_block_inv_triggering_headers_sync = *best_block;
4217 std::vector<CInv> vInv;
4221 Misbehaving(peer,
strprintf(
"getdata message size = %u", vInv.size()));
4227 if (vInv.size() > 0) {
4232 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4233 if (!pushed_tx_opt) {
4244 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4248 peer.m_ping_queued =
true;
4249 MaybeSendPing(pfrom, peer, GetTime<std::chrono::microseconds>());
4259 LOCK(peer.m_getdata_requests_mutex);
4260 peer.m_getdata_requests.insert(peer.m_getdata_requests.end(), vInv.begin(), vInv.end());
4261 ProcessGetData(pfrom, peer, interruptMsgProc);
4270 vRecv >> locator >> hashStop;
4286 std::shared_ptr<const CBlock> a_recent_block;
4288 LOCK(m_most_recent_block_mutex);
4289 a_recent_block = m_most_recent_block;
4292 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4306 LogDebug(
BCLog::NET,
"getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->
nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), nLimit, pfrom.
GetId());
4322 if (--nLimit <= 0) {
4326 WITH_LOCK(peer.m_block_inv_mutex, {peer.m_continuation_block = pindex->GetBlockHash();});
4338 for (
size_t i = 1; i < req.indexes.size(); ++i) {
4339 Assume(req.indexes[i] > req.indexes[i-1]);
4342 std::shared_ptr<const CBlock> recent_block;
4344 LOCK(m_most_recent_block_mutex);
4345 if (m_most_recent_block_hash == req.blockhash)
4346 recent_block = m_most_recent_block;
4350 SendBlockTransactions(pfrom, peer, *recent_block, req);
4369 if (!block_pos.IsNull()) {
4376 SendBlockTransactions(pfrom, peer, block, req);
4389 WITH_LOCK(peer.m_getdata_requests_mutex, peer.m_getdata_requests.push_back(inv));
4397 vRecv >> locator >> hashStop;
4415 if (m_chainman.
ActiveTip() ==
nullptr ||
4417 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4424 CNodeState *nodestate =
State(pfrom.
GetId());
4433 if (!BlockRequestAllowed(*pindex)) {
4434 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4447 std::vector<CBlock> vHeaders;
4448 int nLimit = m_opts.max_headers_result;
4449 LogDebug(
BCLog::NET,
"getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), pfrom.
GetId());
4452 vHeaders.emplace_back(pindex->GetBlockHeader());
4453 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4468 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4474 if (RejectIncomingTxs(pfrom)) {
4488 const Txid& txid = ptx->GetHash();
4489 const Wtxid& wtxid = ptx->GetWitnessHash();
4492 AddKnownTx(peer, hash);
4494 if (
const auto num_broadcasted{m_tx_for_private_broadcast.
Remove(ptx)}) {
4496 "network from peer=%d%s; stopping private broadcast attempts",
4507 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4508 if (!should_validate) {
4513 if (!m_mempool.
exists(txid)) {
4514 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4517 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4519 InitiateTxBroadcastToAll(txid, wtxid);
4523 if (package_to_validate) {
4526 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4527 ProcessPackageResult(package_to_validate.value(), package_result);
4533 Assume(!package_to_validate.has_value());
4539 ProcessValidTx(pfrom.
GetId(), ptx,
result.m_replaced_transactions);
4543 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4546 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4547 ProcessPackageResult(package_to_validate.value(), package_result);
4563 vRecv >> cmpctblock;
4565 bool received_new_header =
false;
4575 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer);
4585 received_new_header =
true;
4593 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4600 if (received_new_header) {
4601 LogBlockHeader(*pindex, pfrom,
true);
4604 bool fProcessBLOCKTXN =
false;
4608 bool fRevertToHeaderProcessing =
false;
4612 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4613 bool fBlockReconstructed =
false;
4619 CNodeState *nodestate =
State(pfrom.
GetId());
4624 nodestate->m_last_block_announcement =
GetTime();
4630 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4631 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4632 bool requested_block_from_this_peer{
false};
4635 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4637 while (range_flight.first != range_flight.second) {
4638 if (range_flight.first->second.first == pfrom.
GetId()) {
4639 requested_block_from_this_peer =
true;
4642 range_flight.first++;
4647 if (requested_block_from_this_peer) {
4650 std::vector<CInv> vInv(1);
4658 if (!already_in_flight && !CanDirectFetch()) {
4666 requested_block_from_this_peer) {
4667 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4668 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4669 if (!(*queuedBlockIt)->partialBlock)
4682 Misbehaving(peer,
"invalid compact block");
4685 if (first_in_flight) {
4687 std::vector<CInv> vInv(1);
4698 for (
size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {
4703 fProcessBLOCKTXN =
true;
4704 }
else if (first_in_flight) {
4711 IsBlockRequestedFromOutbound(blockhash) ||
4730 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4735 std::vector<CTransactionRef> dummy;
4737 status = tempBlock.FillBlock(*pblock, dummy,
4740 fBlockReconstructed =
true;
4744 if (requested_block_from_this_peer) {
4747 std::vector<CInv> vInv(1);
4753 fRevertToHeaderProcessing =
true;
4758 if (fProcessBLOCKTXN) {
4761 return ProcessCompactBlockTxns(pfrom, peer, txn);
4764 if (fRevertToHeaderProcessing) {
4770 return ProcessHeadersMessage(pfrom, peer, {cmpctblock.header},
true);
4773 if (fBlockReconstructed) {
4778 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4796 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4813 return ProcessCompactBlockTxns(pfrom, peer, resp);
4824 std::vector<CBlockHeader> headers;
4828 if (nCount > m_opts.max_headers_result) {
4829 Misbehaving(peer,
strprintf(
"headers message size = %u", nCount));
4832 headers.resize(nCount);
4833 for (
unsigned int n = 0; n < nCount; n++) {
4834 vRecv >> headers[n];
4838 ProcessHeadersMessage(pfrom, peer, std::move(headers),
false);
4842 if (m_headers_presync_should_signal.exchange(
false)) {
4843 HeadersPresyncStats stats;
4845 LOCK(m_headers_presync_mutex);
4846 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4847 if (it != m_headers_presync_stats.end()) stats = it->second;
4865 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4876 Misbehaving(peer,
"mutated block");
4881 bool forceProcessing =
false;
4882 const uint256 hash(pblock->GetHash());
4883 bool min_pow_checked =
false;
4888 forceProcessing = IsBlockRequested(hash);
4889 RemoveBlockRequest(hash, pfrom.
GetId());
4893 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4897 min_pow_checked =
true;
4900 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4917 Assume(SetupAddressRelay(pfrom, peer));
4921 if (peer.m_getaddr_recvd) {
4925 peer.m_getaddr_recvd =
true;
4927 peer.m_addrs_to_send.clear();
4928 std::vector<CAddress> vAddr;
4934 for (
const CAddress &addr : vAddr) {
4935 PushAddress(peer, addr);
4963 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
4964 LOCK(tx_relay->m_tx_inventory_mutex);
4965 tx_relay->m_send_mempool =
true;
4991 const auto ping_end = time_received;
4994 bool bPingFinished =
false;
4995 std::string sProblem;
4997 if (nAvail >=
sizeof(
nonce)) {
5001 if (peer.m_ping_nonce_sent != 0) {
5002 if (
nonce == peer.m_ping_nonce_sent) {
5004 bPingFinished =
true;
5005 const auto ping_time = ping_end - peer.m_ping_start.load();
5006 if (ping_time.count() >= 0) {
5017 sProblem =
"Timing mishap";
5021 sProblem =
"Nonce mismatch";
5024 bPingFinished =
true;
5025 sProblem =
"Nonce zero";
5029 sProblem =
"Unsolicited pong without ping";
5033 bPingFinished =
true;
5034 sProblem =
"Short payload";
5037 if (!(sProblem.empty())) {
5041 peer.m_ping_nonce_sent,
5045 if (bPingFinished) {
5046 peer.m_ping_nonce_sent = 0;
5060 if (!filter.IsWithinSizeConstraints())
5063 Misbehaving(peer,
"too-large bloom filter");
5064 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5066 LOCK(tx_relay->m_bloom_filter_mutex);
5067 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
5068 tx_relay->m_relay_txs =
true;
5082 std::vector<unsigned char> vData;
5090 }
else if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5091 LOCK(tx_relay->m_bloom_filter_mutex);
5092 if (tx_relay->m_bloom_filter) {
5093 tx_relay->m_bloom_filter->insert(vData);
5099 Misbehaving(peer,
"bad filteradd message");
5110 auto tx_relay = peer.GetTxRelay();
5111 if (!tx_relay)
return;
5114 LOCK(tx_relay->m_bloom_filter_mutex);
5115 tx_relay->m_bloom_filter =
nullptr;
5116 tx_relay->m_relay_txs =
true;
5125 vRecv >> newFeeFilter;
5127 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5128 tx_relay->m_fee_filter_received = newFeeFilter;
5136 ProcessGetCFilters(pfrom, peer, vRecv);
5141 ProcessGetCFHeaders(pfrom, peer, vRecv);
5146 ProcessGetCFCheckPt(pfrom, peer, vRecv);
5151 std::vector<CInv> vInv;
5153 std::vector<GenTxid> tx_invs;
5155 for (
CInv &inv : vInv) {
5161 LOCK(m_tx_download_mutex);
5162 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5171 bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5174 LOCK(peer.m_misbehavior_mutex);
5177 if (!peer.m_should_discourage)
return false;
5179 peer.m_should_discourage =
false;
5184 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5190 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5210 bool PeerManagerImpl::ProcessMessages(
CNode&
node, std::atomic<bool>& interruptMsgProc)
5215 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5216 if (maybe_peer ==
nullptr)
return false;
5217 Peer& peer{*maybe_peer};
5221 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent)
return false;
5224 LOCK(peer.m_getdata_requests_mutex);
5225 if (!peer.m_getdata_requests.empty()) {
5226 ProcessGetData(
node, peer, interruptMsgProc);
5230 const bool processed_orphan = ProcessOrphanTx(peer);
5232 if (
node.fDisconnect)
5235 if (processed_orphan)
return true;
5240 LOCK(peer.m_getdata_requests_mutex);
5241 if (!peer.m_getdata_requests.empty())
return true;
5245 if (
node.fPauseSend)
return false;
5247 auto poll_result{
node.PollMessage()};
5254 bool fMoreWork = poll_result->second;
5258 node.m_addr_name.c_str(),
5259 node.ConnectionTypeAsString().c_str(),
5265 if (m_opts.capture_messages) {
5270 ProcessMessage(peer,
node,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5271 if (interruptMsgProc)
return false;
5273 LOCK(peer.m_getdata_requests_mutex);
5274 if (!peer.m_getdata_requests.empty()) fMoreWork =
true;
5281 LOCK(m_tx_download_mutex);
5282 if (m_txdownloadman.HaveMoreWork(peer.m_id)) fMoreWork =
true;
5283 }
catch (
const std::exception& e) {
5292 void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5305 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5307 if (state.m_chain_sync.m_timeout != 0
s) {
5308 state.m_chain_sync.m_timeout = 0
s;
5309 state.m_chain_sync.m_work_header =
nullptr;
5310 state.m_chain_sync.m_sent_getheaders =
false;
5312 }
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)) {
5320 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5321 state.m_chain_sync.m_sent_getheaders =
false;
5322 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5326 if (state.m_chain_sync.m_sent_getheaders) {
5328 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5331 assert(state.m_chain_sync.m_work_header);
5336 MaybeSendGetHeaders(pto,
5337 GetLocator(state.m_chain_sync.m_work_header->pprev),
5339 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());
5340 state.m_chain_sync.m_sent_getheaders =
true;
5352 void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5361 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5365 if (pnode->
GetId() > youngest_peer.first) {
5366 next_youngest_peer = youngest_peer;
5367 youngest_peer.first = pnode->
GetId();
5371 NodeId to_disconnect = youngest_peer.first;
5372 if (youngest_peer.second > next_youngest_peer.second) {
5375 to_disconnect = next_youngest_peer.first;
5384 CNodeState *node_state =
State(pnode->
GetId());
5385 if (node_state ==
nullptr ||
5388 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5392 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5408 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5417 if (state ==
nullptr)
return;
5419 if (state->m_chain_sync.m_protect)
return;
5423 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->
GetId() > worst_peer)) {
5424 worst_peer = pnode->
GetId();
5425 oldest_block_announcement = state->m_last_block_announcement;
5428 if (worst_peer != -1) {
5439 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5443 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5460 void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5464 auto now{GetTime<std::chrono::seconds>()};
5466 EvictExtraOutboundPeers(now);
5468 if (now > m_stale_tip_check_time) {
5472 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5481 if (!m_initial_sync_finished && CanDirectFetch()) {
5483 m_initial_sync_finished =
true;
5487 void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5490 peer.m_ping_nonce_sent &&
5500 bool pingSend =
false;
5502 if (peer.m_ping_queued) {
5507 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5516 }
while (
nonce == 0);
5517 peer.m_ping_queued =
false;
5518 peer.m_ping_start = now;
5520 peer.m_ping_nonce_sent =
nonce;
5524 peer.m_ping_nonce_sent = 0;
5530 void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5533 if (!peer.m_addr_relay_enabled)
return;
5535 LOCK(peer.m_addr_send_times_mutex);
5538 peer.m_next_local_addr_send < current_time) {
5545 if (peer.m_next_local_addr_send != 0us) {
5546 peer.m_addr_known->reset();
5549 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5550 if (peer.m_next_local_addr_send == 0us) {
5554 if (IsAddrCompatible(peer, local_addr)) {
5555 std::vector<CAddress> self_announcement{local_addr};
5556 if (peer.m_wants_addrv2) {
5564 PushAddress(peer, local_addr);
5571 if (current_time <= peer.m_next_addr_send)
return;
5584 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5585 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5588 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5589 peer.m_addrs_to_send.end());
5592 if (peer.m_addrs_to_send.empty())
return;
5594 if (peer.m_wants_addrv2) {
5599 peer.m_addrs_to_send.clear();
5602 if (peer.m_addrs_to_send.capacity() > 40) {
5603 peer.m_addrs_to_send.shrink_to_fit();
5607 void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5615 CNodeState &state = *
State(
node.GetId());
5616 if (state.pindexBestKnownBlock !=
nullptr &&
5623 peer.m_sent_sendheaders =
true;
5628 void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5630 if (m_opts.ignore_incoming_txs)
return;
5646 if (peer.m_fee_filter_sent == MAX_FILTER) {
5649 peer.m_next_send_feefilter = 0us;
5652 if (current_time > peer.m_next_send_feefilter) {
5653 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5656 if (filterToSend != peer.m_fee_filter_sent) {
5658 peer.m_fee_filter_sent = filterToSend;
5665 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5671 class CompareInvMempoolOrder
5675 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5677 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5686 bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const 5696 bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5701 if (
node.IsBlockOnlyConn())
return false;
5703 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5707 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5713 bool PeerManagerImpl::SendMessages(
CNode&
node)
5718 PeerRef maybe_peer{GetPeerRef(
node.GetId())};
5719 if (!maybe_peer)
return false;
5720 Peer& peer{*maybe_peer};
5725 if (MaybeDiscourageAndDisconnect(
node, peer))
return true;
5728 if (!
node.IsInboundConn() && !peer.m_outbound_version_message_sent) {
5729 PushNodeVersion(
node, peer);
5730 peer.m_outbound_version_message_sent =
true;
5734 if (!
node.fSuccessfullyConnected ||
node.fDisconnect)
5737 const auto current_time{GetTime<std::chrono::microseconds>()};
5742 if (
node.IsPrivateBroadcastConn()) {
5746 node.fDisconnect =
true;
5753 node.fDisconnect =
true;
5757 MaybeSendPing(
node, peer, current_time);
5760 if (
node.fDisconnect)
return true;
5762 MaybeSendAddr(
node, peer, current_time);
5764 MaybeSendSendHeaders(
node, peer);
5769 CNodeState &state = *
State(
node.GetId());
5772 if (m_chainman.m_best_header ==
nullptr) {
5779 bool sync_blocks_and_headers_from_peer =
false;
5780 if (state.fPreferredDownload) {
5781 sync_blocks_and_headers_from_peer =
true;
5782 }
else if (CanServeBlocks(peer) && !
node.IsAddrFetchConn()) {
5792 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5793 sync_blocks_and_headers_from_peer =
true;
5799 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5800 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5808 if (pindexStart->
pprev)
5809 pindexStart = pindexStart->
pprev;
5813 state.fSyncStarted =
true;
5837 LOCK(peer.m_block_inv_mutex);
5838 std::vector<CBlock> vHeaders;
5839 bool fRevertToInv = ((!peer.m_prefers_headers &&
5840 (!state.m_requested_hb_cmpctblocks || peer.m_blocks_for_headers_relay.size() > 1)) ||
5843 ProcessBlockAvailability(
node.GetId());
5845 if (!fRevertToInv) {
5846 bool fFoundStartingHeader =
false;
5850 for (
const uint256& hash : peer.m_blocks_for_headers_relay) {
5855 fRevertToInv =
true;
5858 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5870 fRevertToInv =
true;
5873 pBestIndex = pindex;
5874 if (fFoundStartingHeader) {
5877 }
else if (PeerHasHeader(&state, pindex)) {
5879 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5882 fFoundStartingHeader =
true;
5887 fRevertToInv =
true;
5892 if (!fRevertToInv && !vHeaders.empty()) {
5893 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5897 vHeaders.front().GetHash().ToString(),
node.GetId());
5899 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5901 LOCK(m_most_recent_block_mutex);
5902 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5906 if (cached_cmpctblock_msg.has_value()) {
5907 PushMessage(
node, std::move(cached_cmpctblock_msg.value()));
5915 state.pindexBestHeaderSent = pBestIndex;
5916 }
else if (peer.m_prefers_headers) {
5917 if (vHeaders.size() > 1) {
5920 vHeaders.front().GetHash().ToString(),
5921 vHeaders.back().GetHash().ToString(),
node.GetId());
5924 vHeaders.front().GetHash().ToString(),
node.GetId());
5927 state.pindexBestHeaderSent = pBestIndex;
5929 fRevertToInv =
true;
5935 if (!peer.m_blocks_for_headers_relay.empty()) {
5936 const uint256& hashToAnnounce = peer.m_blocks_for_headers_relay.back();
5949 if (!PeerHasHeader(&state, pindex)) {
5950 peer.m_blocks_for_inv_relay.push_back(hashToAnnounce);
5956 peer.m_blocks_for_headers_relay.clear();
5962 std::vector<CInv> vInv;
5964 LOCK(peer.m_block_inv_mutex);
5968 for (
const uint256& hash : peer.m_blocks_for_inv_relay) {
5975 peer.m_blocks_for_inv_relay.clear();
5978 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
5979 LOCK(tx_relay->m_tx_inventory_mutex);
5982 if (tx_relay->m_next_inv_send_time < current_time) {
5983 fSendTrickle =
true;
5984 if (
node.IsInboundConn()) {
5993 LOCK(tx_relay->m_bloom_filter_mutex);
5994 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5998 if (fSendTrickle && tx_relay->m_send_mempool) {
5999 auto vtxinfo = m_mempool.
infoAll();
6000 tx_relay->m_send_mempool =
false;
6001 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6003 LOCK(tx_relay->m_bloom_filter_mutex);
6005 for (
const auto& txinfo : vtxinfo) {
6006 const Txid& txid{txinfo.tx->GetHash()};
6007 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
6008 const auto inv = peer.m_wtxid_relay ?
6011 tx_relay->m_tx_inventory_to_send.erase(wtxid);
6014 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6017 if (tx_relay->m_bloom_filter) {
6018 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6020 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6021 vInv.push_back(inv);
6032 std::vector<std::set<Wtxid>::iterator> vInvTx;
6033 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
6034 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
6035 vInvTx.push_back(it);
6037 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6040 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
6041 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6044 unsigned int nRelayedTransactions = 0;
6045 LOCK(tx_relay->m_bloom_filter_mutex);
6048 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
6050 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6051 std::set<Wtxid>::iterator it = vInvTx.back();
6055 tx_relay->m_tx_inventory_to_send.erase(it);
6057 auto txinfo = m_mempool.
info(wtxid);
6064 const auto inv = peer.m_wtxid_relay ?
6066 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
6068 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
6072 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6075 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6077 vInv.push_back(inv);
6078 nRelayedTransactions++;
6083 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6088 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6095 auto stalling_timeout = m_block_stalling_timeout.load();
6096 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6101 node.fDisconnect =
true;
6105 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6115 if (state.vBlocksInFlight.size() > 0) {
6116 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6117 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6119 LogInfo(
"Timeout downloading block %s, %s\n", queuedBlock.pindex->GetBlockHash().ToString(),
node.DisconnectMsg(
fLogIPs));
6120 node.fDisconnect =
true;
6125 if (state.fSyncStarted && peer.m_headers_sync_timeout < std::chrono::microseconds::max()) {
6127 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6128 if (current_time > peer.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6136 node.fDisconnect =
true;
6139 LogInfo(
"Timeout downloading headers from noban peer, not %s\n",
node.DisconnectMsg(
fLogIPs));
6145 state.fSyncStarted =
false;
6147 peer.m_headers_sync_timeout = 0us;
6153 peer.m_headers_sync_timeout = std::chrono::microseconds::max();
6159 ConsiderEviction(
node, peer, GetTime<std::chrono::seconds>());
6164 std::vector<CInv> vGetData;
6166 std::vector<const CBlockIndex*> vToDownload;
6168 auto get_inflight_budget = [&state]() {
6175 FindNextBlocksToDownload(peer, get_inflight_budget(), vToDownload, staller);
6176 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
6177 if (historical_blocks && !IsLimitedPeer(peer)) {
6181 TryDownloadingHistoricalBlocks(
6183 get_inflight_budget(),
6184 vToDownload, from_tip, historical_blocks->second);
6187 uint32_t nFetchFlags = GetFetchFlags(peer);
6189 BlockRequested(
node.GetId(), *pindex);
6193 if (state.vBlocksInFlight.empty() && staller != -1) {
6194 if (
State(staller)->m_stalling_since == 0us) {
6195 State(staller)->m_stalling_since = current_time;
6205 LOCK(m_tx_download_mutex);
6206 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(
node.GetId(), current_time)) {
6215 if (!vGetData.empty())
6218 MaybeSendFeefilter(
node, peer, current_time);
std::shared_ptr< const CTransaction > CTransactionRef
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< Wtxid, CTransactionRef >> &extra_txn)
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::microseconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
enum ReadStatus_t ReadStatus
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
is a home for simple enum and struct type definitions that can be used internally by functions in the...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
Interval between compact filter checkpoints.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
std::atomic_bool fPauseSend
bool historical
Whether this is a historical chainstate downloading old blocks to validate an assumeutxo snapshot...
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
std::chrono::time_point< NodeClock > time_point
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 unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span
Like the std::span constructor, but for (const) unsigned char member types only.
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.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
ServiceFlags
nServices flags
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...
bool IsPruneMode() const
Whether running in -prune mode.
std::string GetDebugMessage() const
constexpr int64_t count_seconds(std::chrono::seconds t)
int64_t GetBlockTime() const
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
std::vector< TxMempoolInfo > infoAll() const
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
uint64_t m_addr_rate_limited
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...
Valid, transaction was already in the mempool.
std::string ToString() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
ReconciliationRegisterResult
We don't have the previous block the checked one is built on.
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
std::vector< uint16_t > indexes
bool IsOutboundOrBlockRelayConn() const
static const int WTXID_RELAY_VERSION
"wtxidrelay" message type for wtxid-based relay starts with this version
bool IsMsgFilteredBlk() const
An in-memory indexed chain of blocks.
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
Manages warning messages within a node.
size_t DynamicMemoryUsage() const
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
void NodeConfirmedReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Mark that the node has confirmed reception of the transaction we sent it by responding with PONG to o...
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
transaction was not validated because package failed
invalid proof of work or time too old
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
std::optional< size_t > Remove(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Forget a transaction.
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
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 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...
Information about chainstate that notifications are sent from.
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
transaction was missing some of its inputs
bool IsMsgCmpctBlk() const
int64_t GetTime()
DEPRECATED, see GetTime.
bool IsFeelerConn() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
TxMempoolInfo info(const T &id) const
All parent headers found, difficulty matches, timestamp >= median previous.
bool MoneyRange(const CAmount &nValue)
CBlockHeader GetBlockHeader() const
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
int Height() const
Return the maximal height in the chain.
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
size_t NumToOpenSub(size_t n)
Decrement the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
static constexpr SerParams V2_NETWORK
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
unsigned long size() const
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid...
void SetCommonVersion(int greatest_common_version)
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set. ...
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
CTransactionRef get(const Txid &hash) const
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
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...
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
the block header may be on a too-little-work chain
void SetTryNewOutboundPeer(bool flag)
void ignore(size_t num_ignore)
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message...
uint64_t GetLocalNonce() const
bool SeenLocal(const CService &addr)
vote for a local address
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
bool IsInitialBlockDownload() const noexcept
Check whether we are doing an initial block download (synchronizing from disk or network) ...
std::vector< TxBroadcastInfo > GetBroadcastInfo() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get stats about all transactions currently being privately broadcast.
consteval auto _(util::TranslatedLiteral str)
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
bool MultipleManualOrFullOutboundConns(Network net) const EXCLUSIVE_LOCKS_REQUIRED(m_nodes_mutex)
State
The various states a (txhash,peer) pair can be in.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
initial value. Tx has not yet been rejected
bool GetTryNewOutboundPeer() const
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
enum Network GetNetwork() const
std::string ToStringAddrPort() const
std::set< Txid > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
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...
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
Stochastic address manager.
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
static const int SENDHEADERS_VERSION
"sendheaders" message type and announcing blocks with headers starts with this version ...
std::optional< CTransactionRef > GetTxForNode(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transaction that was picked for sending to a given node by PickTxForSend().
bool 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.
int GetExtraBlockRelayCount() const
int64_t CAmount
Amount in satoshis (Can be negative)
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
uint256 GetBlockHash() const
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
std::chrono::seconds median_outbound_time_offset
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
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).
arith_uint256 GetBlockProof(const CBlockIndex &block)
Compute how much work a block index entry corresponds to.
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
initial value. Block has not yet been rejected
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends...
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
bool CompareMiningScoreWithTopology(const Wtxid &hasha, const Wtxid &hashb) const
CAmount m_fee_filter_received
TxMempoolInfo info_for_relay(const T &id, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
The util::Unexpected class represents an unexpected value stored in util::Expected.
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.
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
uint64_t m_addr_processed
void ReportHeadersPresync(int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
bool HavePendingTransactions() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if there are transactions that need to be broadcast.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
Blocks after an assumeutxo snapshot have been validated but the snapshot itself has not been validate...
static constexpr auto PRIVATE_BROADCAST_MAX_CONNECTION_LIFETIME
Private broadcast connections must complete within this time.
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
const bool m_preferred
Whether this peer is preferred for transaction download.
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
std::vector< CTransactionRef > txn
this block was cached as being invalid and we didn't store the reason why
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
Validation result for package mempool acceptance.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
void StartExtraBlockRelayPeers()
Double ended buffer combining vector and stream-like interfaces.
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter...
std::string ToString() const
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
A combination of a network address (CNetAddr) and a (TCP) port.
Transport protocol agnostic message container.
int64_t nPowTargetSpacing
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...
std::optional< CTransactionRef > PickTxForSend(const NodeId &will_send_to_nodeid, const CService &will_send_to_address) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Pick the transaction with the fewest send attempts, and confirmations, and oldest send/confirm times...
const uint256 & ToUint256() const LIFETIMEBOUND
static constexpr SerParams V1
bool IsProxy(const CNetAddr &addr)
bool LoadingBlocks() const
bool IsManualConn() const
int GetExtraFullOutboundCount() const
A CService with information about it as peer.
std::string ToString() const
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
std::vector< unsigned char > GetKey() const
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
bool DisconnectNode(std::string_view node)
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t >> block_part=std::nullopt) const
SnapshotCompletionResult MaybeValidateSnapshot(Chainstate &validated_cs, Chainstate &unvalidated_cs) EXCLUSIVE_LOCKS_REQUIRED(Chainstate & CurrentChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Try to validate an assumeutxo snapshot by using a validated historical chainstate targeted at the sna...
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
static const int PROTOCOL_VERSION
network protocol versioning
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks...
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
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 ExpectServicesFromConn() const
bool GetNetworkActive() const
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return randomly selected addresses.
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) ...
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString() const
constexpr const char * BLOCK
The block message transmits a single serialized block.
std::atomic< bool > m_bip152_highbandwidth_to
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
std::vector< uint256 > vHave
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
static constexpr size_t NUM_PRIVATE_BROADCAST_PER_TX
For private broadcast, send a transaction to this many peers.
TRACEPOINT_SEMAPHORE(net, inbound_message)
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
std::vector< CAddress > GetAddresses(CNode &requestor, size_t max_addresses, size_t max_pct)
Return addresses from the per-requestor cache.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
Parameters that influence chain consensus.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::atomic_bool fDisconnect
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
CFeeRate GetMinFee(size_t sizelimit) const
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...
constexpr bool IsNull() const
bool IsMsgWitnessBlk() const
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
Validation result for a transaction evaluated by MemPoolAccept (single or package).
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define Assume(val)
Assume is the identity function.
256-bit unsigned big integer.
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB...
bool exists(const Txid &txid) const
std::chrono::seconds PowTargetSpacing() const
std::chrono::microseconds m_ping_wait
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
bool CheckIncomingNonce(uint64_t nonce)
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
std::vector< std::pair< unsigned int, Txid > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
bool IsBlockOnlyConn() const
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
void NumToOpenAdd(size_t n)
Increment the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids"...
#define LogDebug(category,...)
PackageValidationState m_state
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
ServiceFlags their_services
invalid by consensus rules (excluding any below reasons)
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static time_point now() noexcept
Return current system time or mocked time, if set.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
const arith_uint256 & MinimumChainWork() const
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::vector< CTransactionRef > vtx
The util::Expected class provides a standard way for low-level functions to return either error value...
std::chrono::seconds time_offset
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 * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
the block's data didn't match the data committed to by the PoW
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void RemoveUnbroadcastTx(const Txid &txid, bool unchecked=false)
Removes a transaction from the unbroadcast set.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
bool DidNodeConfirmReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if the node has confirmed reception of the transaction.
constexpr int64_t count_microseconds(std::chrono::microseconds t)
#define LOCKS_EXCLUDED(...)
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
bool IsPrivateBroadcastConn() const
uint32_t GetMappedAS(const CNetAddr &addr) const
The block chain is a tree shaped structure starting with the genesis block at the root...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
std::vector< CTransactionRef > GetStale() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transactions that have not been broadcast recently.
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
class CConnman::PrivateBroadcast m_private_broadcast
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch? Larger windows tolerate larger download speed differences between peer, but increase the potential degree of disordering of blocks on disk (which make reindexing and pruning harder).
bool Add(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a transaction to the storage.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
#define TRACEPOINT(context,...)
bool IsTxAvailable(size_t index) const
A block this one builds on is invalid.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
#define ACQUIRED_BEFORE(...)
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.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
#define LIMITED_STRING(obj, n)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac...
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
General SipHash-2-4 implementation.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
#define AssertLockNotHeld(cs)
bool HasValidProofOfWork(std::span< const CBlockHeader > headers, const Consensus::Params &consensusParams)
Check that the proof of work on each blockheader matches the value in nBits.
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
Store a list of transactions to be broadcast privately.
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
std::vector< NodeId > m_senders
std::atomic< int > nVersion
std::string ConnectionTypeAsString() const
static size_t RecursiveDynamicUsage(const CScript &script)
std::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
this node does not have a mempool so can't validate the transaction
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
block timestamp was > 2 hours in the future (or our clock is bad)
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
std::atomic< bool > m_bip152_highbandwidth_from
constexpr const char * TX
The tx message transmits a single transaction.
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
const uint256 & ToUint256() const LIFETIMEBOUND
bool IsAddrFetchConn() const
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
Information about a peer.
const Consensus::Params & GetConsensus() const
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict...
std::vector< int > vHeightInFlight
Chainstate & ActiveChainstate() const
Alternatives to CurrentChainstate() used by older code to query latest chainstate information without...
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...
void ForEachNode(const NodeFn &func)
Simple class for background tasks that should be run periodically or once "after a while"...
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
full block available in blk*.dat
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.
static constexpr SerParams V1_NETWORK
int GetCommonVersion() const
uint64_t rand64() noexcept
Generate a random 64-bit integer.
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
bool HasPermission(NetPermissionFlags permission) const
std::string ToString() const
bool IsInboundConn() const
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay...
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.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
const HeadersSyncParams & HeadersSync() const
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
bool GetUseAddrmanOutgoing() const
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
bool m_addr_relay_enabled
unsigned int nTx
Number of transactions in this block.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing, bool segwit_active)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
bool IsFullOutboundConn() const
#define Assert(val)
Identity function.
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...
static constexpr TransactionSerParams TX_WITH_WITNESS
static constexpr TransactionSerParams TX_NO_WITNESS
ReachableNets g_reachable_nets
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.