189 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
223 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
226 Mutex m_misbehavior_mutex;
228 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
231 Mutex m_block_inv_mutex;
235 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
239 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
250 std::atomic<int> m_starting_height{-1};
253 std::atomic<uint64_t> m_ping_nonce_sent{0};
255 std::atomic<std::chrono::microseconds> m_ping_start{0us};
257 std::atomic<bool> m_ping_queued{
false};
260 std::atomic<bool> m_wtxid_relay{
false};
272 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
274 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
285 std::set<uint256> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
289 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
292 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
298 std::atomic<CAmount> m_fee_filter_received{0};
304 LOCK(m_tx_relay_mutex);
306 m_tx_relay = std::make_unique<Peer::TxRelay>();
307 return m_tx_relay.get();
312 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
341 std::atomic_bool m_addr_relay_enabled{
false};
345 mutable Mutex m_addr_send_times_mutex;
347 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
349 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
352 std::atomic_bool m_wants_addrv2{
false};
361 std::atomic<uint64_t> m_addr_rate_limited{0};
363 std::atomic<uint64_t> m_addr_processed{0};
369 Mutex m_getdata_requests_mutex;
371 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
377 Mutex m_headers_sync_mutex;
380 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
383 std::atomic<bool> m_sent_sendheaders{
false};
393 std::atomic<std::chrono::seconds> m_time_offset{0s};
397 , m_our_services{our_services}
401 mutable Mutex m_tx_relay_mutex;
404 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
407 using PeerRef = std::shared_ptr<Peer>;
419 uint256 hashLastUnknownBlock{};
425 bool fSyncStarted{
false};
427 std::chrono::microseconds m_stalling_since{0us};
428 std::list<QueuedBlock> vBlocksInFlight;
430 std::chrono::microseconds m_downloading_since{0us};
432 bool fPreferredDownload{
false};
434 bool m_requested_hb_cmpctblocks{
false};
436 bool m_provides_cmpctblocks{
false};
462 struct ChainSyncTimeoutState {
464 std::chrono::seconds m_timeout{0s};
468 bool m_sent_getheaders{
false};
470 bool m_protect{
false};
473 ChainSyncTimeoutState m_chain_sync;
476 int64_t m_last_block_announcement{0};
479 const bool m_is_inbound;
481 CNodeState(
bool is_inbound) : m_is_inbound(is_inbound) {}
510 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
523 void SetBestBlock(
int height,
std::chrono::seconds time)
override 525 m_best_height = height;
526 m_best_block_time = time;
530 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override 531 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
555 void Misbehaving(Peer& peer,
const std::string& message);
566 bool via_compact_block,
const std::string& message =
"")
581 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
589 bool maybe_add_extra_compact_tx)
597 struct PackageToValidate {
599 const std::vector<NodeId> m_senders;
605 m_txns{parent, child},
606 m_senders {parent_sender, child_sender}
610 Assume(m_txns.size() == 2);
611 return strprintf(
"parent %s (wtxid=%s, sender=%d) + child %s (wtxid=%s, sender=%d)",
612 m_txns.front()->GetHash().ToString(),
613 m_txns.front()->GetWitnessHash().ToString(),
615 m_txns.back()->GetHash().ToString(),
616 m_txns.back()->GetWitnessHash().ToString(),
644 bool ProcessOrphanTx(Peer& peer)
654 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
655 std::vector<CBlockHeader>&& headers,
656 bool via_compact_block)
660 bool CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer);
666 void HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
const std::vector<CBlockHeader>& headers)
EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
668 bool CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const;
687 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
688 std::vector<CBlockHeader>& headers)
701 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
703 std::vector<CBlockHeader>& headers)
716 void HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header);
718 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
726 void AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
731 template <
typename... Args>
732 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const 738 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
744 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
786 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
789 std::atomic<int> m_best_height{-1};
791 std::atomic<std::chrono::seconds> m_best_block_time{0s};
799 const Options m_opts;
801 bool RejectIncomingTxs(
const CNode& peer)
const;
809 mutable Mutex m_peer_mutex;
816 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
826 uint32_t GetFetchFlags(
const Peer& peer)
const;
828 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
845 std::atomic<int> m_wtxid_relay_peers{0};
863 bool AlreadyHaveTx(
const GenTxid& gtxid,
bool include_reconsiderable)
900 std::unique_ptr<CRollingBloomFilter> m_lazy_recent_rejects
GUARDED_BY(m_tx_download_mutex){
nullptr};
906 if (!m_lazy_recent_rejects) {
907 m_lazy_recent_rejects = std::make_unique<CRollingBloomFilter>(120
'000, 0.000'001);
910 return *m_lazy_recent_rejects;
933 std::unique_ptr<CRollingBloomFilter> m_lazy_recent_rejects_reconsiderable
GUARDED_BY(m_tx_download_mutex){
nullptr};
939 if (!m_lazy_recent_rejects_reconsiderable) {
940 m_lazy_recent_rejects_reconsiderable = std::make_unique<CRollingBloomFilter>(120
'000, 0.000'001);
943 return *m_lazy_recent_rejects_reconsiderable;
961 std::unique_ptr<CRollingBloomFilter> m_lazy_recent_confirmed_transactions
GUARDED_BY(m_tx_download_mutex){
nullptr};
967 if (!m_lazy_recent_confirmed_transactions) {
968 m_lazy_recent_confirmed_transactions = std::make_unique<CRollingBloomFilter>(48
'000, 0.000'001);
971 return *m_lazy_recent_confirmed_transactions;
980 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
985 Mutex m_most_recent_block_mutex;
986 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
987 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
989 std::unique_ptr<const std::map<uint256, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
993 Mutex m_headers_presync_mutex;
1001 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
1003 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
1005 NodeId m_headers_presync_bestpeer
GUARDED_BY(m_headers_presync_mutex) {-1};
1007 std::atomic_bool m_headers_presync_should_signal{
false};
1077 std::atomic<
std::chrono::seconds> m_last_tip_update{0s};
1083 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
1088 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
1116 std::vector<CTransactionRef> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
1118 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1130 int64_t ApproximateBestBlockDepth() const;
1140 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1158 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1160 const
uint256& stop_hash, uint32_t max_height_diff,
1209 const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const 1211 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1212 if (it == m_node_states.end())
1219 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1227 static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1232 void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1234 assert(peer.m_addr_known);
1235 peer.m_addr_known->insert(addr.
GetKey());
1238 void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1243 assert(peer.m_addr_known);
1244 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1246 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1248 peer.m_addrs_to_send.push_back(addr);
1253 static void AddKnownTx(Peer& peer,
const uint256& hash)
1255 auto tx_relay = peer.GetTxRelay();
1256 if (!tx_relay)
return;
1258 LOCK(tx_relay->m_tx_inventory_mutex);
1259 tx_relay->m_tx_inventory_known_filter.insert(hash);
1263 static bool CanServeBlocks(
const Peer& peer)
1270 static bool IsLimitedPeer(
const Peer& peer)
1277 static bool CanServeWitnesses(
const Peer& peer)
1282 std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1283 std::chrono::seconds average_interval)
1285 if (m_next_inv_to_inbounds.load() < now) {
1289 m_next_inv_to_inbounds = now + m_rng.rand_exp_duration(average_interval);
1291 return m_next_inv_to_inbounds;
1294 bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1296 return mapBlocksInFlight.count(hash);
1299 bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1301 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1302 auto [nodeid, block_it] = range.first->second;
1304 if (!nodestate.m_is_inbound)
return true;
1310 void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1312 auto range = mapBlocksInFlight.equal_range(hash);
1313 if (range.first == range.second) {
1321 while (range.first != range.second) {
1322 auto [node_id, list_it] = range.first->second;
1324 if (from_peer && *from_peer != node_id) {
1331 if (state.vBlocksInFlight.begin() == list_it) {
1333 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1335 state.vBlocksInFlight.erase(list_it);
1337 if (state.vBlocksInFlight.empty()) {
1339 m_peers_downloading_from--;
1341 state.m_stalling_since = 0us;
1343 range.first = mapBlocksInFlight.erase(range.first);
1347 bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1351 CNodeState *state =
State(nodeid);
1352 assert(state !=
nullptr);
1357 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1358 if (range.first->second.first == nodeid) {
1360 *pit = &range.first->second.second;
1367 RemoveBlockRequest(hash, nodeid);
1369 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1371 if (state->vBlocksInFlight.size() == 1) {
1373 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1374 m_peers_downloading_from++;
1376 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1378 *pit = &itInFlight->second.second;
1383 void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1390 if (m_opts.ignore_incoming_txs)
return;
1392 CNodeState* nodestate =
State(nodeid);
1393 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1398 int num_outbound_hb_peers = 0;
1399 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1400 if (*it == nodeid) {
1401 lNodesAnnouncingHeaderAndIDs.erase(it);
1402 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1405 CNodeState *state =
State(*it);
1406 if (state !=
nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
1408 if (nodestate->m_is_inbound) {
1411 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1412 CNodeState *remove_node =
State(lNodesAnnouncingHeaderAndIDs.front());
1413 if (remove_node !=
nullptr && !remove_node->m_is_inbound) {
1416 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1422 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1425 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1428 pnodeStop->m_bip152_highbandwidth_to =
false;
1431 lNodesAnnouncingHeaderAndIDs.pop_front();
1436 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1441 bool PeerManagerImpl::TipMayBeStale()
1445 if (m_last_tip_update.load() == 0s) {
1446 m_last_tip_update = GetTime<std::chrono::seconds>();
1448 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1451 int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const 1456 bool PeerManagerImpl::CanDirectFetch()
1463 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1465 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1470 void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1471 CNodeState *state =
State(nodeid);
1472 assert(state !=
nullptr);
1474 if (!state->hashLastUnknownBlock.IsNull()) {
1477 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1478 state->pindexBestKnownBlock = pindex;
1480 state->hashLastUnknownBlock.SetNull();
1485 void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1486 CNodeState *state =
State(nodeid);
1487 assert(state !=
nullptr);
1489 ProcessBlockAvailability(nodeid);
1494 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1495 state->pindexBestKnownBlock = pindex;
1499 state->hashLastUnknownBlock = hash;
1504 void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1509 vBlocks.reserve(vBlocks.size() +
count);
1510 CNodeState *state =
State(peer.m_id);
1511 assert(state !=
nullptr);
1514 ProcessBlockAvailability(peer.m_id);
1516 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1524 const CBlockIndex* snap_base{m_chainman.GetSnapshotBaseBlock()};
1525 if (snap_base && state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1526 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1533 if (state->pindexLastCommonBlock ==
nullptr ||
1534 (snap_base && state->pindexLastCommonBlock->nHeight < snap_base->nHeight)) {
1535 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1540 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1541 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1544 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1550 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1553 void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1558 if (vBlocks.size() >=
count) {
1562 vBlocks.reserve(
count);
1565 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1582 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)
1584 std::vector<const CBlockIndex*> vToFetch;
1585 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1586 bool is_limited_peer = IsLimitedPeer(peer);
1588 while (pindexWalk->
nHeight < nMaxHeight) {
1592 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1593 vToFetch.resize(nToFetch);
1594 pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->
nHeight + nToFetch);
1595 vToFetch[nToFetch - 1] = pindexWalk;
1596 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1597 vToFetch[i - 1] = vToFetch[i]->
pprev;
1617 state->pindexLastCommonBlock = pindex;
1624 if (waitingfor == -1) {
1626 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1632 if (pindex->
nHeight > nWindowEnd) {
1634 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1636 if (nodeStaller) *nodeStaller = waitingfor;
1646 vBlocks.push_back(pindex);
1647 if (vBlocks.size() ==
count) {
1656 void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1658 uint64_t my_services{peer.m_our_services};
1659 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1661 const int nNodeStartingHeight{m_best_height};
1668 const bool tx_relay{!RejectIncomingTxs(pnode)};
1675 LogPrint(
BCLog::NET,
"send version message: version %d, blocks=%d, them=%s, txrelay=%d, peer=%d\n",
PROTOCOL_VERSION, nNodeStartingHeight, addr_you.
ToStringAddrPort(), tx_relay, nodeid);
1681 void PeerManagerImpl::AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
1690 const CNodeState* state =
State(nodeid);
1700 const bool preferred = state->fPreferredDownload;
1706 m_txrequest.ReceivedInv(nodeid, gtxid, preferred, current_time + delay);
1709 void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1713 if (state) state->m_last_block_announcement = time_in_seconds;
1721 m_node_states.emplace_hint(m_node_states.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(
node.IsInboundConn()));
1724 LOCK(m_tx_download_mutex);
1725 assert(m_txrequest.Count(nodeid) == 0);
1732 PeerRef peer = std::make_shared<Peer>(nodeid, our_services);
1735 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1739 void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1743 for (
const auto& txid : unbroadcast_txids) {
1746 if (tx !=
nullptr) {
1756 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1759 void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1770 PeerRef peer = RemovePeer(nodeid);
1772 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1773 assert(m_wtxid_relay_peers >= 0);
1775 CNodeState *state =
State(nodeid);
1776 assert(state !=
nullptr);
1778 if (state->fSyncStarted)
1781 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1782 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1783 while (range.first != range.second) {
1784 auto [node_id, list_it] = range.first->second;
1785 if (node_id != nodeid) {
1788 range.first = mapBlocksInFlight.erase(range.first);
1793 LOCK(m_tx_download_mutex);
1794 m_orphanage.EraseForPeer(nodeid);
1795 m_txrequest.DisconnectedPeer(nodeid);
1797 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1798 m_num_preferred_download_peers -= state->fPreferredDownload;
1799 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1800 assert(m_peers_downloading_from >= 0);
1801 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1802 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1804 m_node_states.erase(nodeid);
1806 if (m_node_states.empty()) {
1808 assert(mapBlocksInFlight.empty());
1809 assert(m_num_preferred_download_peers == 0);
1810 assert(m_peers_downloading_from == 0);
1811 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1812 assert(m_wtxid_relay_peers == 0);
1813 LOCK(m_tx_download_mutex);
1814 assert(m_txrequest.Size() == 0);
1815 assert(m_orphanage.Size() == 0);
1818 if (
node.fSuccessfullyConnected &&
1819 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1826 LOCK(m_headers_presync_mutex);
1827 m_headers_presync_stats.erase(nodeid);
1832 bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const 1849 PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const 1852 auto it = m_peer_map.find(
id);
1853 return it != m_peer_map.end() ? it->second :
nullptr;
1856 PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1860 auto it = m_peer_map.find(
id);
1861 if (it != m_peer_map.end()) {
1862 ret = std::move(it->second);
1863 m_peer_map.erase(it);
1872 const CNodeState* state =
State(nodeid);
1873 if (state ==
nullptr)
1875 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1876 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1877 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1883 PeerRef peer = GetPeerRef(nodeid);
1884 if (peer ==
nullptr)
return false;
1893 auto ping_wait{0us};
1894 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1895 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1898 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1911 LOCK(peer->m_headers_sync_mutex);
1912 if (peer->m_headers_sync) {
1925 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1929 void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1931 if (m_opts.max_extra_txs <= 0)
1933 if (!vExtraTxnForCompact.size())
1934 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1935 vExtraTxnForCompact[vExtraTxnForCompactIt] = tx;
1936 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1939 void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1941 LOCK(peer.m_misbehavior_mutex);
1943 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1944 peer.m_should_discourage =
true;
1949 bool via_compact_block,
const std::string& message)
1951 PeerRef peer{GetPeerRef(nodeid)};
1962 if (!via_compact_block) {
1963 if (peer) Misbehaving(*peer, message);
1970 CNodeState *node_state =
State(nodeid);
1971 if (node_state ==
nullptr) {
1977 if (!via_compact_block && !node_state->m_is_inbound) {
1978 if (peer) Misbehaving(*peer, message);
1986 if (peer) Misbehaving(*peer, message);
1990 if (peer) Misbehaving(*peer, message);
1996 if (message !=
"") {
2003 PeerRef peer{GetPeerRef(nodeid)};
2009 if (peer) Misbehaving(*peer,
"");
2028 bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
2037 std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
2042 PeerRef peer = GetPeerRef(peer_id);
2043 if (peer ==
nullptr)
return "Peer does not exist";
2046 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
2051 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
2054 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
2066 if (!success)
return "Peer not fully connected";
2070 return std::nullopt;
2077 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
2083 : m_rng{opts.deterministic_rng},
2085 m_chainparams(chainman.GetParams()),
2089 m_chainman(chainman),
2091 m_warnings{warnings},
2096 if (opts.reconcile_txs) {
2101 void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2112 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2115 void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2123 LOCK(m_tx_download_mutex);
2127 RecentRejectsFilter().reset();
2128 RecentRejectsReconsiderableFilter().reset();
2138 void PeerManagerImpl::BlockConnected(
2140 const std::shared_ptr<const CBlock>& pblock,
2145 m_last_tip_update = GetTime<std::chrono::seconds>();
2148 auto stalling_timeout = m_block_stalling_timeout.load();
2152 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2162 LOCK(m_tx_download_mutex);
2163 m_orphanage.EraseForBlock(*pblock);
2165 for (
const auto& ptx : pblock->vtx) {
2166 RecentConfirmedTransactionsFilter().insert(ptx->GetHash().ToUint256());
2167 if (ptx->HasWitness()) {
2168 RecentConfirmedTransactionsFilter().insert(ptx->GetWitnessHash().ToUint256());
2170 m_txrequest.ForgetTxHash(ptx->GetHash());
2171 m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
2175 void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2185 LOCK(m_tx_download_mutex);
2186 RecentConfirmedTransactionsFilter().reset();
2193 void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2199 if (pindex->
nHeight <= m_highest_fast_announce)
2201 m_highest_fast_announce = pindex->
nHeight;
2205 uint256 hashBlock(pblock->GetHash());
2206 const std::shared_future<CSerializedNetMsg> lazy_ser{
2210 auto most_recent_block_txs = std::make_unique<std::map<uint256, CTransactionRef>>();
2211 for (
const auto& tx : pblock->vtx) {
2212 most_recent_block_txs->emplace(tx->GetHash(), tx);
2213 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2216 LOCK(m_most_recent_block_mutex);
2217 m_most_recent_block_hash = hashBlock;
2218 m_most_recent_block = pblock;
2219 m_most_recent_compact_block = pcmpctblock;
2220 m_most_recent_block_txs = std::move(most_recent_block_txs);
2228 ProcessBlockAvailability(pnode->
GetId());
2232 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2234 LogPrint(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2235 hashBlock.ToString(), pnode->
GetId());
2238 PushMessage(*pnode, ser_cmpctblock.Copy());
2239 state.pindexBestHeaderSent = pindex;
2248 void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2250 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2253 if (fInitialDownload)
return;
2256 std::vector<uint256> vHashes;
2258 while (pindexToAnnounce != pindexFork) {
2260 pindexToAnnounce = pindexToAnnounce->
pprev;
2270 for (
auto& it : m_peer_map) {
2271 Peer& peer = *it.second;
2272 LOCK(peer.m_block_inv_mutex);
2273 for (
const uint256& hash : vHashes | std::views::reverse) {
2274 peer.m_blocks_for_headers_relay.push_back(hash);
2291 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2296 it != mapBlockSource.end() &&
2297 State(it->second.first)) {
2298 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2308 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2309 if (it != mapBlockSource.end()) {
2310 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2313 if (it != mapBlockSource.end())
2314 mapBlockSource.erase(it);
2323 bool PeerManagerImpl::AlreadyHaveTx(
const GenTxid& gtxid,
bool include_reconsiderable)
2347 if (include_reconsiderable && RecentRejectsReconsiderableFilter().contains(hash))
return true;
2349 if (RecentConfirmedTransactionsFilter().contains(hash))
return true;
2351 return RecentRejectsFilter().contains(hash) || m_mempool.
exists(gtxid);
2354 bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2359 void PeerManagerImpl::SendPings()
2362 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2365 void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2368 for(
auto& it : m_peer_map) {
2369 Peer& peer = *it.second;
2370 auto tx_relay = peer.GetTxRelay();
2371 if (!tx_relay)
continue;
2373 LOCK(tx_relay->m_tx_inventory_mutex);
2379 if (tx_relay->m_next_inv_send_time == 0s)
continue;
2381 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2382 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2383 tx_relay->m_tx_inventory_to_send.insert(hash);
2388 void PeerManagerImpl::RelayAddress(
NodeId originator,
2404 const auto current_time{GetTime<std::chrono::seconds>()};
2412 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2414 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2415 assert(nRelayNodes <= best.size());
2419 for (
auto& [
id, peer] : m_peer_map) {
2420 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2422 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2423 if (hashKey > best[i].first) {
2424 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2425 best[i] = std::make_pair(hashKey, peer.get());
2432 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2433 PushAddress(*best[i].second, addr);
2437 void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2439 std::shared_ptr<const CBlock> a_recent_block;
2440 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2442 LOCK(m_most_recent_block_mutex);
2443 a_recent_block = m_most_recent_block;
2444 a_recent_compact_block = m_most_recent_compact_block;
2447 bool need_activate_chain =
false;
2459 need_activate_chain =
true;
2463 if (need_activate_chain) {
2465 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2472 bool can_direct_fetch{
false};
2480 if (!BlockRequestAllowed(pindex)) {
2481 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2498 LogPrint(
BCLog::NET,
"Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.
GetId());
2508 can_direct_fetch = CanDirectFetch();
2512 std::shared_ptr<const CBlock> pblock;
2513 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2514 pblock = a_recent_block;
2518 std::vector<uint8_t> block_data;
2523 LogError(
"Cannot load block from disk, disconnect peer=%d\n", pfrom.
GetId());
2532 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2537 LogError(
"Cannot load block from disk, disconnect peer=%d\n", pfrom.
GetId());
2542 pblock = pblockRead;
2550 bool sendMerkleBlock =
false;
2552 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2553 LOCK(tx_relay->m_bloom_filter_mutex);
2554 if (tx_relay->m_bloom_filter) {
2555 sendMerkleBlock =
true;
2556 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2559 if (sendMerkleBlock) {
2567 typedef std::pair<unsigned int, uint256> PairType;
2579 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2592 LOCK(peer.m_block_inv_mutex);
2594 if (inv.
hash == peer.m_continuation_block) {
2598 std::vector<CInv> vInv;
2599 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2601 peer.m_continuation_block.SetNull();
2609 auto txinfo = m_mempool.
info_for_relay(gtxid, tx_relay.m_last_inv_sequence);
2611 return std::move(txinfo.tx);
2616 LOCK(m_most_recent_block_mutex);
2617 if (m_most_recent_block_txs !=
nullptr) {
2618 auto it = m_most_recent_block_txs->find(gtxid.
GetHash());
2619 if (it != m_most_recent_block_txs->end())
return it->second;
2626 void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2630 auto tx_relay = peer.GetTxRelay();
2632 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2633 std::vector<CInv> vNotFound;
2638 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2639 if (interruptMsgProc)
return;
2644 const CInv &inv = *it++;
2646 if (tx_relay ==
nullptr) {
2656 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2659 vNotFound.push_back(inv);
2665 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2666 const CInv &inv = *it++;
2668 ProcessGetBlockData(pfrom, peer, inv);
2674 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2676 if (!vNotFound.empty()) {
2695 uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const 2697 uint32_t nFetchFlags = 0;
2698 if (CanServeWitnesses(peer)) {
2707 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2709 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2718 bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2722 Misbehaving(peer,
"header with invalid proof of work");
2727 if (!CheckHeadersAreContinuous(headers)) {
2728 Misbehaving(peer,
"non-continuous headers sequence");
2753 void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2754 const std::vector<CBlockHeader>& headers)
2758 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2759 LogPrint(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2761 headers[0].hashPrevBlock.ToString(),
2762 best_header->nHeight,
2772 bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const 2776 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2779 hashLastBlock = header.GetHash();
2784 bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2786 if (peer.m_headers_sync) {
2787 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() ==
MAX_HEADERS_RESULTS);
2789 if (result.success) peer.m_last_getheaders_timestamp = {};
2790 if (result.request_more) {
2791 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2793 Assume(!locator.vHave.empty());
2796 if (!locator.vHave.empty()) {
2799 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2802 locator.vHave.front().ToString(), pfrom.
GetId());
2807 peer.m_headers_sync.reset(
nullptr);
2812 LOCK(m_headers_presync_mutex);
2813 m_headers_presync_stats.erase(pfrom.
GetId());
2816 HeadersPresyncStats stats;
2817 stats.first = peer.m_headers_sync->GetPresyncWork();
2819 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2820 peer.m_headers_sync->GetPresyncTime()};
2824 LOCK(m_headers_presync_mutex);
2825 m_headers_presync_stats[pfrom.
GetId()] = stats;
2826 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2827 bool best_updated =
false;
2828 if (best_it == m_headers_presync_stats.end()) {
2832 const HeadersPresyncStats* stat_best{
nullptr};
2833 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2834 if (!stat_best || stat > *stat_best) {
2839 m_headers_presync_bestpeer = peer_best;
2840 best_updated = (peer_best == pfrom.
GetId());
2841 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2843 m_headers_presync_bestpeer = pfrom.
GetId();
2844 best_updated =
true;
2846 if (best_updated && stats.second.has_value()) {
2848 m_headers_presync_should_signal =
true;
2852 if (result.success) {
2855 headers.swap(result.pow_validated_headers);
2858 return result.success;
2866 bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2873 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2877 if (total_work < minimum_chain_work) {
2891 LOCK(peer.m_headers_sync_mutex);
2893 chain_start_header, minimum_chain_work));
2898 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2912 bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2914 if (header ==
nullptr) {
2916 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2924 bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2932 peer.m_last_getheaders_timestamp = current_time;
2943 void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2946 CNodeState *nodestate =
State(pfrom.
GetId());
2949 std::vector<const CBlockIndex*> vToFetch;
2957 vToFetch.push_back(pindexWalk);
2959 pindexWalk = pindexWalk->
pprev;
2970 std::vector<CInv> vGetData;
2972 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2977 uint32_t nFetchFlags = GetFetchFlags(peer);
2979 BlockRequested(pfrom.
GetId(), *pindex);
2983 if (vGetData.size() > 1) {
2988 if (vGetData.size() > 0) {
2989 if (!m_opts.ignore_incoming_txs &&
2990 nodestate->m_provides_cmpctblocks &&
2991 vGetData.size() == 1 &&
2992 mapBlocksInFlight.size() == 1 &&
3008 void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
3009 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
3012 CNodeState *nodestate =
State(pfrom.
GetId());
3021 nodestate->m_last_block_announcement =
GetTime();
3029 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
3039 LogPrintf(
"Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.
GetId());
3051 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) {
3053 nodestate->m_chain_sync.m_protect =
true;
3054 ++m_outbound_peers_with_protect_from_disconnect;
3059 void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
3060 std::vector<CBlockHeader>&& headers,
3061 bool via_compact_block)
3063 size_t nCount = headers.size();
3070 LOCK(peer.m_headers_sync_mutex);
3071 if (peer.m_headers_sync) {
3072 peer.m_headers_sync.reset(
nullptr);
3073 LOCK(m_headers_presync_mutex);
3074 m_headers_presync_stats.erase(pfrom.
GetId());
3078 peer.m_last_getheaders_timestamp = {};
3086 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
3101 bool already_validated_work =
false;
3104 bool have_headers_sync =
false;
3106 LOCK(peer.m_headers_sync_mutex);
3108 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
3120 if (headers.empty()) {
3124 have_headers_sync = !!peer.m_headers_sync;
3129 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3131 if (!headers_connect_blockindex) {
3135 HandleUnconnectingHeaders(pfrom, peer, headers);
3142 peer.m_last_getheaders_timestamp = {};
3152 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
3153 already_validated_work =
true;
3161 already_validated_work =
true;
3167 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3168 chain_start_header, headers)) {
3180 bool received_new_header{last_received_header ==
nullptr};
3186 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3195 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3197 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
3201 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount ==
MAX_HEADERS_RESULTS);
3204 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3210 bool maybe_add_extra_compact_tx)
3217 ptx->GetHash().ToString(),
3218 ptx->GetWitnessHash().ToString(),
3242 RecentRejectsReconsiderableFilter().insert(ptx->GetWitnessHash().ToUint256());
3244 RecentRejectsFilter().insert(ptx->GetWitnessHash().ToUint256());
3246 m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
3258 RecentRejectsFilter().insert(ptx->GetHash().ToUint256());
3259 m_txrequest.ForgetTxHash(ptx->GetHash());
3262 AddToCompactExtraTransactions(ptx);
3266 MaybePunishNodeForTx(nodeid, state);
3271 LogDebug(
BCLog::TXPACKAGES,
" removed orphan tx %s (wtxid=%s)\n", ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
3275 void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3283 m_txrequest.ForgetTxHash(tx->GetHash());
3284 m_txrequest.ForgetTxHash(tx->GetWitnessHash());
3286 m_orphanage.AddChildrenToWorkSet(*tx);
3288 m_orphanage.EraseTx(tx->GetWitnessHash());
3292 tx->GetHash().ToString(),
3293 tx->GetWitnessHash().ToString(),
3296 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3299 AddToCompactExtraTransactions(removedTx);
3303 void PeerManagerImpl::ProcessPackageResult(
const PackageToValidate& package_to_validate,
const PackageMempoolAcceptResult& package_result)
3309 const auto&
package = package_to_validate.m_txns;
3310 const auto& senders = package_to_validate.m_senders;
3313 RecentRejectsReconsiderableFilter().insert(
GetPackageHash(package));
3316 if (!
Assume(package.size() == 2))
return;
3320 auto package_iter = package.rbegin();
3321 auto senders_iter = senders.rbegin();
3322 while (package_iter != package.rend()) {
3323 const auto& tx = *package_iter;
3324 const NodeId nodeid = *senders_iter;
3325 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3329 const auto& tx_result = it_result->second;
3330 switch (tx_result.m_result_type) {
3333 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3343 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3359 std::optional<PeerManagerImpl::PackageToValidate> PeerManagerImpl::Find1P1CPackage(
const CTransactionRef& ptx,
NodeId nodeid)
3365 const auto& parent_wtxid{ptx->GetWitnessHash()};
3367 Assume(RecentRejectsReconsiderableFilter().contains(parent_wtxid.ToUint256()));
3372 const auto cpfp_candidates_same_peer{m_orphanage.GetChildrenFromSamePeer(ptx, nodeid)};
3377 for (
const auto& child : cpfp_candidates_same_peer) {
3378 Package maybe_cpfp_package{ptx, child};
3379 if (!RecentRejectsReconsiderableFilter().contains(
GetPackageHash(maybe_cpfp_package))) {
3380 return PeerManagerImpl::PackageToValidate{ptx, child, nodeid, nodeid};
3391 const auto cpfp_candidates_different_peer{m_orphanage.GetChildrenFromDifferentPeer(ptx, nodeid)};
3397 std::vector<size_t> tx_indices(cpfp_candidates_different_peer.size());
3398 std::iota(tx_indices.begin(), tx_indices.end(), 0);
3399 std::shuffle(tx_indices.begin(), tx_indices.end(), m_rng);
3401 for (
const auto index : tx_indices) {
3404 const auto [child_tx, child_sender] = cpfp_candidates_different_peer.at(index);
3405 Package maybe_cpfp_package{ptx, child_tx};
3406 if (!RecentRejectsReconsiderableFilter().contains(
GetPackageHash(maybe_cpfp_package))) {
3407 return PeerManagerImpl::PackageToValidate{ptx, child_tx, nodeid, child_sender};
3410 return std::nullopt;
3413 bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3420 while (
CTransactionRef porphanTx = m_orphanage.GetTxToReconsider(peer.m_id)) {
3423 const Txid& orphanHash = porphanTx->GetHash();
3424 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3441 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3450 bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3452 const uint256& stop_hash, uint32_t max_height_diff,
3456 const bool supported_filter_type =
3459 if (!supported_filter_type) {
3461 node.GetId(),
static_cast<uint8_t
>(filter_type));
3462 node.fDisconnect =
true;
3471 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3474 node.fDisconnect =
true;
3479 uint32_t stop_height = stop_index->
nHeight;
3480 if (start_height > stop_height) {
3482 "start height %d and stop height %d\n",
3483 node.GetId(), start_height, stop_height);
3484 node.fDisconnect =
true;
3487 if (stop_height - start_height >= max_height_diff) {
3489 node.GetId(), stop_height - start_height + 1, max_height_diff);
3490 node.fDisconnect =
true;
3495 if (!filter_index) {
3505 uint8_t filter_type_ser;
3506 uint32_t start_height;
3509 vRecv >> filter_type_ser >> start_height >> stop_hash;
3515 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3520 std::vector<BlockFilter> filters;
3522 LogPrint(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3527 for (
const auto& filter : filters) {
3534 uint8_t filter_type_ser;
3535 uint32_t start_height;
3538 vRecv >> filter_type_ser >> start_height >> stop_hash;
3544 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3550 if (start_height > 0) {
3552 stop_index->
GetAncestor(static_cast<int>(start_height - 1));
3554 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3560 std::vector<uint256> filter_hashes;
3562 LogPrint(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3576 uint8_t filter_type_ser;
3579 vRecv >> filter_type_ser >> stop_hash;
3585 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3586 std::numeric_limits<uint32_t>::max(),
3587 stop_index, filter_index)) {
3595 for (
int i = headers.size() - 1; i >= 0; i--) {
3600 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3612 void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked)
3614 bool new_block{
false};
3615 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3617 node.m_last_block_time = GetTime<std::chrono::seconds>();
3622 RemoveBlockRequest(block->GetHash(), std::nullopt);
3625 mapBlockSource.erase(block->GetHash());
3629 void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3631 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3632 bool fBlockRead{
false};
3636 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3637 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3638 bool requested_block_from_this_peer{
false};
3641 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3643 while (range_flight.first != range_flight.second) {
3644 auto [node_id, block_it] = range_flight.first->second;
3645 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3646 requested_block_from_this_peer =
true;
3649 range_flight.first++;
3652 if (!requested_block_from_this_peer) {
3661 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3664 if (first_in_flight) {
3666 std::vector<CInv> invs;
3671 LogPrint(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3700 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3710 ProcessBlock(pfrom, pblock,
true,
true);
3715 void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3716 const std::chrono::microseconds time_received,
3717 const std::atomic<bool>& interruptMsgProc)
3723 PeerRef peer = GetPeerRef(pfrom.
GetId());
3724 if (peer ==
nullptr)
return;
3734 uint64_t nNonce = 1;
3737 std::string cleanSubVer;
3738 int starting_height = -1;
3741 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3756 LogPrint(
BCLog::NET,
"peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom.
GetId(), nServices, GetDesirableServiceFlags(nServices));
3768 if (!vRecv.
empty()) {
3776 if (!vRecv.
empty()) {
3777 std::string strSubVer;
3781 if (!vRecv.
empty()) {
3782 vRecv >> starting_height;
3802 PushNodeVersion(pfrom, *peer);
3815 if (greatest_common_version >= 70016) {
3824 peer->m_their_services = nServices;
3828 pfrom.cleanSubVer = cleanSubVer;
3830 peer->m_starting_height = starting_height;
3840 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3841 auto*
const tx_relay = peer->SetTxRelay();
3843 LOCK(tx_relay->m_bloom_filter_mutex);
3844 tx_relay->m_relay_txs = fRelay;
3856 const auto* tx_relay = peer->GetTxRelay();
3857 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3859 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3872 m_num_preferred_download_peers += state->fPreferredDownload;
3878 bool send_getaddr{
false};
3880 send_getaddr = SetupAddressRelay(pfrom, *peer);
3890 peer->m_getaddr_sent =
true;
3914 std::string remoteAddr;
3919 LogPrint(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3922 remoteAddr, (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3924 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3928 m_outbound_time_offsets.Add(peer->m_time_offset);
3929 m_outbound_time_offsets.WarnIfOutOfSync();
3933 if (greatest_common_version <= 70012) {
3934 const auto finalAlert{
ParseHex(
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50")};
3935 MakeAndPushMessage(pfrom,
"alert",
Span{finalAlert});
3962 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3965 pfrom.
nVersion.load(), peer->m_starting_height,
3967 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3979 if (m_txreconciliation) {
3980 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3984 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3988 if (
auto tx_relay = peer->GetTxRelay()) {
3997 tx_relay->m_tx_inventory_mutex,
3998 return tx_relay->m_tx_inventory_to_send.empty() &&
3999 tx_relay->m_next_inv_send_time == 0s));
4007 peer->m_prefers_headers =
true;
4012 bool sendcmpct_hb{
false};
4013 uint64_t sendcmpct_version{0};
4014 vRecv >> sendcmpct_hb >> sendcmpct_version;
4020 CNodeState* nodestate =
State(pfrom.
GetId());
4021 nodestate->m_provides_cmpctblocks =
true;
4022 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
4039 if (!peer->m_wtxid_relay) {
4040 peer->m_wtxid_relay =
true;
4041 m_wtxid_relay_peers++;
4060 peer->m_wants_addrv2 =
true;
4068 if (!m_txreconciliation) {
4080 if (RejectIncomingTxs(pfrom)) {
4089 const auto* tx_relay = peer->GetTxRelay();
4090 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
4096 uint32_t peer_txreconcl_version;
4097 uint64_t remote_salt;
4098 vRecv >> peer_txreconcl_version >> remote_salt;
4101 peer_txreconcl_version, remote_salt);
4126 const auto ser_params{
4134 std::vector<CAddress> vAddr;
4136 vRecv >> ser_params(vAddr);
4138 if (!SetupAddressRelay(pfrom, *peer)) {
4145 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
4150 std::vector<CAddress> vAddrOk;
4151 const auto current_a_time{Now<NodeSeconds>()};
4154 const auto current_time{GetTime<std::chrono::microseconds>()};
4157 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
4161 peer->m_addr_token_timestamp = current_time;
4164 uint64_t num_proc = 0;
4165 uint64_t num_rate_limit = 0;
4166 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
4169 if (interruptMsgProc)
4173 if (peer->m_addr_token_bucket < 1.0) {
4179 peer->m_addr_token_bucket -= 1.0;
4188 addr.
nTime = current_a_time - 5 * 24h;
4190 AddAddressKnown(*peer, addr);
4197 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
4199 RelayAddress(pfrom.
GetId(), addr, reachable);
4203 vAddrOk.push_back(addr);
4206 peer->m_addr_processed += num_proc;
4207 peer->m_addr_rate_limited += num_rate_limit;
4208 LogPrint(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
4209 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
4211 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
4212 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
4223 std::vector<CInv> vInv;
4227 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
4231 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4235 const auto current_time{GetTime<std::chrono::microseconds>()};
4238 for (
CInv& inv : vInv) {
4239 if (interruptMsgProc)
return;
4244 if (peer->m_wtxid_relay) {
4251 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4254 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4262 best_block = &inv.
hash;
4265 if (reject_tx_invs) {
4271 const bool fAlreadyHave = AlreadyHaveTx(gtxid,
true);
4274 AddKnownTx(*peer, inv.
hash);
4276 AddTxAnnouncement(pfrom, gtxid, current_time);
4283 if (best_block !=
nullptr) {
4295 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4296 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
4298 m_chainman.m_best_header->nHeight, best_block->ToString(),
4301 if (!state.fSyncStarted) {
4302 peer->m_inv_triggered_getheaders_before_sync =
true;
4306 m_last_block_inv_triggering_headers_sync = *best_block;
4315 std::vector<CInv> vInv;
4319 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
4325 if (vInv.size() > 0) {
4330 LOCK(peer->m_getdata_requests_mutex);
4331 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
4332 ProcessGetData(pfrom, *peer, interruptMsgProc);
4341 vRecv >> locator >> hashStop;
4357 std::shared_ptr<const CBlock> a_recent_block;
4359 LOCK(m_most_recent_block_mutex);
4360 a_recent_block = m_most_recent_block;
4363 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4377 LogPrint(
BCLog::NET,
"getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->
nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), nLimit, pfrom.
GetId());
4393 if (--nLimit <= 0) {
4397 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4408 std::shared_ptr<const CBlock> recent_block;
4410 LOCK(m_most_recent_block_mutex);
4411 if (m_most_recent_block_hash == req.blockhash)
4412 recent_block = m_most_recent_block;
4416 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4435 if (!block_pos.IsNull()) {
4442 SendBlockTransactions(pfrom, *peer, block, req);
4455 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4463 vRecv >> locator >> hashStop;
4485 if (m_chainman.
ActiveTip() ==
nullptr ||
4487 LogPrint(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4494 CNodeState *nodestate =
State(pfrom.
GetId());
4504 if (!BlockRequestAllowed(pindex)) {
4505 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4518 std::vector<CBlock> vHeaders;
4520 LogPrint(
BCLog::NET,
"getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), pfrom.
GetId());
4523 vHeaders.emplace_back(pindex->GetBlockHeader());
4524 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4539 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4545 if (RejectIncomingTxs(pfrom)) {
4560 const uint256& txid = ptx->GetHash();
4561 const uint256& wtxid = ptx->GetWitnessHash();
4563 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4564 AddKnownTx(*peer, hash);
4568 m_txrequest.ReceivedResponse(pfrom.
GetId(), txid);
4569 if (tx.
HasWitness()) m_txrequest.ReceivedResponse(pfrom.
GetId(), wtxid);
4589 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4592 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4598 if (RecentRejectsReconsiderableFilter().contains(wtxid)) {
4604 if (
auto package_to_validate{Find1P1CPackage(ptx, pfrom.
GetId())}) {
4607 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4608 ProcessPackageResult(package_to_validate.value(), package_result);
4638 bool fRejectedParents =
false;
4642 std::vector<uint256> unique_parents;
4643 unique_parents.reserve(tx.
vin.size());
4648 std::sort(unique_parents.begin(), unique_parents.end());
4649 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
4654 std::optional<uint256> rejected_parent_reconsiderable;
4655 for (
const uint256& parent_txid : unique_parents) {
4656 if (RecentRejectsFilter().contains(parent_txid)) {
4657 fRejectedParents =
true;
4659 }
else if (RecentRejectsReconsiderableFilter().contains(parent_txid) && !m_mempool.
exists(
GenTxid::Txid(parent_txid))) {
4662 if (rejected_parent_reconsiderable.has_value()) {
4663 fRejectedParents =
true;
4666 rejected_parent_reconsiderable = parent_txid;
4669 if (!fRejectedParents) {
4670 const auto current_time{GetTime<std::chrono::microseconds>()};
4672 for (
const uint256& parent_txid : unique_parents) {
4679 AddKnownTx(*peer, parent_txid);
4682 if (!AlreadyHaveTx(gtxid,
false)) AddTxAnnouncement(pfrom, gtxid, current_time);
4685 if (m_orphanage.AddTx(ptx, pfrom.
GetId())) {
4686 AddToCompactExtraTransactions(ptx);
4690 m_txrequest.ForgetTxHash(tx.
GetHash());
4694 m_orphanage.LimitOrphans(m_opts.max_orphan_txs, m_rng);
4707 m_txrequest.ForgetTxHash(tx.
GetHash());
4712 ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true);
4719 if (
auto package_to_validate{Find1P1CPackage(ptx, pfrom.
GetId())}) {
4722 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4723 ProcessPackageResult(package_to_validate.value(), package_result);
4739 vRecv >> cmpctblock;
4741 bool received_new_header =
false;
4751 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4761 received_new_header =
true;
4769 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4774 if (received_new_header) {
4775 LogInfo(
"Saw new cmpctblock header hash=%s peer=%d\n",
4776 blockhash.ToString(), pfrom.
GetId());
4779 bool fProcessBLOCKTXN =
false;
4783 bool fRevertToHeaderProcessing =
false;
4787 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4788 bool fBlockReconstructed =
false;
4796 CNodeState *nodestate =
State(pfrom.
GetId());
4801 nodestate->m_last_block_announcement =
GetTime();
4807 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4808 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4809 bool requested_block_from_this_peer{
false};
4812 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4814 while (range_flight.first != range_flight.second) {
4815 if (range_flight.first->second.first == pfrom.
GetId()) {
4816 requested_block_from_this_peer =
true;
4819 range_flight.first++;
4824 if (requested_block_from_this_peer) {
4827 std::vector<CInv> vInv(1);
4828 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4835 if (!already_in_flight && !CanDirectFetch()) {
4843 requested_block_from_this_peer) {
4844 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4845 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4846 if (!(*queuedBlockIt)->partialBlock)
4859 Misbehaving(*peer,
"invalid compact block");
4862 if (first_in_flight) {
4864 std::vector<CInv> vInv(1);
4865 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4875 for (
size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {
4880 fProcessBLOCKTXN =
true;
4881 }
else if (first_in_flight) {
4888 IsBlockRequestedFromOutbound(blockhash) ||
4907 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4912 std::vector<CTransactionRef> dummy;
4913 status = tempBlock.FillBlock(*pblock, dummy);
4915 fBlockReconstructed =
true;
4919 if (requested_block_from_this_peer) {
4922 std::vector<CInv> vInv(1);
4923 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4928 fRevertToHeaderProcessing =
true;
4933 if (fProcessBLOCKTXN) {
4936 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4939 if (fRevertToHeaderProcessing) {
4945 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.header},
true);
4948 if (fBlockReconstructed) {
4953 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4964 ProcessBlock(pfrom, pblock,
true,
true);
4971 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4988 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4999 std::vector<CBlockHeader> headers;
5004 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
5007 headers.resize(nCount);
5008 for (
unsigned int n = 0; n < nCount; n++) {
5009 vRecv >> headers[n];
5013 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
5017 if (m_headers_presync_should_signal.exchange(
false)) {
5018 HeadersPresyncStats stats;
5020 LOCK(m_headers_presync_mutex);
5021 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
5022 if (it != m_headers_presync_stats.end()) stats = it->second;
5040 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
5051 Misbehaving(*peer,
"mutated block");
5056 bool forceProcessing =
false;
5057 const uint256 hash(pblock->GetHash());
5058 bool min_pow_checked =
false;
5063 forceProcessing = IsBlockRequested(hash);
5064 RemoveBlockRequest(hash, pfrom.
GetId());
5068 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
5072 min_pow_checked =
true;
5075 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
5092 Assume(SetupAddressRelay(pfrom, *peer));
5096 if (peer->m_getaddr_recvd) {
5100 peer->m_getaddr_recvd =
true;
5102 peer->m_addrs_to_send.clear();
5103 std::vector<CAddress> vAddr;
5109 for (
const CAddress &addr : vAddr) {
5110 PushAddress(*peer, addr);
5138 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5139 LOCK(tx_relay->m_tx_inventory_mutex);
5140 tx_relay->m_send_mempool =
true;
5166 const auto ping_end = time_received;
5169 bool bPingFinished =
false;
5170 std::string sProblem;
5172 if (nAvail >=
sizeof(
nonce)) {
5176 if (peer->m_ping_nonce_sent != 0) {
5177 if (
nonce == peer->m_ping_nonce_sent) {
5179 bPingFinished =
true;
5180 const auto ping_time = ping_end - peer->m_ping_start.load();
5181 if (ping_time.count() >= 0) {
5186 sProblem =
"Timing mishap";
5190 sProblem =
"Nonce mismatch";
5193 bPingFinished =
true;
5194 sProblem =
"Nonce zero";
5198 sProblem =
"Unsolicited pong without ping";
5202 bPingFinished =
true;
5203 sProblem =
"Short payload";
5206 if (!(sProblem.empty())) {
5210 peer->m_ping_nonce_sent,
5214 if (bPingFinished) {
5215 peer->m_ping_nonce_sent = 0;
5222 LogPrint(
BCLog::NET,
"filterload received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
5229 if (!filter.IsWithinSizeConstraints())
5232 Misbehaving(*peer,
"too-large bloom filter");
5233 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5235 LOCK(tx_relay->m_bloom_filter_mutex);
5236 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
5237 tx_relay->m_relay_txs =
true;
5247 LogPrint(
BCLog::NET,
"filteradd received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
5251 std::vector<unsigned char> vData;
5259 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5260 LOCK(tx_relay->m_bloom_filter_mutex);
5261 if (tx_relay->m_bloom_filter) {
5262 tx_relay->m_bloom_filter->insert(vData);
5268 Misbehaving(*peer,
"bad filteradd message");
5275 LogPrint(
BCLog::NET,
"filterclear received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
5279 auto tx_relay = peer->GetTxRelay();
5280 if (!tx_relay)
return;
5283 LOCK(tx_relay->m_bloom_filter_mutex);
5284 tx_relay->m_bloom_filter =
nullptr;
5285 tx_relay->m_relay_txs =
true;
5294 vRecv >> newFeeFilter;
5296 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5297 tx_relay->m_fee_filter_received = newFeeFilter;
5305 ProcessGetCFilters(pfrom, *peer, vRecv);
5310 ProcessGetCFHeaders(pfrom, *peer, vRecv);
5315 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
5320 std::vector<CInv> vInv;
5323 LOCK(m_tx_download_mutex);
5324 for (
CInv &inv : vInv) {
5328 m_txrequest.ReceivedResponse(pfrom.
GetId(), inv.
hash);
5340 bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5343 LOCK(peer.m_misbehavior_mutex);
5346 if (!peer.m_should_discourage)
return false;
5348 peer.m_should_discourage =
false;
5353 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
5359 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
5379 bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
5384 PeerRef peer = GetPeerRef(pfrom->
GetId());
5385 if (peer ==
nullptr)
return false;
5389 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
5392 LOCK(peer->m_getdata_requests_mutex);
5393 if (!peer->m_getdata_requests.empty()) {
5394 ProcessGetData(*pfrom, *peer, interruptMsgProc);
5398 const bool processed_orphan = ProcessOrphanTx(*peer);
5403 if (processed_orphan)
return true;
5408 LOCK(peer->m_getdata_requests_mutex);
5409 if (!peer->m_getdata_requests.empty())
return true;
5422 bool fMoreWork = poll_result->second;
5424 TRACE6(net, inbound_message,
5433 if (m_opts.capture_messages) {
5438 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5439 if (interruptMsgProc)
return false;
5441 LOCK(peer->m_getdata_requests_mutex);
5442 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5449 LOCK(m_tx_download_mutex);
5450 if (m_orphanage.HaveTxToReconsider(peer->m_id)) fMoreWork =
true;
5451 }
catch (
const std::exception& e) {
5460 void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5473 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5475 if (state.m_chain_sync.m_timeout != 0s) {
5476 state.m_chain_sync.m_timeout = 0s;
5477 state.m_chain_sync.m_work_header =
nullptr;
5478 state.m_chain_sync.m_sent_getheaders =
false;
5480 }
else if (state.m_chain_sync.m_timeout == 0s || (state.m_chain_sync.m_work_header !=
nullptr && state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= state.m_chain_sync.m_work_header->nChainWork)) {
5488 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5489 state.m_chain_sync.m_sent_getheaders =
false;
5490 }
else if (state.m_chain_sync.m_timeout > 0s && time_in_seconds > state.m_chain_sync.m_timeout) {
5494 if (state.m_chain_sync.m_sent_getheaders) {
5496 LogPrintf(
"Disconnecting outbound peer %d for old chain, best known block = %s\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>");
5499 assert(state.m_chain_sync.m_work_header);
5504 MaybeSendGetHeaders(pto,
5505 GetLocator(state.m_chain_sync.m_work_header->pprev),
5507 LogPrint(
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());
5508 state.m_chain_sync.m_sent_getheaders =
true;
5520 void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5529 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5533 if (pnode->
GetId() > youngest_peer.first) {
5534 next_youngest_peer = youngest_peer;
5535 youngest_peer.first = pnode->
GetId();
5539 NodeId to_disconnect = youngest_peer.first;
5540 if (youngest_peer.second > next_youngest_peer.second) {
5543 to_disconnect = next_youngest_peer.first;
5552 CNodeState *node_state =
State(pnode->
GetId());
5553 if (node_state ==
nullptr ||
5556 LogPrint(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5560 LogPrint(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5576 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5585 if (state ==
nullptr)
return;
5587 if (state->m_chain_sync.m_protect)
return;
5591 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->
GetId() > worst_peer)) {
5592 worst_peer = pnode->
GetId();
5593 oldest_block_announcement = state->m_last_block_announcement;
5596 if (worst_peer != -1) {
5607 LogPrint(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5611 LogPrint(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5628 void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5632 auto now{GetTime<std::chrono::seconds>()};
5634 EvictExtraOutboundPeers(now);
5636 if (now > m_stale_tip_check_time) {
5640 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5649 if (!m_initial_sync_finished && CanDirectFetch()) {
5651 m_initial_sync_finished =
true;
5655 void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5658 peer.m_ping_nonce_sent &&
5668 bool pingSend =
false;
5670 if (peer.m_ping_queued) {
5675 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5684 }
while (
nonce == 0);
5685 peer.m_ping_queued =
false;
5686 peer.m_ping_start = now;
5688 peer.m_ping_nonce_sent =
nonce;
5692 peer.m_ping_nonce_sent = 0;
5698 void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5701 if (!peer.m_addr_relay_enabled)
return;
5703 LOCK(peer.m_addr_send_times_mutex);
5706 peer.m_next_local_addr_send < current_time) {
5713 if (peer.m_next_local_addr_send != 0us) {
5714 peer.m_addr_known->reset();
5717 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5718 PushAddress(peer, local_addr);
5724 if (current_time <= peer.m_next_addr_send)
return;
5737 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5738 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5741 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5742 peer.m_addrs_to_send.end());
5745 if (peer.m_addrs_to_send.empty())
return;
5747 if (peer.m_wants_addrv2) {
5752 peer.m_addrs_to_send.clear();
5755 if (peer.m_addrs_to_send.capacity() > 40) {
5756 peer.m_addrs_to_send.shrink_to_fit();
5760 void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5768 CNodeState &state = *
State(
node.GetId());
5769 if (state.pindexBestKnownBlock !=
nullptr &&
5776 peer.m_sent_sendheaders =
true;
5781 void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5783 if (m_opts.ignore_incoming_txs)
return;
5799 if (peer.m_fee_filter_sent == MAX_FILTER) {
5802 peer.m_next_send_feefilter = 0us;
5805 if (current_time > peer.m_next_send_feefilter) {
5806 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5809 if (filterToSend != peer.m_fee_filter_sent) {
5811 peer.m_fee_filter_sent = filterToSend;
5818 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5824 class CompareInvMempoolOrder
5829 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5832 m_wtxid_relay = use_wtxid;
5835 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5839 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5844 bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const 5854 bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5859 if (
node.IsBlockOnlyConn())
return false;
5861 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5865 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5871 bool PeerManagerImpl::SendMessages(
CNode* pto)
5876 PeerRef peer = GetPeerRef(pto->
GetId());
5877 if (!peer)
return false;
5882 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5885 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5886 PushNodeVersion(*pto, *peer);
5887 peer->m_outbound_version_message_sent =
true;
5894 const auto current_time{GetTime<std::chrono::microseconds>()};
5902 MaybeSendPing(*pto, *peer, current_time);
5907 MaybeSendAddr(*pto, *peer, current_time);
5909 MaybeSendSendHeaders(*pto, *peer);
5917 if (m_chainman.m_best_header ==
nullptr) {
5924 bool sync_blocks_and_headers_from_peer =
false;
5925 if (state.fPreferredDownload) {
5926 sync_blocks_and_headers_from_peer =
true;
5937 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5938 sync_blocks_and_headers_from_peer =
true;
5944 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5945 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5953 if (pindexStart->
pprev)
5954 pindexStart = pindexStart->
pprev;
5955 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5958 state.fSyncStarted =
true;
5982 LOCK(peer->m_block_inv_mutex);
5983 std::vector<CBlock> vHeaders;
5984 bool fRevertToInv = ((!peer->m_prefers_headers &&
5985 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5988 ProcessBlockAvailability(pto->
GetId());
5990 if (!fRevertToInv) {
5991 bool fFoundStartingHeader =
false;
5995 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
6000 fRevertToInv =
true;
6003 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
6015 fRevertToInv =
true;
6018 pBestIndex = pindex;
6019 if (fFoundStartingHeader) {
6022 }
else if (PeerHasHeader(&state, pindex)) {
6024 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
6027 fFoundStartingHeader =
true;
6032 fRevertToInv =
true;
6037 if (!fRevertToInv && !vHeaders.empty()) {
6038 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
6042 vHeaders.front().GetHash().ToString(), pto->
GetId());
6044 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
6046 LOCK(m_most_recent_block_mutex);
6047 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
6051 if (cached_cmpctblock_msg.has_value()) {
6052 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
6060 state.pindexBestHeaderSent = pBestIndex;
6061 }
else if (peer->m_prefers_headers) {
6062 if (vHeaders.size() > 1) {
6065 vHeaders.front().GetHash().ToString(),
6066 vHeaders.back().GetHash().ToString(), pto->
GetId());
6069 vHeaders.front().GetHash().ToString(), pto->
GetId());
6072 state.pindexBestHeaderSent = pBestIndex;
6074 fRevertToInv =
true;
6080 if (!peer->m_blocks_for_headers_relay.empty()) {
6081 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
6094 if (!PeerHasHeader(&state, pindex)) {
6095 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
6101 peer->m_blocks_for_headers_relay.clear();
6107 std::vector<CInv> vInv;
6109 LOCK(peer->m_block_inv_mutex);
6113 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
6120 peer->m_blocks_for_inv_relay.clear();
6123 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
6124 LOCK(tx_relay->m_tx_inventory_mutex);
6127 if (tx_relay->m_next_inv_send_time < current_time) {
6128 fSendTrickle =
true;
6138 LOCK(tx_relay->m_bloom_filter_mutex);
6139 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
6143 if (fSendTrickle && tx_relay->m_send_mempool) {
6144 auto vtxinfo = m_mempool.
infoAll();
6145 tx_relay->m_send_mempool =
false;
6146 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6148 LOCK(tx_relay->m_bloom_filter_mutex);
6150 for (
const auto& txinfo : vtxinfo) {
6153 peer->m_wtxid_relay ?
6154 txinfo.tx->GetWitnessHash().ToUint256() :
6155 txinfo.tx->GetHash().ToUint256(),
6157 tx_relay->m_tx_inventory_to_send.erase(inv.
hash);
6160 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6163 if (tx_relay->m_bloom_filter) {
6164 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6166 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6167 vInv.push_back(inv);
6178 std::vector<std::set<uint256>::iterator> vInvTx;
6179 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
6180 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
6181 vInvTx.push_back(it);
6183 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6186 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
6187 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6190 unsigned int nRelayedTransactions = 0;
6191 LOCK(tx_relay->m_bloom_filter_mutex);
6194 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
6196 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6197 std::set<uint256>::iterator it = vInvTx.back();
6202 tx_relay->m_tx_inventory_to_send.erase(it);
6204 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
6213 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6216 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6218 vInv.push_back(inv);
6219 nRelayedTransactions++;
6224 tx_relay->m_tx_inventory_known_filter.insert(hash);
6229 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6236 auto stalling_timeout = m_block_stalling_timeout.load();
6237 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6246 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6256 if (state.vBlocksInFlight.size() > 0) {
6257 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6258 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6266 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
6268 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6269 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6286 state.fSyncStarted =
false;
6288 peer->m_headers_sync_timeout = 0us;
6294 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
6300 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
6305 std::vector<CInv> vGetData;
6307 std::vector<const CBlockIndex*> vToDownload;
6309 auto get_inflight_budget = [&state]() {
6315 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
6320 TryDownloadingHistoricalBlocks(
6322 get_inflight_budget(),
6323 vToDownload, from_tip,
6324 Assert(m_chainman.GetSnapshotBaseBlock()));
6327 uint32_t nFetchFlags = GetFetchFlags(*peer);
6329 BlockRequested(pto->
GetId(), *pindex);
6333 if (state.vBlocksInFlight.empty() && staller != -1) {
6334 if (
State(staller)->m_stalling_since == 0us) {
6335 State(staller)->m_stalling_since = current_time;
6345 LOCK(m_tx_download_mutex);
6346 std::vector<std::pair<NodeId, GenTxid>> expired;
6347 auto requestable = m_txrequest.GetRequestable(pto->
GetId(), current_time, &expired);
6348 for (
const auto& entry : expired) {
6349 LogPrint(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ?
"wtx" :
"tx",
6350 entry.second.GetHash().ToString(), entry.first);
6352 for (
const GenTxid& gtxid : requestable) {
6355 if (!AlreadyHaveTx(gtxid,
false)) {
6367 m_txrequest.ForgetTxHash(gtxid.
GetHash());
6372 if (!vGetData.empty())
6375 MaybeSendFeefilter(*pto, *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.
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
enum ReadStatus_t ReadStatus
static constexpr auto TXID_RELAY_DELAY
How long to delay requesting transactions via txids, if we have wtxid-relaying peers.
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
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
invalid by consensus rules
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 GenTxid Wtxid(const uint256 &hash)
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.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
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::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
#define LogPrint(category,...)
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...
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected Provides the block that was disconnected.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
std::vector< TxMempoolInfo > infoAll() const
uint256 GetPackageHash(const std::vector< CTransactionRef > &transactions)
Get the hash of these transactions' wtxids, concatenated in lexicographical order (treating the wtxid...
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
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)
bool exists(const GenTxid >xid) const
ReconciliationRegisterResult
We don't have the previous block the checked one is built on.
Data structure to keep track of, and schedule, transaction downloads from peers.
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
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
std::vector< uint16_t > indexes
bool IsOutboundOrBlockRelayConn() const
static const int WTXID_RELAY_VERSION
"wtxidrelay" command 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.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests.cpp.
Manages warning messages within a node.
size_t DynamicMemoryUsage() const
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
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)
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
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...
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
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return all or many randomly selected addresses, optionally by network.
bool IsFeelerConn() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
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...
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.
virtual void ActiveTipChange(const CBlockIndex &new_tip, bool is_ibd)
Notifies listeners any time the block chain tip changes, synchronously.
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.
const TxValidationState m_state
Contains information about why the transaction failed.
std::map< uint256, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
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...
violated mempool's fee/size/descendant/RBF/etc limits
static constexpr auto NONPREF_PEER_TX_DELAY
How long to delay requesting transactions from non-preferred peers.
the block header may be on a too-little-work chain
inputs (covered by txid) failed policy rules
void SetTryNewOutboundPeer(bool flag)
void ignore(size_t num_ignore)
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
const ResultType m_result_type
Result type.
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
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.
transaction spends a coinbase too early, or violates locktime/sequence locks
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
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
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
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
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)
const std::vector< CTxIn > vin
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" command and announcing blocks with headers starts with this version ...
Functions to serialize / deserialize common bitcoin types.
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool DisconnectNode(const std::string &node)
std::function< void(const CAddress &addr, const std::string &msg_type, Span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
int GetExtraBlockRelayCount() const
int64_t CAmount
Amount in satoshis (Can be negative)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
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.
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
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).
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
virtual PeerManagerInfo GetInfo() const =0
Get peer manager info.
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.
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
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.
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, DataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
CAmount m_fee_filter_received
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.
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
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
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
Invalid by a change to consensus rules more recent than SegWit.
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
const std::list< CTransactionRef > m_replaced_transactions
Mempool transactions replaced by the tx.
arith_uint256 CalculateClaimedHeadersWork(const std::vector< CBlockHeader > &headers)
Return the sum of the claimed work on a given set of headers.
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
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...
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
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.
An input of a transaction.
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
the block failed to meet one of our checkpoints
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...
constexpr int64_t count_microseconds(std::chrono::microseconds t)
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
static constexpr SerParams V1
bool IsProxy(const CNetAddr &addr)
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
bool LoadingBlocks() const
bool IsManualConn() const
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
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.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
#define LogPrintLevel(category, level,...)
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
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
bool GetNetworkActive() const
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.
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.
virtual std::optional< std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
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.
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
fails some policy, but might be acceptable if submitted in a (different) package
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...
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< CTransactionRef > &extra_txn)
std::chrono::seconds PowTargetSpacing() const
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::microseconds m_ping_wait
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
bool CheckIncomingNonce(uint64_t nonce)
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
bool IsBlockOnlyConn() const
Transaction is missing a witness.
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids"...
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
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...
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
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
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
#define LogDebug(category,...)
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
#define LOCKS_EXCLUDED(...)
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
std::set< uint256 > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
uint32_t GetMappedAS(const CNetAddr &addr) const
std::vector< std::pair< unsigned int, uint256 > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
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...
static transaction_identifier FromUint256(const uint256 &id)
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
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).
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
virtual void RelayTransaction(const uint256 &txid, const uint256 &wtxid)=0
Relay transaction to all peers.
bool ReadRawBlockFromDisk(std::vector< uint8_t > &block, const FlatFilePos &pos) const
bool IsTxAvailable(size_t index) const
A block this one builds on is invalid.
TxMempoolInfo info(const GenTxid >xid) const
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
#define TRACE6(context, event, a, b, c, d, e, f)
#define ACQUIRED_BEFORE(...)
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network) ...
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
virtual void UnitTestMisbehaving(NodeId peer_id)=0
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
#define LIMITED_STRING(obj, n)
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
static constexpr auto OVERLOADED_PEER_TX_DELAY
How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT).
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span
Like the Span constructor, but for (const) unsigned char member types only.
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.
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)
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
std::atomic< int > nVersion
Invalid by a change to consensus rules more recent than SegWit.
const CBlockIndex * GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The tip of the background sync chain.
std::string ConnectionTypeAsString() const
static size_t RecursiveDynamicUsage(const CScript &script)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
virtual void BlockConnected(ChainstateRole role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
this node does not have a mempool so can't validate the transaction
CTransactionRef get(const uint256 &hash) const
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
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
bool IsAddrFetchConn() const
arith_uint256 GetBlockProof(const CBlockIndex &block)
A Span is an object that can refer to a contiguous sequence of objects.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
The basic transaction that is broadcasted on the network and contained in blocks. ...
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
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"...
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT
Maximum number of in-flight transaction requests from a peer.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
full block available in blk*.dat
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
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
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
int64_t GetTime()
DEPRECATED, see GetTime.
int GetCommonVersion() const
const std::string m_addr_name
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
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.
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
otherwise didn't meet our local policy rules
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.
A generic txid reference (txid or wtxid).
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
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.
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
static GenTxid Txid(const uint256 &hash)
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
std::string ToString(const T &t)
Locale-independent version of std::to_string.
static constexpr auto GETDATA_TX_INTERVAL
How long to wait before downloading a transaction from an additional peer.
const uint256 & GetHash() const LIFETIMEBOUND
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.
const Txid & GetHash() const LIFETIMEBOUND
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.
bool ProcessNewBlockHeaders(const std::vector< CBlockHeader > &block, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
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.