73#include <initializer_list>
206 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
240 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
243 const bool m_is_inbound;
246 Mutex m_misbehavior_mutex;
248 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
251 Mutex m_block_inv_mutex;
255 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
259 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
270 std::atomic<int> m_starting_height{-1};
273 std::atomic<uint64_t> m_ping_nonce_sent{0};
275 std::atomic<std::chrono::microseconds> m_ping_start{0us};
277 std::atomic<bool> m_ping_queued{
false};
280 std::atomic<bool> m_wtxid_relay{
false};
292 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
294 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
305 std::set<uint256> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
309 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
312 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
318 std::atomic<CAmount> m_fee_filter_received{0};
324 LOCK(m_tx_relay_mutex);
326 m_tx_relay = std::make_unique<Peer::TxRelay>();
327 return m_tx_relay.get();
332 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
361 std::atomic_bool m_addr_relay_enabled{
false};
365 mutable Mutex m_addr_send_times_mutex;
367 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
369 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
372 std::atomic_bool m_wants_addrv2{
false};
381 std::atomic<uint64_t> m_addr_rate_limited{0};
383 std::atomic<uint64_t> m_addr_processed{0};
389 Mutex m_getdata_requests_mutex;
391 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
397 Mutex m_headers_sync_mutex;
400 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
403 std::atomic<bool> m_sent_sendheaders{
false};
413 std::atomic<std::chrono::seconds> m_time_offset{0
s};
417 , m_our_services{our_services}
418 , m_is_inbound{is_inbound}
422 mutable Mutex m_tx_relay_mutex;
425 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
428using PeerRef = std::shared_ptr<Peer>;
440 uint256 hashLastUnknownBlock{};
446 bool fSyncStarted{
false};
448 std::chrono::microseconds m_stalling_since{0us};
449 std::list<QueuedBlock> vBlocksInFlight;
451 std::chrono::microseconds m_downloading_since{0us};
453 bool fPreferredDownload{
false};
455 bool m_requested_hb_cmpctblocks{
false};
457 bool m_provides_cmpctblocks{
false};
483 struct ChainSyncTimeoutState {
485 std::chrono::seconds m_timeout{0
s};
489 bool m_sent_getheaders{
false};
491 bool m_protect{
false};
494 ChainSyncTimeoutState m_chain_sync;
497 int64_t m_last_block_announcement{0};
526 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
540 void SetBestBlock(
int height,
std::chrono::seconds time)
override
542 m_best_height = height;
543 m_best_block_time = time;
547 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
548 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
572 void Misbehaving(Peer& peer,
const std::string& message);
583 bool via_compact_block,
const std::string& message =
"")
598 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
612 bool first_time_failure)
637 bool ProcessOrphanTx(Peer& peer)
647 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
649 bool via_compact_block)
661 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
680 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
694 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
709 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
711 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
718 template <
typename... Args>
719 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
725 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
731 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
774 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
777 std::atomic<int> m_best_height{-1};
779 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
787 const Options m_opts;
789 bool RejectIncomingTxs(
const CNode& peer)
const;
797 mutable Mutex m_peer_mutex;
804 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
814 uint32_t GetFetchFlags(
const Peer& peer)
const;
816 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
833 std::atomic<int> m_wtxid_relay_peers{0};
850 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
855 Mutex m_most_recent_block_mutex;
856 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
857 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
859 std::unique_ptr<const std::map<uint256, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
863 Mutex m_headers_presync_mutex;
871 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
873 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
877 std::atomic_bool m_headers_presync_should_signal{
false};
947 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
953 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
958 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
983 std::vector<CTransactionRef> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
985 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
997 int64_t ApproximateBestBlockDepth() const;
1007 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1025 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1027 const
uint256& stop_hash, uint32_t max_height_diff,
1076const CNodeState* PeerManagerImpl::State(
NodeId pnode)
const
1078 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1079 if (it == m_node_states.end())
1084CNodeState* PeerManagerImpl::State(
NodeId pnode)
1086 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1094static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1099void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1101 assert(peer.m_addr_known);
1102 peer.m_addr_known->insert(addr.
GetKey());
1105void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1110 assert(peer.m_addr_known);
1111 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1113 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1115 peer.m_addrs_to_send.push_back(addr);
1120static void AddKnownTx(Peer& peer,
const uint256& hash)
1122 auto tx_relay = peer.GetTxRelay();
1123 if (!tx_relay)
return;
1125 LOCK(tx_relay->m_tx_inventory_mutex);
1126 tx_relay->m_tx_inventory_known_filter.insert(hash);
1130static bool CanServeBlocks(
const Peer& peer)
1137static bool IsLimitedPeer(
const Peer& peer)
1144static bool CanServeWitnesses(
const Peer& peer)
1149std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1150 std::chrono::seconds average_interval)
1152 if (m_next_inv_to_inbounds.load() < now) {
1156 m_next_inv_to_inbounds = now + m_rng.rand_exp_duration(average_interval);
1158 return m_next_inv_to_inbounds;
1161bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1163 return mapBlocksInFlight.count(hash);
1166bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1168 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1169 auto [nodeid, block_it] = range.first->second;
1170 PeerRef peer{GetPeerRef(nodeid)};
1171 if (peer && !peer->m_is_inbound)
return true;
1177void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1179 auto range = mapBlocksInFlight.equal_range(hash);
1180 if (range.first == range.second) {
1188 while (range.first != range.second) {
1189 const auto& [node_id, list_it]{range.first->second};
1191 if (from_peer && *from_peer != node_id) {
1196 CNodeState& state = *
Assert(State(node_id));
1198 if (state.vBlocksInFlight.begin() == list_it) {
1200 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1202 state.vBlocksInFlight.erase(list_it);
1204 if (state.vBlocksInFlight.empty()) {
1206 m_peers_downloading_from--;
1208 state.m_stalling_since = 0us;
1210 range.first = mapBlocksInFlight.erase(range.first);
1214bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1218 CNodeState *state = State(nodeid);
1219 assert(state !=
nullptr);
1224 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1225 if (range.first->second.first == nodeid) {
1227 *pit = &range.first->second.second;
1234 RemoveBlockRequest(hash, nodeid);
1236 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1237 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1238 if (state->vBlocksInFlight.size() == 1) {
1240 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1241 m_peers_downloading_from++;
1243 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1245 *pit = &itInFlight->second.second;
1250void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1257 if (m_opts.ignore_incoming_txs)
return;
1259 CNodeState* nodestate = State(nodeid);
1260 PeerRef peer{GetPeerRef(nodeid)};
1261 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1266 int num_outbound_hb_peers = 0;
1267 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1268 if (*it == nodeid) {
1269 lNodesAnnouncingHeaderAndIDs.erase(it);
1270 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1273 PeerRef peer_ref{GetPeerRef(*it)};
1274 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1276 if (peer && peer->m_is_inbound) {
1279 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1280 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1281 if (remove_peer && !remove_peer->m_is_inbound) {
1284 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1290 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1293 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1294 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1296 pnodeStop->m_bip152_highbandwidth_to = false;
1299 lNodesAnnouncingHeaderAndIDs.pop_front();
1304 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1309bool PeerManagerImpl::TipMayBeStale()
1313 if (m_last_tip_update.load() == 0
s) {
1314 m_last_tip_update = GetTime<std::chrono::seconds>();
1316 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1319int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1324bool PeerManagerImpl::CanDirectFetch()
1331 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1333 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1338void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1339 CNodeState *state = State(nodeid);
1340 assert(state !=
nullptr);
1342 if (!state->hashLastUnknownBlock.IsNull()) {
1345 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1346 state->pindexBestKnownBlock = pindex;
1348 state->hashLastUnknownBlock.SetNull();
1353void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1354 CNodeState *state = State(nodeid);
1355 assert(state !=
nullptr);
1357 ProcessBlockAvailability(nodeid);
1362 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1363 state->pindexBestKnownBlock = pindex;
1367 state->hashLastUnknownBlock = hash;
1372void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1377 vBlocks.reserve(vBlocks.size() +
count);
1378 CNodeState *state = State(peer.m_id);
1379 assert(state !=
nullptr);
1382 ProcessBlockAvailability(peer.m_id);
1384 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1392 const CBlockIndex* snap_base{m_chainman.GetSnapshotBaseBlock()};
1393 if (snap_base && state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1394 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1401 if (state->pindexLastCommonBlock ==
nullptr ||
1402 (snap_base && state->pindexLastCommonBlock->nHeight < snap_base->nHeight)) {
1403 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1408 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1409 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1412 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1418 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1421void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1426 if (vBlocks.size() >=
count) {
1430 vBlocks.reserve(
count);
1431 CNodeState *state =
Assert(State(peer.m_id));
1433 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1450void 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)
1452 std::vector<const CBlockIndex*> vToFetch;
1453 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1454 bool is_limited_peer = IsLimitedPeer(peer);
1456 while (pindexWalk->
nHeight < nMaxHeight) {
1460 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1461 vToFetch.resize(nToFetch);
1462 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1463 vToFetch[nToFetch - 1] = pindexWalk;
1464 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1465 vToFetch[i - 1] = vToFetch[i]->
pprev;
1485 state->pindexLastCommonBlock = pindex;
1492 if (waitingfor == -1) {
1494 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1500 if (pindex->
nHeight > nWindowEnd) {
1502 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1504 if (nodeStaller) *nodeStaller = waitingfor;
1514 vBlocks.push_back(pindex);
1515 if (vBlocks.size() ==
count) {
1524void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1526 uint64_t my_services{peer.m_our_services};
1527 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1529 const int nNodeStartingHeight{m_best_height};
1536 const bool tx_relay{!RejectIncomingTxs(pnode)};
1543 LogDebug(
BCLog::NET,
"send version message: version %d, blocks=%d, them=%s, txrelay=%d, peer=%d\n",
PROTOCOL_VERSION, nNodeStartingHeight, addr_you.
ToStringAddrPort(), tx_relay, nodeid);
1549void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1552 CNodeState *state = State(
node);
1553 if (state) state->m_last_block_announcement = time_in_seconds;
1561 m_node_states.try_emplace(m_node_states.end(), nodeid);
1563 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1569 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1572 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1576void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1580 for (
const auto& txid : unbroadcast_txids) {
1583 if (tx !=
nullptr) {
1584 RelayTransaction(txid, tx->GetWitnessHash());
1593 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1596void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1607 PeerRef peer = RemovePeer(nodeid);
1609 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1610 assert(m_wtxid_relay_peers >= 0);
1612 CNodeState *state = State(nodeid);
1613 assert(state !=
nullptr);
1615 if (state->fSyncStarted)
1618 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1619 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1620 while (range.first != range.second) {
1621 auto [node_id, list_it] = range.first->second;
1622 if (node_id != nodeid) {
1625 range.first = mapBlocksInFlight.erase(range.first);
1630 LOCK(m_tx_download_mutex);
1631 m_txdownloadman.DisconnectedPeer(nodeid);
1633 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1634 m_num_preferred_download_peers -= state->fPreferredDownload;
1635 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1636 assert(m_peers_downloading_from >= 0);
1637 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1638 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1640 m_node_states.erase(nodeid);
1642 if (m_node_states.empty()) {
1644 assert(mapBlocksInFlight.empty());
1645 assert(m_num_preferred_download_peers == 0);
1646 assert(m_peers_downloading_from == 0);
1647 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1648 assert(m_wtxid_relay_peers == 0);
1649 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1652 if (
node.fSuccessfullyConnected &&
1653 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1660 LOCK(m_headers_presync_mutex);
1661 m_headers_presync_stats.erase(nodeid);
1666bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1669 return !(GetDesirableServiceFlags(services) & (~services));
1683PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1686 auto it = m_peer_map.find(
id);
1687 return it != m_peer_map.end() ? it->second :
nullptr;
1690PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1694 auto it = m_peer_map.find(
id);
1695 if (it != m_peer_map.end()) {
1696 ret = std::move(it->second);
1697 m_peer_map.erase(it);
1706 const CNodeState* state = State(nodeid);
1707 if (state ==
nullptr)
1709 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1710 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1711 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1717 PeerRef peer = GetPeerRef(nodeid);
1718 if (peer ==
nullptr)
return false;
1727 auto ping_wait{0us};
1728 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1729 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1732 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1745 LOCK(peer->m_headers_sync_mutex);
1746 if (peer->m_headers_sync) {
1755std::vector<TxOrphanage::OrphanTxBase> PeerManagerImpl::GetOrphanTransactions()
1757 LOCK(m_tx_download_mutex);
1758 return m_txdownloadman.GetOrphanTransactions();
1765 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1769void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1771 if (m_opts.max_extra_txs <= 0)
1773 if (!vExtraTxnForCompact.size())
1774 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1775 vExtraTxnForCompact[vExtraTxnForCompactIt] = tx;
1776 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1779void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1781 LOCK(peer.m_misbehavior_mutex);
1783 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1784 peer.m_should_discourage =
true;
1793 bool via_compact_block,
const std::string& message)
1795 PeerRef peer{GetPeerRef(nodeid)};
1806 if (!via_compact_block) {
1807 if (peer) Misbehaving(*peer, message);
1815 if (peer && !via_compact_block && !peer->m_is_inbound) {
1816 if (peer) Misbehaving(*peer, message);
1823 if (peer) Misbehaving(*peer, message);
1827 if (peer) Misbehaving(*peer, message);
1832 if (message !=
"") {
1839 PeerRef peer{GetPeerRef(nodeid)};
1845 if (peer) Misbehaving(*peer,
"");
1863bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1872std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1877 PeerRef peer = GetPeerRef(peer_id);
1878 if (peer ==
nullptr)
return "Peer does not exist";
1881 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1886 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1889 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1901 if (!success)
return "Peer not fully connected";
1905 return std::nullopt;
1912 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1918 : m_rng{opts.deterministic_rng},
1920 m_chainparams(chainman.GetParams()),
1924 m_chainman(chainman),
1926 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.max_orphan_txs, opts.deterministic_rng}),
1927 m_warnings{warnings},
1932 if (opts.reconcile_txs) {
1937void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1948 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1951void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
1959 LOCK(m_tx_download_mutex);
1963 m_txdownloadman.ActiveTipChange();
1973void PeerManagerImpl::BlockConnected(
1975 const std::shared_ptr<const CBlock>& pblock,
1980 m_last_tip_update = GetTime<std::chrono::seconds>();
1983 auto stalling_timeout = m_block_stalling_timeout.load();
1987 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1997 LOCK(m_tx_download_mutex);
1998 m_txdownloadman.BlockConnected(pblock);
2001void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2003 LOCK(m_tx_download_mutex);
2004 m_txdownloadman.BlockDisconnected();
2011void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2013 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2017 if (pindex->
nHeight <= m_highest_fast_announce)
2019 m_highest_fast_announce = pindex->
nHeight;
2023 uint256 hashBlock(pblock->GetHash());
2024 const std::shared_future<CSerializedNetMsg> lazy_ser{
2028 auto most_recent_block_txs = std::make_unique<std::map<uint256, CTransactionRef>>();
2029 for (
const auto& tx : pblock->vtx) {
2030 most_recent_block_txs->emplace(tx->GetHash(), tx);
2031 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2034 LOCK(m_most_recent_block_mutex);
2035 m_most_recent_block_hash = hashBlock;
2036 m_most_recent_block = pblock;
2037 m_most_recent_compact_block = pcmpctblock;
2038 m_most_recent_block_txs = std::move(most_recent_block_txs);
2046 ProcessBlockAvailability(pnode->
GetId());
2047 CNodeState &state = *State(pnode->
GetId());
2050 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2052 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2053 hashBlock.ToString(), pnode->
GetId());
2056 PushMessage(*pnode, ser_cmpctblock.Copy());
2057 state.pindexBestHeaderSent = pindex;
2066void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2068 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2071 if (fInitialDownload)
return;
2074 std::vector<uint256> vHashes;
2076 while (pindexToAnnounce != pindexFork) {
2078 pindexToAnnounce = pindexToAnnounce->
pprev;
2088 for (
auto& it : m_peer_map) {
2089 Peer& peer = *it.second;
2090 LOCK(peer.m_block_inv_mutex);
2091 for (
const uint256& hash : vHashes | std::views::reverse) {
2092 peer.m_blocks_for_headers_relay.push_back(hash);
2109 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2114 it != mapBlockSource.end() &&
2115 State(it->second.first)) {
2116 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2126 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2127 if (it != mapBlockSource.end()) {
2128 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2131 if (it != mapBlockSource.end())
2132 mapBlockSource.erase(it);
2140bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2145void PeerManagerImpl::SendPings()
2148 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2151void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2154 for(
auto& it : m_peer_map) {
2155 Peer& peer = *it.second;
2156 auto tx_relay = peer.GetTxRelay();
2157 if (!tx_relay)
continue;
2159 LOCK(tx_relay->m_tx_inventory_mutex);
2165 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2167 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2168 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2169 tx_relay->m_tx_inventory_to_send.insert(hash);
2174void PeerManagerImpl::RelayAddress(
NodeId originator,
2190 const auto current_time{GetTime<std::chrono::seconds>()};
2198 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2200 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2201 assert(nRelayNodes <= best.size());
2205 for (
auto& [
id, peer] : m_peer_map) {
2206 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2208 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2209 if (hashKey > best[i].first) {
2210 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2211 best[i] = std::make_pair(hashKey, peer.get());
2218 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2219 PushAddress(*best[i].second, addr);
2223void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2225 std::shared_ptr<const CBlock> a_recent_block;
2226 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2228 LOCK(m_most_recent_block_mutex);
2229 a_recent_block = m_most_recent_block;
2230 a_recent_compact_block = m_most_recent_compact_block;
2233 bool need_activate_chain =
false;
2245 need_activate_chain =
true;
2249 if (need_activate_chain) {
2251 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2258 bool can_direct_fetch{
false};
2266 if (!BlockRequestAllowed(pindex)) {
2267 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2294 can_direct_fetch = CanDirectFetch();
2298 std::shared_ptr<const CBlock> pblock;
2299 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2300 pblock = a_recent_block;
2304 std::vector<uint8_t> block_data;
2318 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2328 pblock = pblockRead;
2336 bool sendMerkleBlock =
false;
2338 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2339 LOCK(tx_relay->m_bloom_filter_mutex);
2340 if (tx_relay->m_bloom_filter) {
2341 sendMerkleBlock =
true;
2342 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2345 if (sendMerkleBlock) {
2353 typedef std::pair<unsigned int, uint256> PairType;
2365 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2378 LOCK(peer.m_block_inv_mutex);
2380 if (inv.
hash == peer.m_continuation_block) {
2384 std::vector<CInv> vInv;
2385 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2387 peer.m_continuation_block.SetNull();
2395 auto txinfo = m_mempool.
info_for_relay(gtxid, tx_relay.m_last_inv_sequence);
2397 return std::move(txinfo.tx);
2402 LOCK(m_most_recent_block_mutex);
2403 if (m_most_recent_block_txs !=
nullptr) {
2404 auto it = m_most_recent_block_txs->find(gtxid.
GetHash());
2405 if (it != m_most_recent_block_txs->end())
return it->second;
2412void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2416 auto tx_relay = peer.GetTxRelay();
2418 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2419 std::vector<CInv> vNotFound;
2424 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2425 if (interruptMsgProc)
return;
2430 const CInv &inv = *it++;
2432 if (tx_relay ==
nullptr) {
2442 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2445 vNotFound.push_back(inv);
2451 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2452 const CInv &inv = *it++;
2454 ProcessGetBlockData(pfrom, peer, inv);
2463 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2465 if (!vNotFound.empty()) {
2484uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2486 uint32_t nFetchFlags = 0;
2487 if (CanServeWitnesses(peer)) {
2496 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2498 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2507bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2511 Misbehaving(peer,
"header with invalid proof of work");
2516 if (!CheckHeadersAreContinuous(headers)) {
2517 Misbehaving(peer,
"non-continuous headers sequence");
2542void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2543 const std::vector<CBlockHeader>& headers)
2547 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2548 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2550 headers[0].hashPrevBlock.ToString(),
2551 best_header->nHeight,
2561bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2565 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2568 hashLastBlock = header.GetHash();
2573bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2575 if (peer.m_headers_sync) {
2576 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2578 if (result.success) peer.m_last_getheaders_timestamp = {};
2579 if (result.request_more) {
2580 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2582 Assume(!locator.vHave.empty());
2585 if (!locator.vHave.empty()) {
2588 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2591 locator.vHave.front().ToString(), pfrom.
GetId());
2596 peer.m_headers_sync.reset(
nullptr);
2601 LOCK(m_headers_presync_mutex);
2602 m_headers_presync_stats.erase(pfrom.
GetId());
2605 HeadersPresyncStats stats;
2606 stats.first = peer.m_headers_sync->GetPresyncWork();
2608 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2609 peer.m_headers_sync->GetPresyncTime()};
2613 LOCK(m_headers_presync_mutex);
2614 m_headers_presync_stats[pfrom.
GetId()] = stats;
2615 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2616 bool best_updated =
false;
2617 if (best_it == m_headers_presync_stats.end()) {
2621 const HeadersPresyncStats* stat_best{
nullptr};
2622 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2623 if (!stat_best || stat > *stat_best) {
2628 m_headers_presync_bestpeer = peer_best;
2629 best_updated = (peer_best == pfrom.
GetId());
2630 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2632 m_headers_presync_bestpeer = pfrom.
GetId();
2633 best_updated =
true;
2635 if (best_updated && stats.second.has_value()) {
2637 m_headers_presync_should_signal =
true;
2641 if (result.success) {
2644 headers.swap(result.pow_validated_headers);
2647 return result.success;
2655bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2662 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2666 if (total_work < minimum_chain_work) {
2670 if (headers.size() == m_opts.max_headers_result) {
2680 LOCK(peer.m_headers_sync_mutex);
2682 chain_start_header, minimum_chain_work));
2687 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2701bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2703 if (header ==
nullptr) {
2705 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2713bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2721 peer.m_last_getheaders_timestamp = current_time;
2732void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2735 CNodeState *nodestate = State(pfrom.
GetId());
2738 std::vector<const CBlockIndex*> vToFetch;
2746 vToFetch.push_back(pindexWalk);
2748 pindexWalk = pindexWalk->
pprev;
2759 std::vector<CInv> vGetData;
2761 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2766 uint32_t nFetchFlags = GetFetchFlags(peer);
2768 BlockRequested(pfrom.
GetId(), *pindex);
2772 if (vGetData.size() > 1) {
2777 if (vGetData.size() > 0) {
2778 if (!m_opts.ignore_incoming_txs &&
2779 nodestate->m_provides_cmpctblocks &&
2780 vGetData.size() == 1 &&
2781 mapBlocksInFlight.size() == 1 &&
2797void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2798 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2801 CNodeState *nodestate = State(pfrom.
GetId());
2810 nodestate->m_last_block_announcement =
GetTime();
2818 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2840 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) {
2842 nodestate->m_chain_sync.m_protect =
true;
2843 ++m_outbound_peers_with_protect_from_disconnect;
2848void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2849 std::vector<CBlockHeader>&& headers,
2850 bool via_compact_block)
2852 size_t nCount = headers.size();
2859 LOCK(peer.m_headers_sync_mutex);
2860 if (peer.m_headers_sync) {
2861 peer.m_headers_sync.reset(
nullptr);
2862 LOCK(m_headers_presync_mutex);
2863 m_headers_presync_stats.erase(pfrom.
GetId());
2867 peer.m_last_getheaders_timestamp = {};
2875 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2890 bool already_validated_work =
false;
2893 bool have_headers_sync =
false;
2895 LOCK(peer.m_headers_sync_mutex);
2897 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2909 if (headers.empty()) {
2913 have_headers_sync = !!peer.m_headers_sync;
2918 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2920 if (!headers_connect_blockindex) {
2924 HandleUnconnectingHeaders(pfrom, peer, headers);
2931 peer.m_last_getheaders_timestamp = {};
2941 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2942 already_validated_work =
true;
2950 already_validated_work =
true;
2956 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2957 chain_start_header, headers)) {
2969 bool received_new_header{last_received_header ==
nullptr};
2975 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2982 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
2984 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2986 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2990 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
2993 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
2999 bool first_time_failure)
3005 PeerRef peer{GetPeerRef(nodeid)};
3008 ptx->GetHash().ToString(),
3009 ptx->GetWitnessHash().ToString(),
3013 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3016 AddToCompactExtraTransactions(ptx);
3018 for (
const Txid& parent_txid : unique_parents) {
3019 if (peer) AddKnownTx(*peer, parent_txid);
3022 MaybePunishNodeForTx(nodeid, state);
3024 return package_to_validate;
3027void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3033 m_txdownloadman.MempoolAcceptedTx(tx);
3037 tx->GetHash().ToString(),
3038 tx->GetWitnessHash().ToString(),
3041 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3044 AddToCompactExtraTransactions(removedTx);
3054 const auto&
package = package_to_validate.m_txns;
3055 const auto& senders = package_to_validate.
m_senders;
3058 m_txdownloadman.MempoolRejectedPackage(package);
3061 if (!
Assume(package.size() == 2))
return;
3065 auto package_iter = package.rbegin();
3066 auto senders_iter = senders.rbegin();
3067 while (package_iter != package.rend()) {
3068 const auto& tx = *package_iter;
3069 const NodeId nodeid = *senders_iter;
3070 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3074 const auto& tx_result = it_result->second;
3075 switch (tx_result.m_result_type) {
3078 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3088 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3106bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3113 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3116 const Txid& orphanHash = porphanTx->GetHash();
3117 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3134 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3143bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3145 const uint256& stop_hash, uint32_t max_height_diff,
3149 const bool supported_filter_type =
3152 if (!supported_filter_type) {
3154 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg(
fLogIPs));
3155 node.fDisconnect =
true;
3164 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3167 node.fDisconnect =
true;
3172 uint32_t stop_height = stop_index->
nHeight;
3173 if (start_height > stop_height) {
3175 "start height %d and stop height %d, %s\n",
3176 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3177 node.fDisconnect =
true;
3180 if (stop_height - start_height >= max_height_diff) {
3182 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3183 node.fDisconnect =
true;
3188 if (!filter_index) {
3198 uint8_t filter_type_ser;
3199 uint32_t start_height;
3202 vRecv >> filter_type_ser >> start_height >> stop_hash;
3208 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3213 std::vector<BlockFilter> filters;
3215 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3220 for (
const auto& filter : filters) {
3227 uint8_t filter_type_ser;
3228 uint32_t start_height;
3231 vRecv >> filter_type_ser >> start_height >> stop_hash;
3237 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3243 if (start_height > 0) {
3245 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3247 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3253 std::vector<uint256> filter_hashes;
3255 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3269 uint8_t filter_type_ser;
3272 vRecv >> filter_type_ser >> stop_hash;
3278 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3279 std::numeric_limits<uint32_t>::max(),
3280 stop_index, filter_index)) {
3288 for (
int i = headers.size() - 1; i >= 0; i--) {
3293 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3307 bool new_block{
false};
3308 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3310 node.m_last_block_time = GetTime<std::chrono::seconds>();
3315 RemoveBlockRequest(block->GetHash(), std::nullopt);
3318 mapBlockSource.erase(block->GetHash());
3322void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3324 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3325 bool fBlockRead{
false};
3329 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3330 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3331 bool requested_block_from_this_peer{
false};
3334 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3336 while (range_flight.first != range_flight.second) {
3337 auto [node_id, block_it] = range_flight.first->second;
3338 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3339 requested_block_from_this_peer =
true;
3342 range_flight.first++;
3345 if (!requested_block_from_this_peer) {
3354 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3357 if (first_in_flight) {
3359 std::vector<CInv> invs;
3364 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3393 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3408void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3409 const std::chrono::microseconds time_received,
3410 const std::atomic<bool>& interruptMsgProc)
3416 PeerRef peer = GetPeerRef(pfrom.
GetId());
3417 if (peer ==
nullptr)
return;
3427 uint64_t nNonce = 1;
3430 std::string cleanSubVer;
3431 int starting_height = -1;
3434 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3449 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3451 GetDesirableServiceFlags(nServices),
3464 if (!vRecv.
empty()) {
3472 if (!vRecv.
empty()) {
3473 std::string strSubVer;
3477 if (!vRecv.
empty()) {
3478 vRecv >> starting_height;
3498 PushNodeVersion(pfrom, *peer);
3511 if (greatest_common_version >= 70016) {
3520 peer->m_their_services = nServices;
3524 pfrom.cleanSubVer = cleanSubVer;
3526 peer->m_starting_height = starting_height;
3536 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3537 auto*
const tx_relay = peer->SetTxRelay();
3539 LOCK(tx_relay->m_bloom_filter_mutex);
3540 tx_relay->m_relay_txs = fRelay;
3552 const auto* tx_relay = peer->GetTxRelay();
3553 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3555 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3566 CNodeState* state = State(pfrom.
GetId());
3568 m_num_preferred_download_peers += state->fPreferredDownload;
3574 bool send_getaddr{
false};
3576 send_getaddr = SetupAddressRelay(pfrom, *peer);
3586 peer->m_getaddr_sent =
true;
3611 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3616 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3620 m_outbound_time_offsets.Add(peer->m_time_offset);
3621 m_outbound_time_offsets.WarnIfOutOfSync();
3625 if (greatest_common_version <= 70012) {
3626 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3627 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3654 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3657 pfrom.
nVersion.load(), peer->m_starting_height,
3659 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3671 if (m_txreconciliation) {
3672 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3676 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3680 if (
auto tx_relay = peer->GetTxRelay()) {
3689 tx_relay->m_tx_inventory_mutex,
3690 return tx_relay->m_tx_inventory_to_send.empty() &&
3691 tx_relay->m_next_inv_send_time == 0
s));
3696 const CNodeState* state = State(pfrom.
GetId());
3698 .m_preferred = state->fPreferredDownload,
3699 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3700 .m_wtxid_relay = peer->m_wtxid_relay,
3709 peer->m_prefers_headers =
true;
3714 bool sendcmpct_hb{
false};
3715 uint64_t sendcmpct_version{0};
3716 vRecv >> sendcmpct_hb >> sendcmpct_version;
3722 CNodeState* nodestate = State(pfrom.
GetId());
3723 nodestate->m_provides_cmpctblocks =
true;
3724 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3741 if (!peer->m_wtxid_relay) {
3742 peer->m_wtxid_relay =
true;
3743 m_wtxid_relay_peers++;
3762 peer->m_wants_addrv2 =
true;
3770 if (!m_txreconciliation) {
3771 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3782 if (RejectIncomingTxs(pfrom)) {
3791 const auto* tx_relay = peer->GetTxRelay();
3792 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3798 uint32_t peer_txreconcl_version;
3799 uint64_t remote_salt;
3800 vRecv >> peer_txreconcl_version >> remote_salt;
3803 peer_txreconcl_version, remote_salt);
3828 const auto ser_params{
3836 std::vector<CAddress> vAddr;
3838 vRecv >> ser_params(vAddr);
3840 if (!SetupAddressRelay(pfrom, *peer)) {
3847 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3852 std::vector<CAddress> vAddrOk;
3853 const auto current_a_time{Now<NodeSeconds>()};
3856 const auto current_time{GetTime<std::chrono::microseconds>()};
3859 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3863 peer->m_addr_token_timestamp = current_time;
3866 uint64_t num_proc = 0;
3867 uint64_t num_rate_limit = 0;
3868 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
3871 if (interruptMsgProc)
3875 if (peer->m_addr_token_bucket < 1.0) {
3881 peer->m_addr_token_bucket -= 1.0;
3890 addr.
nTime = current_a_time - 5 * 24h;
3892 AddAddressKnown(*peer, addr);
3899 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3901 RelayAddress(pfrom.
GetId(), addr, reachable);
3905 vAddrOk.push_back(addr);
3908 peer->m_addr_processed += num_proc;
3909 peer->m_addr_rate_limited += num_rate_limit;
3910 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3911 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3913 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3914 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3925 std::vector<CInv> vInv;
3929 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
3933 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3937 const auto current_time{GetTime<std::chrono::microseconds>()};
3940 for (
CInv& inv : vInv) {
3941 if (interruptMsgProc)
return;
3946 if (peer->m_wtxid_relay) {
3953 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3956 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3964 best_block = &inv.
hash;
3967 if (reject_tx_invs) {
3973 AddKnownTx(*peer, inv.
hash);
3976 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
3984 if (best_block !=
nullptr) {
3996 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
3997 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
3999 m_chainman.m_best_header->nHeight, best_block->ToString(),
4002 if (!state.fSyncStarted) {
4003 peer->m_inv_triggered_getheaders_before_sync =
true;
4007 m_last_block_inv_triggering_headers_sync = *best_block;
4016 std::vector<CInv> vInv;
4020 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
4026 if (vInv.size() > 0) {
4031 LOCK(peer->m_getdata_requests_mutex);
4032 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
4033 ProcessGetData(pfrom, *peer, interruptMsgProc);
4042 vRecv >> locator >> hashStop;
4058 std::shared_ptr<const CBlock> a_recent_block;
4060 LOCK(m_most_recent_block_mutex);
4061 a_recent_block = m_most_recent_block;
4064 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4079 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4094 if (--nLimit <= 0) {
4098 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4109 std::shared_ptr<const CBlock> recent_block;
4111 LOCK(m_most_recent_block_mutex);
4112 if (m_most_recent_block_hash == req.
blockhash)
4113 recent_block = m_most_recent_block;
4117 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4136 if (!block_pos.IsNull()) {
4143 SendBlockTransactions(pfrom, *peer, block, req);
4156 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4164 vRecv >> locator >> hashStop;
4182 if (m_chainman.
ActiveTip() ==
nullptr ||
4184 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4191 CNodeState *nodestate = State(pfrom.
GetId());
4201 if (!BlockRequestAllowed(pindex)) {
4202 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4215 std::vector<CBlock> vHeaders;
4216 int nLimit = m_opts.max_headers_result;
4218 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4221 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4236 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4242 if (RejectIncomingTxs(pfrom)) {
4257 const uint256& txid = ptx->GetHash();
4258 const uint256& wtxid = ptx->GetWitnessHash();
4260 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4261 AddKnownTx(*peer, hash);
4265 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4266 if (!should_validate) {
4272 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4275 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4281 if (package_to_validate) {
4284 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4285 ProcessPackageResult(package_to_validate.value(), package_result);
4291 Assume(!package_to_validate.has_value());
4301 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4304 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4305 ProcessPackageResult(package_to_validate.value(), package_result);
4321 vRecv >> cmpctblock;
4323 bool received_new_header =
false;
4333 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4343 received_new_header =
true;
4351 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4356 if (received_new_header) {
4357 LogInfo(
"Saw new cmpctblock header hash=%s peer=%d\n",
4358 blockhash.ToString(), pfrom.
GetId());
4361 bool fProcessBLOCKTXN =
false;
4365 bool fRevertToHeaderProcessing =
false;
4369 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4370 bool fBlockReconstructed =
false;
4378 CNodeState *nodestate = State(pfrom.
GetId());
4383 nodestate->m_last_block_announcement =
GetTime();
4389 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4390 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4391 bool requested_block_from_this_peer{
false};
4394 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4396 while (range_flight.first != range_flight.second) {
4397 if (range_flight.first->second.first == pfrom.
GetId()) {
4398 requested_block_from_this_peer =
true;
4401 range_flight.first++;
4406 if (requested_block_from_this_peer) {
4409 std::vector<CInv> vInv(1);
4410 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4417 if (!already_in_flight && !CanDirectFetch()) {
4425 requested_block_from_this_peer) {
4426 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4427 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4428 if (!(*queuedBlockIt)->partialBlock)
4441 Misbehaving(*peer,
"invalid compact block");
4444 if (first_in_flight) {
4446 std::vector<CInv> vInv(1);
4447 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4457 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4462 fProcessBLOCKTXN =
true;
4463 }
else if (first_in_flight) {
4470 IsBlockRequestedFromOutbound(blockhash) ||
4489 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4494 std::vector<CTransactionRef> dummy;
4495 status = tempBlock.FillBlock(*pblock, dummy);
4497 fBlockReconstructed =
true;
4501 if (requested_block_from_this_peer) {
4504 std::vector<CInv> vInv(1);
4505 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4510 fRevertToHeaderProcessing =
true;
4515 if (fProcessBLOCKTXN) {
4518 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4521 if (fRevertToHeaderProcessing) {
4527 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4530 if (fBlockReconstructed) {
4535 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4553 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4570 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4581 std::vector<CBlockHeader> headers;
4585 if (nCount > m_opts.max_headers_result) {
4586 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4589 headers.resize(nCount);
4590 for (
unsigned int n = 0; n < nCount; n++) {
4591 vRecv >> headers[n];
4595 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4599 if (m_headers_presync_should_signal.exchange(
false)) {
4600 HeadersPresyncStats stats;
4602 LOCK(m_headers_presync_mutex);
4603 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4604 if (it != m_headers_presync_stats.end()) stats = it->second;
4622 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4633 Misbehaving(*peer,
"mutated block");
4638 bool forceProcessing =
false;
4639 const uint256 hash(pblock->GetHash());
4640 bool min_pow_checked =
false;
4645 forceProcessing = IsBlockRequested(hash);
4646 RemoveBlockRequest(hash, pfrom.
GetId());
4650 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4654 min_pow_checked =
true;
4657 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4674 Assume(SetupAddressRelay(pfrom, *peer));
4678 if (peer->m_getaddr_recvd) {
4682 peer->m_getaddr_recvd =
true;
4684 peer->m_addrs_to_send.clear();
4685 std::vector<CAddress> vAddr;
4691 for (
const CAddress &addr : vAddr) {
4692 PushAddress(*peer, addr);
4720 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4721 LOCK(tx_relay->m_tx_inventory_mutex);
4722 tx_relay->m_send_mempool =
true;
4748 const auto ping_end = time_received;
4751 bool bPingFinished =
false;
4752 std::string sProblem;
4754 if (nAvail >=
sizeof(
nonce)) {
4758 if (peer->m_ping_nonce_sent != 0) {
4759 if (
nonce == peer->m_ping_nonce_sent) {
4761 bPingFinished =
true;
4762 const auto ping_time = ping_end - peer->m_ping_start.load();
4763 if (ping_time.count() >= 0) {
4768 sProblem =
"Timing mishap";
4772 sProblem =
"Nonce mismatch";
4775 bPingFinished =
true;
4776 sProblem =
"Nonce zero";
4780 sProblem =
"Unsolicited pong without ping";
4784 bPingFinished =
true;
4785 sProblem =
"Short payload";
4788 if (!(sProblem.empty())) {
4792 peer->m_ping_nonce_sent,
4796 if (bPingFinished) {
4797 peer->m_ping_nonce_sent = 0;
4814 Misbehaving(*peer,
"too-large bloom filter");
4815 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4817 LOCK(tx_relay->m_bloom_filter_mutex);
4818 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4819 tx_relay->m_relay_txs =
true;
4833 std::vector<unsigned char> vData;
4841 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4842 LOCK(tx_relay->m_bloom_filter_mutex);
4843 if (tx_relay->m_bloom_filter) {
4844 tx_relay->m_bloom_filter->insert(vData);
4850 Misbehaving(*peer,
"bad filteradd message");
4861 auto tx_relay = peer->GetTxRelay();
4862 if (!tx_relay)
return;
4865 LOCK(tx_relay->m_bloom_filter_mutex);
4866 tx_relay->m_bloom_filter =
nullptr;
4867 tx_relay->m_relay_txs =
true;
4876 vRecv >> newFeeFilter;
4878 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4879 tx_relay->m_fee_filter_received = newFeeFilter;
4887 ProcessGetCFilters(pfrom, *peer, vRecv);
4892 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4897 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4902 std::vector<CInv> vInv;
4904 std::vector<uint256> tx_invs;
4906 for (
CInv &inv : vInv) {
4908 tx_invs.emplace_back(inv.
hash);
4912 LOCK(m_tx_download_mutex);
4913 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
4922bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4925 LOCK(peer.m_misbehavior_mutex);
4928 if (!peer.m_should_discourage)
return false;
4930 peer.m_should_discourage =
false;
4935 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
4941 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
4961bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4966 PeerRef peer = GetPeerRef(pfrom->
GetId());
4967 if (peer ==
nullptr)
return false;
4971 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
4974 LOCK(peer->m_getdata_requests_mutex);
4975 if (!peer->m_getdata_requests.empty()) {
4976 ProcessGetData(*pfrom, *peer, interruptMsgProc);
4980 const bool processed_orphan = ProcessOrphanTx(*peer);
4985 if (processed_orphan)
return true;
4990 LOCK(peer->m_getdata_requests_mutex);
4991 if (!peer->m_getdata_requests.empty())
return true;
5004 bool fMoreWork = poll_result->second;
5015 if (m_opts.capture_messages) {
5020 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5021 if (interruptMsgProc)
return false;
5023 LOCK(peer->m_getdata_requests_mutex);
5024 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5031 LOCK(m_tx_download_mutex);
5032 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
5033 }
catch (
const std::exception& e) {
5042void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5046 CNodeState &state = *State(pto.
GetId());
5055 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5057 if (state.m_chain_sync.m_timeout != 0
s) {
5058 state.m_chain_sync.m_timeout = 0
s;
5059 state.m_chain_sync.m_work_header =
nullptr;
5060 state.m_chain_sync.m_sent_getheaders =
false;
5062 }
else if (state.m_chain_sync.m_timeout == 0
s || (state.m_chain_sync.m_work_header !=
nullptr && state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= state.m_chain_sync.m_work_header->nChainWork)) {
5070 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5071 state.m_chain_sync.m_sent_getheaders =
false;
5072 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5076 if (state.m_chain_sync.m_sent_getheaders) {
5078 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5081 assert(state.m_chain_sync.m_work_header);
5086 MaybeSendGetHeaders(pto,
5087 GetLocator(state.m_chain_sync.m_work_header->pprev),
5089 LogDebug(
BCLog::NET,
"sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString());
5090 state.m_chain_sync.m_sent_getheaders =
true;
5102void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5111 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5115 if (pnode->
GetId() > youngest_peer.first) {
5116 next_youngest_peer = youngest_peer;
5117 youngest_peer.first = pnode->GetId();
5118 youngest_peer.second = pnode->m_last_block_time;
5121 NodeId to_disconnect = youngest_peer.first;
5122 if (youngest_peer.second > next_youngest_peer.second) {
5125 to_disconnect = next_youngest_peer.first;
5134 CNodeState *node_state = State(pnode->
GetId());
5135 if (node_state ==
nullptr ||
5138 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5142 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5158 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5161 AssertLockHeld(::cs_main);
5165 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5166 CNodeState *state = State(pnode->GetId());
5167 if (state == nullptr) return;
5169 if (state->m_chain_sync.m_protect) return;
5172 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5173 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5174 worst_peer = pnode->GetId();
5175 oldest_block_announcement = state->m_last_block_announcement;
5178 if (worst_peer != -1) {
5187 CNodeState &state = *State(pnode->
GetId());
5189 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5193 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5210void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5214 auto now{GetTime<std::chrono::seconds>()};
5216 EvictExtraOutboundPeers(now);
5218 if (now > m_stale_tip_check_time) {
5222 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5231 if (!m_initial_sync_finished && CanDirectFetch()) {
5233 m_initial_sync_finished =
true;
5237void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5240 peer.m_ping_nonce_sent &&
5250 bool pingSend =
false;
5252 if (peer.m_ping_queued) {
5257 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5266 }
while (
nonce == 0);
5267 peer.m_ping_queued =
false;
5268 peer.m_ping_start = now;
5270 peer.m_ping_nonce_sent =
nonce;
5274 peer.m_ping_nonce_sent = 0;
5280void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5283 if (!peer.m_addr_relay_enabled)
return;
5285 LOCK(peer.m_addr_send_times_mutex);
5288 peer.m_next_local_addr_send < current_time) {
5295 if (peer.m_next_local_addr_send != 0us) {
5296 peer.m_addr_known->reset();
5299 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5300 PushAddress(peer, local_addr);
5306 if (current_time <= peer.m_next_addr_send)
return;
5319 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5320 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5323 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5324 peer.m_addrs_to_send.end());
5327 if (peer.m_addrs_to_send.empty())
return;
5329 if (peer.m_wants_addrv2) {
5334 peer.m_addrs_to_send.clear();
5337 if (peer.m_addrs_to_send.capacity() > 40) {
5338 peer.m_addrs_to_send.shrink_to_fit();
5342void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5350 CNodeState &state = *State(
node.GetId());
5351 if (state.pindexBestKnownBlock !=
nullptr &&
5358 peer.m_sent_sendheaders =
true;
5363void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5365 if (m_opts.ignore_incoming_txs)
return;
5381 if (peer.m_fee_filter_sent == MAX_FILTER) {
5384 peer.m_next_send_feefilter = 0us;
5387 if (current_time > peer.m_next_send_feefilter) {
5388 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5391 if (filterToSend != peer.m_fee_filter_sent) {
5393 peer.m_fee_filter_sent = filterToSend;
5400 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5406class CompareInvMempoolOrder
5411 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5414 m_wtxid_relay = use_wtxid;
5417 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5421 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5426bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5436bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5441 if (
node.IsBlockOnlyConn())
return false;
5443 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5447 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5453bool PeerManagerImpl::SendMessages(
CNode* pto)
5458 PeerRef peer = GetPeerRef(pto->
GetId());
5459 if (!peer)
return false;
5464 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5467 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5468 PushNodeVersion(*pto, *peer);
5469 peer->m_outbound_version_message_sent =
true;
5476 const auto current_time{GetTime<std::chrono::microseconds>()};
5484 MaybeSendPing(*pto, *peer, current_time);
5489 MaybeSendAddr(*pto, *peer, current_time);
5491 MaybeSendSendHeaders(*pto, *peer);
5496 CNodeState &state = *State(pto->
GetId());
5499 if (m_chainman.m_best_header ==
nullptr) {
5506 bool sync_blocks_and_headers_from_peer =
false;
5507 if (state.fPreferredDownload) {
5508 sync_blocks_and_headers_from_peer =
true;
5519 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5520 sync_blocks_and_headers_from_peer =
true;
5526 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5527 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5535 if (pindexStart->
pprev)
5536 pindexStart = pindexStart->
pprev;
5537 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5540 state.fSyncStarted =
true;
5564 LOCK(peer->m_block_inv_mutex);
5565 std::vector<CBlock> vHeaders;
5566 bool fRevertToInv = ((!peer->m_prefers_headers &&
5567 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5570 ProcessBlockAvailability(pto->
GetId());
5572 if (!fRevertToInv) {
5573 bool fFoundStartingHeader =
false;
5577 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5582 fRevertToInv =
true;
5585 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5597 fRevertToInv =
true;
5600 pBestIndex = pindex;
5601 if (fFoundStartingHeader) {
5604 }
else if (PeerHasHeader(&state, pindex)) {
5606 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5609 fFoundStartingHeader =
true;
5614 fRevertToInv =
true;
5619 if (!fRevertToInv && !vHeaders.empty()) {
5620 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5624 vHeaders.front().GetHash().ToString(), pto->
GetId());
5626 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5628 LOCK(m_most_recent_block_mutex);
5629 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5633 if (cached_cmpctblock_msg.has_value()) {
5634 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5642 state.pindexBestHeaderSent = pBestIndex;
5643 }
else if (peer->m_prefers_headers) {
5644 if (vHeaders.size() > 1) {
5647 vHeaders.front().GetHash().ToString(),
5648 vHeaders.back().GetHash().ToString(), pto->
GetId());
5651 vHeaders.front().GetHash().ToString(), pto->
GetId());
5654 state.pindexBestHeaderSent = pBestIndex;
5656 fRevertToInv =
true;
5662 if (!peer->m_blocks_for_headers_relay.empty()) {
5663 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5676 if (!PeerHasHeader(&state, pindex)) {
5677 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5683 peer->m_blocks_for_headers_relay.clear();
5689 std::vector<CInv> vInv;
5691 LOCK(peer->m_block_inv_mutex);
5695 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5702 peer->m_blocks_for_inv_relay.clear();
5705 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5706 LOCK(tx_relay->m_tx_inventory_mutex);
5709 if (tx_relay->m_next_inv_send_time < current_time) {
5710 fSendTrickle =
true;
5720 LOCK(tx_relay->m_bloom_filter_mutex);
5721 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5725 if (fSendTrickle && tx_relay->m_send_mempool) {
5726 auto vtxinfo = m_mempool.
infoAll();
5727 tx_relay->m_send_mempool =
false;
5728 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5730 LOCK(tx_relay->m_bloom_filter_mutex);
5732 for (
const auto& txinfo : vtxinfo) {
5735 peer->m_wtxid_relay ?
5736 txinfo.tx->GetWitnessHash().ToUint256() :
5737 txinfo.tx->GetHash().ToUint256(),
5739 tx_relay->m_tx_inventory_to_send.erase(inv.
hash);
5742 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5745 if (tx_relay->m_bloom_filter) {
5746 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5748 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5749 vInv.push_back(inv);
5760 std::vector<std::set<uint256>::iterator> vInvTx;
5761 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5762 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5763 vInvTx.push_back(it);
5765 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5768 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
5769 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5772 unsigned int nRelayedTransactions = 0;
5773 LOCK(tx_relay->m_bloom_filter_mutex);
5776 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5778 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5779 std::set<uint256>::iterator it = vInvTx.back();
5784 tx_relay->m_tx_inventory_to_send.erase(it);
5786 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
5795 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5798 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5800 vInv.push_back(inv);
5801 nRelayedTransactions++;
5806 tx_relay->m_tx_inventory_known_filter.insert(hash);
5811 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5818 auto stalling_timeout = m_block_stalling_timeout.load();
5819 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5828 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5838 if (state.vBlocksInFlight.size() > 0) {
5839 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5840 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5848 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5850 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5851 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5868 state.fSyncStarted =
false;
5870 peer->m_headers_sync_timeout = 0us;
5876 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5882 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5887 std::vector<CInv> vGetData;
5889 std::vector<const CBlockIndex*> vToDownload;
5891 auto get_inflight_budget = [&state]() {
5897 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5902 TryDownloadingHistoricalBlocks(
5904 get_inflight_budget(),
5905 vToDownload, from_tip,
5906 Assert(m_chainman.GetSnapshotBaseBlock()));
5909 uint32_t nFetchFlags = GetFetchFlags(*peer);
5911 BlockRequested(pto->
GetId(), *pindex);
5915 if (state.vBlocksInFlight.empty() && staller != -1) {
5916 if (State(staller)->m_stalling_since == 0us) {
5917 State(staller)->m_stalling_since = current_time;
5927 LOCK(m_tx_download_mutex);
5928 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
5937 if (!vGetData.empty())
5940 MaybeSendFeefilter(*pto, *peer, current_time);
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
arith_uint256 GetBlockProof(const CBlockIndex &block)
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
@ BLOCK_VALID_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous.
@ BLOCK_HAVE_DATA
full block available in blk*.dat
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< CTransactionRef > txn
std::vector< uint16_t > indexes
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
static constexpr SerParams V1_NETWORK
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V2_NETWORK
size_t BlockTxCount() const
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
unsigned int nTx
Number of transactions in this block.
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
An in-memory indexed chain of blocks.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const Consensus::Params & GetConsensus() const
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool GetTryNewOutboundPeer() const
void SetTryNewOutboundPeer(bool flag)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
bool DisconnectNode(const std::string &node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return all or many randomly selected addresses, optionally by network.
bool CheckIncomingNonce(uint64_t nonce)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, uint256 > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
const std::string m_addr_name
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
std::atomic< bool > m_bip152_highbandwidth_from
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
The basic transaction that is broadcasted on the network and contained in blocks.
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
const Txid & GetHash() const LIFETIMEBOUND
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
std::set< uint256 > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
CFeeRate GetMinFee(size_t sizelimit) const
CTransactionRef get(const uint256 &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
TxMempoolInfo info(const GenTxid >xid) const
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
bool exists(const GenTxid >xid) const
unsigned long size() const
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void BlockConnected(ChainstateRole role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void ActiveTipChange(const CBlockIndex &new_tip, bool is_ibd)
Notifies listeners any time the block chain tip changes, synchronously.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected Provides the block that was disconnected.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
const CBlockIndex * GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The tip of the background sync chain.
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
bool ProcessNewBlockHeaders(std::span< const CBlockHeader > headers, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const arith_uint256 & MinimumChainWork() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Double ended buffer combining vector and stream-like interfaces.
void ignore(size_t num_ignore)
uint64_t rand64() noexcept
Generate a random 64-bit integer.
A generic txid reference (txid or wtxid).
const uint256 & GetHash() const LIFETIMEBOUND
static GenTxid Txid(const uint256 &hash)
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< CTransactionRef > &extra_txn)
bool IsTxAvailable(size_t index) const
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
virtual std::optional< std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, DataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
virtual std::vector< TxOrphanage::OrphanTxBase > GetOrphanTransactions()=0
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
virtual void UnitTestMisbehaving(NodeId peer_id)=0
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests....
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
std::string ToString() const
256-bit unsigned big integer.
constexpr bool IsNull() const
std::string ToString() const
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool ReadRawBlock(std::vector< uint8_t > &block, const FlatFilePos &pos) const
bool LoadingBlocks() const
bool IsPruneMode() const
Whether running in -prune mode.
bool ReadBlock(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
Manages warning messages within a node.
std::string ToString() const
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
@ BLOCK_HEADER_LOW_WORK
the block header may be on a too-little-work chain
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ BLOCK_RESULT_UNSET
initial value. Block has not yet been rejected
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_MEMPOOL_POLICY
violated mempool's fee/size/descendant/RBF/etc limits
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_PREMATURE_SPEND
transaction spends a coinbase too early, or violates locktime/sequence locks
@ TX_INPUTS_NOT_STANDARD
inputs (covered by txid) failed policy rules
@ TX_WITNESS_STRIPPED
Transaction is missing a witness.
@ TX_CONFLICT
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
@ TX_WITNESS_MUTATED
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
@ TX_NO_MEMPOOL
this node does not have a mempool so can't validate the transaction
@ TX_RESULT_UNSET
initial value. Tx has not yet been rejected
@ TX_CONSENSUS
invalid by consensus rules
@ TX_RECONSIDERABLE
fails some policy, but might be acceptable if submitted in a (different) package
static size_t RecursiveDynamicUsage(const CScript &script)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
#define LogDebug(category,...)
Transaction validation functions.
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
Functions to serialize / deserialize common bitcoin types.
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
TRACEPOINT_SEMAPHORE(net, inbound_message)
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" command for wtxid-based relay starts with this version
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
std::chrono::seconds time_offset
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
@ DIFFERENT_WITNESS
Valid, transaction was already in the mempool.
@ INVALID
Fully validated, valid.
const std::list< CTransactionRef > m_replaced_transactions
Mempool transactions replaced by the tx.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
Validation result for package mempool acceptance.
PackageValidationState m_state
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
std::chrono::seconds median_outbound_time_offset
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
std::vector< NodeId > m_senders
std::string ToString() const
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
#define TRACEPOINT(context,...)
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
ReconciliationRegisterResult
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
constexpr int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...