73#include <initializer_list>
207 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
241 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
244 const bool m_is_inbound;
247 Mutex m_misbehavior_mutex;
249 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
252 Mutex m_block_inv_mutex;
256 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
260 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
272 std::atomic<int> m_starting_height{-1};
275 std::atomic<uint64_t> m_ping_nonce_sent{0};
277 std::atomic<std::chrono::microseconds> m_ping_start{0us};
279 std::atomic<bool> m_ping_queued{
false};
282 std::atomic<bool> m_wtxid_relay{
false};
294 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
296 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
307 std::set<Wtxid> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
311 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
314 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
317 uint64_t m_last_inv_sequence
GUARDED_BY(m_tx_inventory_mutex){1};
320 std::atomic<CAmount> m_fee_filter_received{0};
326 LOCK(m_tx_relay_mutex);
328 m_tx_relay = std::make_unique<Peer::TxRelay>();
329 return m_tx_relay.get();
334 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
363 std::atomic_bool m_addr_relay_enabled{
false};
367 mutable Mutex m_addr_send_times_mutex;
369 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
371 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
374 std::atomic_bool m_wants_addrv2{
false};
383 std::atomic<uint64_t> m_addr_rate_limited{0};
385 std::atomic<uint64_t> m_addr_processed{0};
391 Mutex m_getdata_requests_mutex;
393 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
399 Mutex m_headers_sync_mutex;
402 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
405 std::atomic<bool> m_sent_sendheaders{
false};
415 std::atomic<std::chrono::seconds> m_time_offset{0
s};
419 , m_our_services{our_services}
420 , m_is_inbound{is_inbound}
424 mutable Mutex m_tx_relay_mutex;
427 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
430using PeerRef = std::shared_ptr<Peer>;
442 uint256 hashLastUnknownBlock{};
448 bool fSyncStarted{
false};
450 std::chrono::microseconds m_stalling_since{0us};
451 std::list<QueuedBlock> vBlocksInFlight;
453 std::chrono::microseconds m_downloading_since{0us};
455 bool fPreferredDownload{
false};
457 bool m_requested_hb_cmpctblocks{
false};
459 bool m_provides_cmpctblocks{
false};
485 struct ChainSyncTimeoutState {
487 std::chrono::seconds m_timeout{0
s};
491 bool m_sent_getheaders{
false};
493 bool m_protect{
false};
496 ChainSyncTimeoutState m_chain_sync;
499 int64_t m_last_block_announcement{0};
528 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
542 void SetBestBlock(
int height,
std::chrono::seconds time)
override
544 m_best_height = height;
545 m_best_block_time = time;
549 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
550 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
574 void Misbehaving(Peer& peer,
const std::string& message);
585 bool via_compact_block,
const std::string& message =
"")
594 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
608 bool first_time_failure)
633 bool ProcessOrphanTx(Peer& peer)
643 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
645 bool via_compact_block)
657 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
676 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
690 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
705 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
707 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
714 template <
typename... Args>
715 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
721 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
727 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
770 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
773 std::atomic<int> m_best_height{-1};
775 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
783 const Options m_opts;
785 bool RejectIncomingTxs(
const CNode& peer)
const;
793 mutable Mutex m_peer_mutex;
800 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
810 uint32_t GetFetchFlags(
const Peer& peer)
const;
812 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
829 std::atomic<int> m_wtxid_relay_peers{0};
847 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
848 std::chrono::seconds average_interval,
853 Mutex m_most_recent_block_mutex;
854 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
855 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
857 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
861 Mutex m_headers_presync_mutex;
869 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
871 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
875 std::atomic_bool m_headers_presync_should_signal{
false};
945 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
951 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
956 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
981 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
983 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
995 int64_t ApproximateBestBlockDepth() const;
1005 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1023 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1025 const
uint256& stop_hash, uint32_t max_height_diff,
1073 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
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())
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,
1151 uint64_t network_key)
1153 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1154 auto& timer{it->second};
1156 timer = now + m_rng.rand_exp_duration(average_interval);
1161bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1163 return mapBlocksInFlight.contains(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) {
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()) {
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);
1403 if (state->pindexLastCommonBlock ==
nullptr ||
1404 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1405 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1406 state->pindexLastCommonBlock = fork_point;
1408 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1411 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1417 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1420void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1425 if (vBlocks.size() >=
count) {
1429 vBlocks.reserve(
count);
1432 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1449void 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)
1451 std::vector<const CBlockIndex*> vToFetch;
1452 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1453 bool is_limited_peer = IsLimitedPeer(peer);
1455 while (pindexWalk->
nHeight < nMaxHeight) {
1459 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1460 vToFetch.resize(nToFetch);
1461 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1462 vToFetch[nToFetch - 1] = pindexWalk;
1463 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1464 vToFetch[i - 1] = vToFetch[i]->
pprev;
1484 state->pindexLastCommonBlock = pindex;
1491 if (waitingfor == -1) {
1493 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1499 if (pindex->
nHeight > nWindowEnd) {
1501 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1503 if (nodeStaller) *nodeStaller = waitingfor;
1513 vBlocks.push_back(pindex);
1514 if (vBlocks.size() ==
count) {
1523void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1525 uint64_t my_services{peer.m_our_services};
1526 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1528 const int nNodeStartingHeight{m_best_height};
1535 const bool tx_relay{!RejectIncomingTxs(pnode)};
1542 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);
1548void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1552 if (state) state->m_last_block_announcement = time_in_seconds;
1560 m_node_states.try_emplace(m_node_states.end(), nodeid);
1562 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1568 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1571 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1575void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1579 for (
const auto& txid : unbroadcast_txids) {
1582 if (tx !=
nullptr) {
1583 RelayTransaction(txid, tx->GetWitnessHash());
1592 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1595void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1606 PeerRef peer = RemovePeer(nodeid);
1608 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1609 assert(m_wtxid_relay_peers >= 0);
1611 CNodeState *state =
State(nodeid);
1612 assert(state !=
nullptr);
1614 if (state->fSyncStarted)
1617 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1618 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1619 while (range.first != range.second) {
1620 auto [node_id, list_it] = range.first->second;
1621 if (node_id != nodeid) {
1624 range.first = mapBlocksInFlight.erase(range.first);
1629 LOCK(m_tx_download_mutex);
1630 m_txdownloadman.DisconnectedPeer(nodeid);
1632 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1633 m_num_preferred_download_peers -= state->fPreferredDownload;
1634 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1635 assert(m_peers_downloading_from >= 0);
1636 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1637 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1639 m_node_states.erase(nodeid);
1641 if (m_node_states.empty()) {
1643 assert(mapBlocksInFlight.empty());
1644 assert(m_num_preferred_download_peers == 0);
1645 assert(m_peers_downloading_from == 0);
1646 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1647 assert(m_wtxid_relay_peers == 0);
1648 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1651 if (
node.fSuccessfullyConnected &&
1652 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1659 LOCK(m_headers_presync_mutex);
1660 m_headers_presync_stats.erase(nodeid);
1665bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1668 return !(GetDesirableServiceFlags(services) & (~services));
1682PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1685 auto it = m_peer_map.find(
id);
1686 return it != m_peer_map.end() ? it->second :
nullptr;
1689PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1693 auto it = m_peer_map.find(
id);
1694 if (it != m_peer_map.end()) {
1695 ret = std::move(it->second);
1696 m_peer_map.erase(it);
1705 const CNodeState* state =
State(nodeid);
1706 if (state ==
nullptr)
1708 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1709 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1710 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1716 PeerRef peer = GetPeerRef(nodeid);
1717 if (peer ==
nullptr)
return false;
1726 auto ping_wait{0us};
1727 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1728 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1731 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1734 LOCK(tx_relay->m_tx_inventory_mutex);
1736 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1748 LOCK(peer->m_headers_sync_mutex);
1749 if (peer->m_headers_sync) {
1758std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1760 LOCK(m_tx_download_mutex);
1761 return m_txdownloadman.GetOrphanTransactions();
1768 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1772void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1774 if (m_opts.max_extra_txs <= 0)
1776 if (!vExtraTxnForCompact.size())
1777 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1778 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1779 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1782void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1784 LOCK(peer.m_misbehavior_mutex);
1786 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1787 peer.m_should_discourage =
true;
1796 bool via_compact_block,
const std::string& message)
1798 PeerRef peer{GetPeerRef(nodeid)};
1809 if (!via_compact_block) {
1810 if (peer) Misbehaving(*peer, message);
1818 if (peer && !via_compact_block && !peer->m_is_inbound) {
1819 if (peer) Misbehaving(*peer, message);
1826 if (peer) Misbehaving(*peer, message);
1830 if (peer) Misbehaving(*peer, message);
1835 if (message !=
"") {
1840bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1854 PeerRef peer = GetPeerRef(peer_id);
1863 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1866 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
1889 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1895 : m_rng{opts.deterministic_rng},
1897 m_chainparams(chainman.GetParams()),
1901 m_chainman(chainman),
1903 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
1904 m_warnings{warnings},
1909 if (opts.reconcile_txs) {
1914void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1925 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1928void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
1936 LOCK(m_tx_download_mutex);
1940 m_txdownloadman.ActiveTipChange();
1950void PeerManagerImpl::BlockConnected(
1952 const std::shared_ptr<const CBlock>& pblock,
1957 m_last_tip_update = GetTime<std::chrono::seconds>();
1960 auto stalling_timeout = m_block_stalling_timeout.load();
1964 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1974 LOCK(m_tx_download_mutex);
1975 m_txdownloadman.BlockConnected(pblock);
1978void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1980 LOCK(m_tx_download_mutex);
1981 m_txdownloadman.BlockDisconnected();
1988void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1990 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
1994 if (pindex->
nHeight <= m_highest_fast_announce)
1996 m_highest_fast_announce = pindex->
nHeight;
2000 uint256 hashBlock(pblock->GetHash());
2001 const std::shared_future<CSerializedNetMsg> lazy_ser{
2005 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2006 for (
const auto& tx : pblock->vtx) {
2007 most_recent_block_txs->emplace(tx->GetHash(), tx);
2008 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2011 LOCK(m_most_recent_block_mutex);
2012 m_most_recent_block_hash = hashBlock;
2013 m_most_recent_block = pblock;
2014 m_most_recent_compact_block = pcmpctblock;
2015 m_most_recent_block_txs = std::move(most_recent_block_txs);
2023 ProcessBlockAvailability(pnode->
GetId());
2027 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2029 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2030 hashBlock.ToString(), pnode->
GetId());
2033 PushMessage(*pnode, ser_cmpctblock.Copy());
2034 state.pindexBestHeaderSent = pindex;
2043void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2045 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2048 if (fInitialDownload)
return;
2051 std::vector<uint256> vHashes;
2053 while (pindexToAnnounce != pindexFork) {
2055 pindexToAnnounce = pindexToAnnounce->
pprev;
2065 for (
auto& it : m_peer_map) {
2066 Peer& peer = *it.second;
2067 LOCK(peer.m_block_inv_mutex);
2068 for (
const uint256& hash : vHashes | std::views::reverse) {
2069 peer.m_blocks_for_headers_relay.push_back(hash);
2081void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2085 const uint256 hash(block->GetHash());
2086 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2091 it != mapBlockSource.end() &&
2092 State(it->second.first)) {
2093 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2103 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2104 if (it != mapBlockSource.end()) {
2105 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2108 if (it != mapBlockSource.end())
2109 mapBlockSource.erase(it);
2117bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2122void PeerManagerImpl::SendPings()
2125 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2128void PeerManagerImpl::RelayTransaction(
const Txid& txid,
const Wtxid& wtxid)
2131 for(
auto& it : m_peer_map) {
2132 Peer& peer = *it.second;
2133 auto tx_relay = peer.GetTxRelay();
2134 if (!tx_relay)
continue;
2136 LOCK(tx_relay->m_tx_inventory_mutex);
2142 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2145 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2146 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2151void PeerManagerImpl::RelayAddress(
NodeId originator,
2167 const auto current_time{GetTime<std::chrono::seconds>()};
2175 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2177 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2178 assert(nRelayNodes <= best.size());
2182 for (
auto& [
id, peer] : m_peer_map) {
2183 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2185 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2186 if (hashKey > best[i].first) {
2187 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2188 best[i] = std::make_pair(hashKey, peer.get());
2195 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2196 PushAddress(*best[i].second, addr);
2200void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2202 std::shared_ptr<const CBlock> a_recent_block;
2203 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2205 LOCK(m_most_recent_block_mutex);
2206 a_recent_block = m_most_recent_block;
2207 a_recent_compact_block = m_most_recent_compact_block;
2210 bool need_activate_chain =
false;
2222 need_activate_chain =
true;
2226 if (need_activate_chain) {
2228 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2235 bool can_direct_fetch{
false};
2243 if (!BlockRequestAllowed(pindex)) {
2244 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2271 can_direct_fetch = CanDirectFetch();
2275 std::shared_ptr<const CBlock> pblock;
2276 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2277 pblock = a_recent_block;
2295 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2305 pblock = pblockRead;
2313 bool sendMerkleBlock =
false;
2315 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2316 LOCK(tx_relay->m_bloom_filter_mutex);
2317 if (tx_relay->m_bloom_filter) {
2318 sendMerkleBlock =
true;
2319 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2322 if (sendMerkleBlock) {
2330 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2341 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2354 LOCK(peer.m_block_inv_mutex);
2356 if (inv.
hash == peer.m_continuation_block) {
2360 std::vector<CInv> vInv;
2361 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2363 peer.m_continuation_block.SetNull();
2371 auto txinfo{std::visit(
2372 [&](
const auto&
id) {
2373 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2377 return std::move(txinfo.tx);
2382 LOCK(m_most_recent_block_mutex);
2383 if (m_most_recent_block_txs !=
nullptr) {
2384 auto it = m_most_recent_block_txs->find(gtxid);
2385 if (it != m_most_recent_block_txs->end())
return it->second;
2392void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2396 auto tx_relay = peer.GetTxRelay();
2398 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2399 std::vector<CInv> vNotFound;
2404 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2405 if (interruptMsgProc)
return;
2410 const CInv &inv = *it++;
2412 if (tx_relay ==
nullptr) {
2418 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2421 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2424 vNotFound.push_back(inv);
2430 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2431 const CInv &inv = *it++;
2433 ProcessGetBlockData(pfrom, peer, inv);
2442 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2444 if (!vNotFound.empty()) {
2463uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2465 uint32_t nFetchFlags = 0;
2466 if (CanServeWitnesses(peer)) {
2475 unsigned int tx_requested_size = 0;
2476 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2478 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2482 tx_requested_size += resp.txn[i]->GetTotalSize();
2489bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2493 Misbehaving(peer,
"header with invalid proof of work");
2498 if (!CheckHeadersAreContinuous(headers)) {
2499 Misbehaving(peer,
"non-continuous headers sequence");
2524void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2525 const std::vector<CBlockHeader>& headers)
2529 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2530 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2532 headers[0].hashPrevBlock.ToString(),
2533 best_header->nHeight,
2543bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2547 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2550 hashLastBlock = header.GetHash();
2555bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2557 if (peer.m_headers_sync) {
2558 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2560 if (result.success) peer.m_last_getheaders_timestamp = {};
2561 if (result.request_more) {
2562 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2564 Assume(!locator.vHave.empty());
2567 if (!locator.vHave.empty()) {
2570 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2573 locator.vHave.front().ToString(), pfrom.
GetId());
2578 peer.m_headers_sync.reset(
nullptr);
2583 LOCK(m_headers_presync_mutex);
2584 m_headers_presync_stats.erase(pfrom.
GetId());
2587 HeadersPresyncStats stats;
2588 stats.first = peer.m_headers_sync->GetPresyncWork();
2590 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2591 peer.m_headers_sync->GetPresyncTime()};
2595 LOCK(m_headers_presync_mutex);
2596 m_headers_presync_stats[pfrom.
GetId()] = stats;
2597 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2598 bool best_updated =
false;
2599 if (best_it == m_headers_presync_stats.end()) {
2603 const HeadersPresyncStats* stat_best{
nullptr};
2604 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2605 if (!stat_best || stat > *stat_best) {
2610 m_headers_presync_bestpeer = peer_best;
2611 best_updated = (peer_best == pfrom.
GetId());
2612 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2614 m_headers_presync_bestpeer = pfrom.
GetId();
2615 best_updated =
true;
2617 if (best_updated && stats.second.has_value()) {
2619 m_headers_presync_should_signal =
true;
2623 if (result.success) {
2626 headers.swap(result.pow_validated_headers);
2629 return result.success;
2637bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2644 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2648 if (total_work < minimum_chain_work) {
2652 if (headers.size() == m_opts.max_headers_result) {
2662 LOCK(peer.m_headers_sync_mutex);
2664 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2669 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2683bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2685 if (header ==
nullptr) {
2687 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2695bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2703 peer.m_last_getheaders_timestamp = current_time;
2714void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2717 CNodeState *nodestate =
State(pfrom.
GetId());
2720 std::vector<const CBlockIndex*> vToFetch;
2728 vToFetch.push_back(pindexWalk);
2730 pindexWalk = pindexWalk->
pprev;
2741 std::vector<CInv> vGetData;
2743 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2748 uint32_t nFetchFlags = GetFetchFlags(peer);
2750 BlockRequested(pfrom.
GetId(), *pindex);
2754 if (vGetData.size() > 1) {
2759 if (vGetData.size() > 0) {
2760 if (!m_opts.ignore_incoming_txs &&
2761 nodestate->m_provides_cmpctblocks &&
2762 vGetData.size() == 1 &&
2763 mapBlocksInFlight.size() == 1 &&
2779void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2780 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2783 CNodeState *nodestate =
State(pfrom.
GetId());
2792 nodestate->m_last_block_announcement =
GetTime();
2800 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2822 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) {
2824 nodestate->m_chain_sync.m_protect =
true;
2825 ++m_outbound_peers_with_protect_from_disconnect;
2830void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2831 std::vector<CBlockHeader>&& headers,
2832 bool via_compact_block)
2834 size_t nCount = headers.size();
2841 LOCK(peer.m_headers_sync_mutex);
2842 if (peer.m_headers_sync) {
2843 peer.m_headers_sync.reset(
nullptr);
2844 LOCK(m_headers_presync_mutex);
2845 m_headers_presync_stats.erase(pfrom.
GetId());
2849 peer.m_last_getheaders_timestamp = {};
2857 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2872 bool already_validated_work =
false;
2875 bool have_headers_sync =
false;
2877 LOCK(peer.m_headers_sync_mutex);
2879 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2891 if (headers.empty()) {
2895 have_headers_sync = !!peer.m_headers_sync;
2900 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2902 if (!headers_connect_blockindex) {
2906 HandleUnconnectingHeaders(pfrom, peer, headers);
2913 peer.m_last_getheaders_timestamp = {};
2923 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2924 already_validated_work =
true;
2932 already_validated_work =
true;
2938 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2939 chain_start_header, headers)) {
2951 bool received_new_header{last_received_header ==
nullptr};
2957 state, &pindexLast)};
2963 "If this happens with all peers, consider database corruption (that -reindex may fix) "
2964 "or a potential consensus incompatibility.",
2967 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2973 if (processed && received_new_header) {
2974 LogBlockHeader(*pindexLast, pfrom,
false);
2978 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
2980 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2982 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2986 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
2989 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
2995 bool first_time_failure)
3001 PeerRef peer{GetPeerRef(nodeid)};
3004 ptx->GetHash().ToString(),
3005 ptx->GetWitnessHash().ToString(),
3009 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3012 AddToCompactExtraTransactions(ptx);
3014 for (
const Txid& parent_txid : unique_parents) {
3015 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3018 return package_to_validate;
3021void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3027 m_txdownloadman.MempoolAcceptedTx(tx);
3031 tx->GetHash().ToString(),
3032 tx->GetWitnessHash().ToString(),
3035 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3038 AddToCompactExtraTransactions(removedTx);
3048 const auto&
package = package_to_validate.m_txns;
3049 const auto& senders = package_to_validate.
m_senders;
3052 m_txdownloadman.MempoolRejectedPackage(package);
3055 if (!
Assume(package.size() == 2))
return;
3059 auto package_iter = package.rbegin();
3060 auto senders_iter = senders.rbegin();
3061 while (package_iter != package.rend()) {
3062 const auto& tx = *package_iter;
3063 const NodeId nodeid = *senders_iter;
3064 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3068 const auto& tx_result = it_result->second;
3069 switch (tx_result.m_result_type) {
3072 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3082 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3100bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3107 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3110 const Txid& orphanHash = porphanTx->GetHash();
3111 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3128 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3137bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3139 const uint256& stop_hash, uint32_t max_height_diff,
3143 const bool supported_filter_type =
3146 if (!supported_filter_type) {
3148 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg(
fLogIPs));
3149 node.fDisconnect =
true;
3158 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3161 node.fDisconnect =
true;
3166 uint32_t stop_height = stop_index->
nHeight;
3167 if (start_height > stop_height) {
3169 "start height %d and stop height %d, %s\n",
3170 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3171 node.fDisconnect =
true;
3174 if (stop_height - start_height >= max_height_diff) {
3176 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3177 node.fDisconnect =
true;
3182 if (!filter_index) {
3192 uint8_t filter_type_ser;
3193 uint32_t start_height;
3196 vRecv >> filter_type_ser >> start_height >> stop_hash;
3202 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3207 std::vector<BlockFilter> filters;
3209 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3214 for (
const auto& filter : filters) {
3221 uint8_t filter_type_ser;
3222 uint32_t start_height;
3225 vRecv >> filter_type_ser >> start_height >> stop_hash;
3231 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3237 if (start_height > 0) {
3239 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3241 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3247 std::vector<uint256> filter_hashes;
3249 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3263 uint8_t filter_type_ser;
3266 vRecv >> filter_type_ser >> stop_hash;
3272 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3273 std::numeric_limits<uint32_t>::max(),
3274 stop_index, filter_index)) {
3282 for (
int i = headers.size() - 1; i >= 0; i--) {
3287 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3301 bool new_block{
false};
3302 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3304 node.m_last_block_time = GetTime<std::chrono::seconds>();
3309 RemoveBlockRequest(block->GetHash(), std::nullopt);
3312 mapBlockSource.erase(block->GetHash());
3316void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3318 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3319 bool fBlockRead{
false};
3323 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3324 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3325 bool requested_block_from_this_peer{
false};
3328 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3330 while (range_flight.first != range_flight.second) {
3331 auto [node_id, block_it] = range_flight.first->second;
3332 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3333 requested_block_from_this_peer =
true;
3336 range_flight.first++;
3339 if (!requested_block_from_this_peer) {
3351 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3362 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3365 if (first_in_flight) {
3370 std::vector<CInv> invs;
3375 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3388 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3403void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3415 "Saw new %sheader hash=%s height=%d peer=%d%s",
3416 via_compact_block ?
"cmpctblock " :
"",
3429void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3430 const std::chrono::microseconds time_received,
3431 const std::atomic<bool>& interruptMsgProc)
3437 PeerRef peer = GetPeerRef(pfrom.
GetId());
3438 if (peer ==
nullptr)
return;
3448 uint64_t nNonce = 1;
3451 std::string cleanSubVer;
3452 int starting_height = -1;
3455 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3470 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3472 GetDesirableServiceFlags(nServices),
3485 if (!vRecv.
empty()) {
3493 if (!vRecv.
empty()) {
3494 std::string strSubVer;
3498 if (!vRecv.
empty()) {
3499 vRecv >> starting_height;
3519 PushNodeVersion(pfrom, *peer);
3532 if (greatest_common_version >= 70016) {
3541 peer->m_their_services = nServices;
3545 pfrom.cleanSubVer = cleanSubVer;
3547 peer->m_starting_height = starting_height;
3557 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3558 auto*
const tx_relay = peer->SetTxRelay();
3560 LOCK(tx_relay->m_bloom_filter_mutex);
3561 tx_relay->m_relay_txs = fRelay;
3573 const auto* tx_relay = peer->GetTxRelay();
3574 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3576 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3589 m_num_preferred_download_peers += state->fPreferredDownload;
3595 bool send_getaddr{
false};
3597 send_getaddr = SetupAddressRelay(pfrom, *peer);
3607 peer->m_getaddr_sent =
true;
3632 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3637 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3641 m_outbound_time_offsets.Add(peer->m_time_offset);
3642 m_outbound_time_offsets.WarnIfOutOfSync();
3646 if (greatest_common_version <= 70012) {
3647 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3648 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3671 auto new_peer_msg = [&]() {
3673 return strprintf(
"New %s peer connected: transport: %s, version: %d, blocks=%d peer=%d%s%s\n",
3676 pfrom.
nVersion.load(), peer->m_starting_height,
3678 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3686 LogInfo(
"%s", new_peer_msg());
3698 if (m_txreconciliation) {
3699 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3703 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3707 if (
auto tx_relay = peer->GetTxRelay()) {
3716 tx_relay->m_tx_inventory_mutex,
3717 return tx_relay->m_tx_inventory_to_send.empty() &&
3718 tx_relay->m_next_inv_send_time == 0
s));
3723 const CNodeState* state =
State(pfrom.
GetId());
3725 .m_preferred = state->fPreferredDownload,
3726 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3727 .m_wtxid_relay = peer->m_wtxid_relay,
3736 peer->m_prefers_headers =
true;
3741 bool sendcmpct_hb{
false};
3742 uint64_t sendcmpct_version{0};
3743 vRecv >> sendcmpct_hb >> sendcmpct_version;
3749 CNodeState* nodestate =
State(pfrom.
GetId());
3750 nodestate->m_provides_cmpctblocks =
true;
3751 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3768 if (!peer->m_wtxid_relay) {
3769 peer->m_wtxid_relay =
true;
3770 m_wtxid_relay_peers++;
3789 peer->m_wants_addrv2 =
true;
3797 if (!m_txreconciliation) {
3798 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3809 if (RejectIncomingTxs(pfrom)) {
3818 const auto* tx_relay = peer->GetTxRelay();
3819 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3825 uint32_t peer_txreconcl_version;
3826 uint64_t remote_salt;
3827 vRecv >> peer_txreconcl_version >> remote_salt;
3830 peer_txreconcl_version, remote_salt);
3855 const auto ser_params{
3863 std::vector<CAddress> vAddr;
3865 vRecv >> ser_params(vAddr);
3867 if (!SetupAddressRelay(pfrom, *peer)) {
3874 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3879 std::vector<CAddress> vAddrOk;
3880 const auto current_a_time{Now<NodeSeconds>()};
3883 const auto current_time{GetTime<std::chrono::microseconds>()};
3886 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3890 peer->m_addr_token_timestamp = current_time;
3893 uint64_t num_proc = 0;
3894 uint64_t num_rate_limit = 0;
3895 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
3898 if (interruptMsgProc)
3902 if (peer->m_addr_token_bucket < 1.0) {
3908 peer->m_addr_token_bucket -= 1.0;
3917 addr.
nTime = current_a_time - 5 * 24h;
3919 AddAddressKnown(*peer, addr);
3926 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3928 RelayAddress(pfrom.
GetId(), addr, reachable);
3932 vAddrOk.push_back(addr);
3935 peer->m_addr_processed += num_proc;
3936 peer->m_addr_rate_limited += num_rate_limit;
3937 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3938 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3940 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3941 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3952 std::vector<CInv> vInv;
3956 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
3960 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3964 const auto current_time{GetTime<std::chrono::microseconds>()};
3967 for (
CInv& inv : vInv) {
3968 if (interruptMsgProc)
return;
3973 if (peer->m_wtxid_relay) {
3980 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3983 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3991 best_block = &inv.
hash;
3994 if (reject_tx_invs) {
4000 AddKnownTx(*peer, inv.
hash);
4003 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4011 if (best_block !=
nullptr) {
4023 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4024 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
4026 m_chainman.m_best_header->nHeight, best_block->ToString(),
4029 if (!state.fSyncStarted) {
4030 peer->m_inv_triggered_getheaders_before_sync =
true;
4034 m_last_block_inv_triggering_headers_sync = *best_block;
4043 std::vector<CInv> vInv;
4047 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
4053 if (vInv.size() > 0) {
4058 LOCK(peer->m_getdata_requests_mutex);
4059 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
4060 ProcessGetData(pfrom, *peer, interruptMsgProc);
4069 vRecv >> locator >> hashStop;
4085 std::shared_ptr<const CBlock> a_recent_block;
4087 LOCK(m_most_recent_block_mutex);
4088 a_recent_block = m_most_recent_block;
4091 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4106 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4121 if (--nLimit <= 0) {
4125 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4137 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4141 std::shared_ptr<const CBlock> recent_block;
4143 LOCK(m_most_recent_block_mutex);
4144 if (m_most_recent_block_hash == req.
blockhash)
4145 recent_block = m_most_recent_block;
4149 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4168 if (!block_pos.IsNull()) {
4175 SendBlockTransactions(pfrom, *peer, block, req);
4188 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4196 vRecv >> locator >> hashStop;
4214 if (m_chainman.
ActiveTip() ==
nullptr ||
4216 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4223 CNodeState *nodestate =
State(pfrom.
GetId());
4233 if (!BlockRequestAllowed(pindex)) {
4234 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4247 std::vector<CBlock> vHeaders;
4248 int nLimit = m_opts.max_headers_result;
4250 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4253 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4268 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4274 if (RejectIncomingTxs(pfrom)) {
4288 const Txid& txid = ptx->GetHash();
4289 const Wtxid& wtxid = ptx->GetWitnessHash();
4292 AddKnownTx(*peer, hash);
4296 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4297 if (!should_validate) {
4302 if (!m_mempool.
exists(txid)) {
4303 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4306 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4308 RelayTransaction(txid, wtxid);
4312 if (package_to_validate) {
4315 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4316 ProcessPackageResult(package_to_validate.value(), package_result);
4322 Assume(!package_to_validate.has_value());
4332 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4335 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4336 ProcessPackageResult(package_to_validate.value(), package_result);
4352 vRecv >> cmpctblock;
4354 bool received_new_header =
false;
4364 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4374 received_new_header =
true;
4382 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4389 if (received_new_header) {
4390 LogBlockHeader(*pindex, pfrom,
true);
4393 bool fProcessBLOCKTXN =
false;
4397 bool fRevertToHeaderProcessing =
false;
4401 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4402 bool fBlockReconstructed =
false;
4408 CNodeState *nodestate =
State(pfrom.
GetId());
4413 nodestate->m_last_block_announcement =
GetTime();
4419 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4420 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4421 bool requested_block_from_this_peer{
false};
4424 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4426 while (range_flight.first != range_flight.second) {
4427 if (range_flight.first->second.first == pfrom.
GetId()) {
4428 requested_block_from_this_peer =
true;
4431 range_flight.first++;
4436 if (requested_block_from_this_peer) {
4439 std::vector<CInv> vInv(1);
4440 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4447 if (!already_in_flight && !CanDirectFetch()) {
4455 requested_block_from_this_peer) {
4456 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4457 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4458 if (!(*queuedBlockIt)->partialBlock)
4471 Misbehaving(*peer,
"invalid compact block");
4474 if (first_in_flight) {
4476 std::vector<CInv> vInv(1);
4477 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4487 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4492 fProcessBLOCKTXN =
true;
4493 }
else if (first_in_flight) {
4500 IsBlockRequestedFromOutbound(blockhash) ||
4519 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4524 std::vector<CTransactionRef> dummy;
4526 status = tempBlock.FillBlock(*pblock, dummy,
4529 fBlockReconstructed =
true;
4533 if (requested_block_from_this_peer) {
4536 std::vector<CInv> vInv(1);
4537 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4542 fRevertToHeaderProcessing =
true;
4547 if (fProcessBLOCKTXN) {
4550 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4553 if (fRevertToHeaderProcessing) {
4559 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4562 if (fBlockReconstructed) {
4567 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4585 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4602 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4613 std::vector<CBlockHeader> headers;
4617 if (nCount > m_opts.max_headers_result) {
4618 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4621 headers.resize(nCount);
4622 for (
unsigned int n = 0; n < nCount; n++) {
4623 vRecv >> headers[n];
4627 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4631 if (m_headers_presync_should_signal.exchange(
false)) {
4632 HeadersPresyncStats stats;
4634 LOCK(m_headers_presync_mutex);
4635 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4636 if (it != m_headers_presync_stats.end()) stats = it->second;
4654 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4665 Misbehaving(*peer,
"mutated block");
4670 bool forceProcessing =
false;
4671 const uint256 hash(pblock->GetHash());
4672 bool min_pow_checked =
false;
4677 forceProcessing = IsBlockRequested(hash);
4678 RemoveBlockRequest(hash, pfrom.
GetId());
4682 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4686 min_pow_checked =
true;
4689 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4706 Assume(SetupAddressRelay(pfrom, *peer));
4710 if (peer->m_getaddr_recvd) {
4714 peer->m_getaddr_recvd =
true;
4716 peer->m_addrs_to_send.clear();
4717 std::vector<CAddress> vAddr;
4723 for (
const CAddress &addr : vAddr) {
4724 PushAddress(*peer, addr);
4752 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4753 LOCK(tx_relay->m_tx_inventory_mutex);
4754 tx_relay->m_send_mempool =
true;
4780 const auto ping_end = time_received;
4783 bool bPingFinished =
false;
4784 std::string sProblem;
4786 if (nAvail >=
sizeof(
nonce)) {
4790 if (peer->m_ping_nonce_sent != 0) {
4791 if (
nonce == peer->m_ping_nonce_sent) {
4793 bPingFinished =
true;
4794 const auto ping_time = ping_end - peer->m_ping_start.load();
4795 if (ping_time.count() >= 0) {
4800 sProblem =
"Timing mishap";
4804 sProblem =
"Nonce mismatch";
4807 bPingFinished =
true;
4808 sProblem =
"Nonce zero";
4812 sProblem =
"Unsolicited pong without ping";
4816 bPingFinished =
true;
4817 sProblem =
"Short payload";
4820 if (!(sProblem.empty())) {
4824 peer->m_ping_nonce_sent,
4828 if (bPingFinished) {
4829 peer->m_ping_nonce_sent = 0;
4846 Misbehaving(*peer,
"too-large bloom filter");
4847 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4849 LOCK(tx_relay->m_bloom_filter_mutex);
4850 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4851 tx_relay->m_relay_txs =
true;
4865 std::vector<unsigned char> vData;
4873 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4874 LOCK(tx_relay->m_bloom_filter_mutex);
4875 if (tx_relay->m_bloom_filter) {
4876 tx_relay->m_bloom_filter->insert(vData);
4882 Misbehaving(*peer,
"bad filteradd message");
4893 auto tx_relay = peer->GetTxRelay();
4894 if (!tx_relay)
return;
4897 LOCK(tx_relay->m_bloom_filter_mutex);
4898 tx_relay->m_bloom_filter =
nullptr;
4899 tx_relay->m_relay_txs =
true;
4908 vRecv >> newFeeFilter;
4910 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4911 tx_relay->m_fee_filter_received = newFeeFilter;
4919 ProcessGetCFilters(pfrom, *peer, vRecv);
4924 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4929 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4934 std::vector<CInv> vInv;
4936 std::vector<GenTxid> tx_invs;
4938 for (
CInv &inv : vInv) {
4944 LOCK(m_tx_download_mutex);
4945 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
4954bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4957 LOCK(peer.m_misbehavior_mutex);
4960 if (!peer.m_should_discourage)
return false;
4962 peer.m_should_discourage =
false;
4967 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
4973 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
4993bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4998 PeerRef peer = GetPeerRef(pfrom->
GetId());
4999 if (peer ==
nullptr)
return false;
5003 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
5006 LOCK(peer->m_getdata_requests_mutex);
5007 if (!peer->m_getdata_requests.empty()) {
5008 ProcessGetData(*pfrom, *peer, interruptMsgProc);
5012 const bool processed_orphan = ProcessOrphanTx(*peer);
5017 if (processed_orphan)
return true;
5022 LOCK(peer->m_getdata_requests_mutex);
5023 if (!peer->m_getdata_requests.empty())
return true;
5036 bool fMoreWork = poll_result->second;
5047 if (m_opts.capture_messages) {
5052 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5053 if (interruptMsgProc)
return false;
5055 LOCK(peer->m_getdata_requests_mutex);
5056 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5063 LOCK(m_tx_download_mutex);
5064 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
5065 }
catch (
const std::exception& e) {
5074void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5087 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5089 if (state.m_chain_sync.m_timeout != 0
s) {
5090 state.m_chain_sync.m_timeout = 0
s;
5091 state.m_chain_sync.m_work_header =
nullptr;
5092 state.m_chain_sync.m_sent_getheaders =
false;
5094 }
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)) {
5102 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5103 state.m_chain_sync.m_sent_getheaders =
false;
5104 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5108 if (state.m_chain_sync.m_sent_getheaders) {
5110 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5113 assert(state.m_chain_sync.m_work_header);
5118 MaybeSendGetHeaders(pto,
5119 GetLocator(state.m_chain_sync.m_work_header->pprev),
5121 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());
5122 state.m_chain_sync.m_sent_getheaders =
true;
5134void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5143 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5147 if (pnode->
GetId() > youngest_peer.first) {
5148 next_youngest_peer = youngest_peer;
5149 youngest_peer.first = pnode->GetId();
5150 youngest_peer.second = pnode->m_last_block_time;
5153 NodeId to_disconnect = youngest_peer.first;
5154 if (youngest_peer.second > next_youngest_peer.second) {
5157 to_disconnect = next_youngest_peer.first;
5166 CNodeState *node_state =
State(pnode->
GetId());
5167 if (node_state ==
nullptr ||
5170 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5174 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5190 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5193 AssertLockHeld(::cs_main);
5197 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5198 CNodeState *state = State(pnode->GetId());
5199 if (state == nullptr) return;
5201 if (state->m_chain_sync.m_protect) return;
5204 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5205 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5206 worst_peer = pnode->GetId();
5207 oldest_block_announcement = state->m_last_block_announcement;
5210 if (worst_peer != -1) {
5221 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5225 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5242void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5246 auto now{GetTime<std::chrono::seconds>()};
5248 EvictExtraOutboundPeers(now);
5250 if (now > m_stale_tip_check_time) {
5254 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5263 if (!m_initial_sync_finished && CanDirectFetch()) {
5265 m_initial_sync_finished =
true;
5269void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5272 peer.m_ping_nonce_sent &&
5282 bool pingSend =
false;
5284 if (peer.m_ping_queued) {
5289 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5298 }
while (
nonce == 0);
5299 peer.m_ping_queued =
false;
5300 peer.m_ping_start = now;
5302 peer.m_ping_nonce_sent =
nonce;
5306 peer.m_ping_nonce_sent = 0;
5312void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5315 if (!peer.m_addr_relay_enabled)
return;
5317 LOCK(peer.m_addr_send_times_mutex);
5320 peer.m_next_local_addr_send < current_time) {
5327 if (peer.m_next_local_addr_send != 0us) {
5328 peer.m_addr_known->reset();
5331 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5332 PushAddress(peer, local_addr);
5338 if (current_time <= peer.m_next_addr_send)
return;
5351 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5352 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5355 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5356 peer.m_addrs_to_send.end());
5359 if (peer.m_addrs_to_send.empty())
return;
5361 if (peer.m_wants_addrv2) {
5366 peer.m_addrs_to_send.clear();
5369 if (peer.m_addrs_to_send.capacity() > 40) {
5370 peer.m_addrs_to_send.shrink_to_fit();
5374void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5382 CNodeState &state = *
State(
node.GetId());
5383 if (state.pindexBestKnownBlock !=
nullptr &&
5390 peer.m_sent_sendheaders =
true;
5395void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5397 if (m_opts.ignore_incoming_txs)
return;
5413 if (peer.m_fee_filter_sent == MAX_FILTER) {
5416 peer.m_next_send_feefilter = 0us;
5419 if (current_time > peer.m_next_send_feefilter) {
5420 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5423 if (filterToSend != peer.m_fee_filter_sent) {
5425 peer.m_fee_filter_sent = filterToSend;
5432 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5438class CompareInvMempoolOrder
5442 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5444 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5453bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5463bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5468 if (
node.IsBlockOnlyConn())
return false;
5470 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5474 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5480bool PeerManagerImpl::SendMessages(
CNode* pto)
5485 PeerRef peer = GetPeerRef(pto->
GetId());
5486 if (!peer)
return false;
5491 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5494 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5495 PushNodeVersion(*pto, *peer);
5496 peer->m_outbound_version_message_sent =
true;
5503 const auto current_time{GetTime<std::chrono::microseconds>()};
5511 MaybeSendPing(*pto, *peer, current_time);
5516 MaybeSendAddr(*pto, *peer, current_time);
5518 MaybeSendSendHeaders(*pto, *peer);
5526 if (m_chainman.m_best_header ==
nullptr) {
5533 bool sync_blocks_and_headers_from_peer =
false;
5534 if (state.fPreferredDownload) {
5535 sync_blocks_and_headers_from_peer =
true;
5546 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5547 sync_blocks_and_headers_from_peer =
true;
5553 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5554 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5562 if (pindexStart->
pprev)
5563 pindexStart = pindexStart->
pprev;
5564 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5567 state.fSyncStarted =
true;
5591 LOCK(peer->m_block_inv_mutex);
5592 std::vector<CBlock> vHeaders;
5593 bool fRevertToInv = ((!peer->m_prefers_headers &&
5594 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5597 ProcessBlockAvailability(pto->
GetId());
5599 if (!fRevertToInv) {
5600 bool fFoundStartingHeader =
false;
5604 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5609 fRevertToInv =
true;
5612 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5624 fRevertToInv =
true;
5627 pBestIndex = pindex;
5628 if (fFoundStartingHeader) {
5631 }
else if (PeerHasHeader(&state, pindex)) {
5633 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5636 fFoundStartingHeader =
true;
5641 fRevertToInv =
true;
5646 if (!fRevertToInv && !vHeaders.empty()) {
5647 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5651 vHeaders.front().GetHash().ToString(), pto->
GetId());
5653 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5655 LOCK(m_most_recent_block_mutex);
5656 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5660 if (cached_cmpctblock_msg.has_value()) {
5661 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5669 state.pindexBestHeaderSent = pBestIndex;
5670 }
else if (peer->m_prefers_headers) {
5671 if (vHeaders.size() > 1) {
5674 vHeaders.front().GetHash().ToString(),
5675 vHeaders.back().GetHash().ToString(), pto->
GetId());
5678 vHeaders.front().GetHash().ToString(), pto->
GetId());
5681 state.pindexBestHeaderSent = pBestIndex;
5683 fRevertToInv =
true;
5689 if (!peer->m_blocks_for_headers_relay.empty()) {
5690 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5703 if (!PeerHasHeader(&state, pindex)) {
5704 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5710 peer->m_blocks_for_headers_relay.clear();
5716 std::vector<CInv> vInv;
5718 LOCK(peer->m_block_inv_mutex);
5722 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5729 peer->m_blocks_for_inv_relay.clear();
5732 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5733 LOCK(tx_relay->m_tx_inventory_mutex);
5736 if (tx_relay->m_next_inv_send_time < current_time) {
5737 fSendTrickle =
true;
5747 LOCK(tx_relay->m_bloom_filter_mutex);
5748 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5752 if (fSendTrickle && tx_relay->m_send_mempool) {
5753 auto vtxinfo = m_mempool.
infoAll();
5754 tx_relay->m_send_mempool =
false;
5755 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5757 LOCK(tx_relay->m_bloom_filter_mutex);
5759 for (
const auto& txinfo : vtxinfo) {
5760 const Txid& txid{txinfo.tx->GetHash()};
5761 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
5762 const auto inv = peer->m_wtxid_relay ?
5765 tx_relay->m_tx_inventory_to_send.erase(wtxid);
5768 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5771 if (tx_relay->m_bloom_filter) {
5772 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5774 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5775 vInv.push_back(inv);
5786 std::vector<std::set<Wtxid>::iterator> vInvTx;
5787 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5788 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5789 vInvTx.push_back(it);
5791 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5794 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
5795 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5798 unsigned int nRelayedTransactions = 0;
5799 LOCK(tx_relay->m_bloom_filter_mutex);
5802 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5804 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5805 std::set<Wtxid>::iterator it = vInvTx.back();
5809 tx_relay->m_tx_inventory_to_send.erase(it);
5811 auto txinfo = m_mempool.
info(wtxid);
5818 const auto inv = peer->m_wtxid_relay ?
5820 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
5822 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
5826 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5829 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5831 vInv.push_back(inv);
5832 nRelayedTransactions++;
5837 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5842 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5849 auto stalling_timeout = m_block_stalling_timeout.load();
5850 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5859 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5869 if (state.vBlocksInFlight.size() > 0) {
5870 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5871 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5879 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5881 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5882 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5899 state.fSyncStarted =
false;
5901 peer->m_headers_sync_timeout = 0us;
5907 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5913 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5918 std::vector<CInv> vGetData;
5920 std::vector<const CBlockIndex*> vToDownload;
5922 auto get_inflight_budget = [&state]() {
5929 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5930 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
5931 if (historical_blocks && !IsLimitedPeer(*peer)) {
5935 TryDownloadingHistoricalBlocks(
5937 get_inflight_budget(),
5938 vToDownload, from_tip, historical_blocks->second);
5941 uint32_t nFetchFlags = GetFetchFlags(*peer);
5943 BlockRequested(pto->
GetId(), *pindex);
5947 if (state.vBlocksInFlight.empty() && staller != -1) {
5948 if (
State(staller)->m_stalling_since == 0us) {
5949 State(staller)->m_stalling_since = current_time;
5959 LOCK(m_tx_download_mutex);
5960 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
5969 if (!vGetData.empty())
5972 MaybeSendFeefilter(*pto, *peer, current_time);
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
arith_uint256 GetBlockProof(const CBlockIndex &block)
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
@ BLOCK_VALID_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous.
@ BLOCK_HAVE_DATA
full block available in blk*.dat
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< CTransactionRef > txn
std::vector< uint16_t > indexes
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
static constexpr SerParams V1_NETWORK
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V2_NETWORK
size_t BlockTxCount() const
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
unsigned int nTx
Number of transactions in this block.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
An in-memory indexed chain of blocks.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const HeadersSyncParams & HeadersSync() const
const Consensus::Params & GetConsensus() const
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::microseconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetTryNewOutboundPeer() const
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return randomly selected addresses.
std::vector< CAddress > GetAddresses(CNode &requestor, size_t max_addresses, size_t max_pct)
Return addresses from the per-requestor cache.
void SetTryNewOutboundPeer(bool flag)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
bool DisconnectNode(std::string_view node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
bool CheckIncomingNonce(uint64_t nonce)
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, Txid > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
const std::string m_addr_name
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
std::atomic< bool > m_bip152_highbandwidth_from
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
const uint64_t m_network_key
Network key used to prevent fingerprinting our node across networks.
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
General SipHash-2-4 implementation.
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
bool CompareMiningScoreWithTopology(const Wtxid &hasha, const Wtxid &hashb) const
TxMempoolInfo info_for_relay(const T &id, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
CFeeRate GetMinFee(size_t sizelimit) const
CTransactionRef get(const Txid &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
TxMempoolInfo info(const T &id) const
void RemoveUnbroadcastTx(const Txid &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
bool exists(const Txid &txid) const
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
std::set< Txid > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
unsigned long size() const
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void BlockChecked(const std::shared_ptr< const CBlock > &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void ActiveTipChange(const CBlockIndex &new_tip, bool is_ibd)
Notifies listeners any time the block chain tip changes, synchronously.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected Provides the block that was disconnected.
virtual void BlockConnected(const kernel::ChainstateRole &role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
void ClearBlockIndexCandidates() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex * FindForkInGlobalIndex(const CBlockLocator &locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Find the last common block of this chain and a locator.
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Chainstate & ActiveChainstate() const
Alternatives to CurrentChainstate() used by older code to query latest chainstate information without...
SnapshotCompletionResult MaybeValidateSnapshot(Chainstate &validated_cs, Chainstate &unvalidated_cs) EXCLUSIVE_LOCKS_REQUIRED(Chainstate & CurrentChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Try to validate an assumeutxo snapshot by using a validated historical chainstate targeted at the sna...
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool ProcessNewBlockHeaders(std::span< const CBlockHeader > headers, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const arith_uint256 & MinimumChainWork() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Double ended buffer combining vector and stream-like interfaces.
void ignore(size_t num_ignore)
uint64_t rand64() noexcept
Generate a random 64-bit integer.
const uint256 & ToUint256() const LIFETIMEBOUND
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing, bool segwit_active)
bool IsTxAvailable(size_t index) const
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< Wtxid, CTransactionRef > > &extra_txn)
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, DataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
virtual util::Expected< void, std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
virtual std::vector< node::TxOrphanage::OrphanInfo > GetOrphanTransactions()=0
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
virtual void UnitTestMisbehaving(NodeId peer_id)=0
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests....
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
std::string GetDebugMessage() const
std::string ToString() const
256-bit unsigned big integer.
constexpr bool IsNull() const
std::string ToString() const
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool LoadingBlocks() const
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t > > block_part=std::nullopt) const
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
bool IsPruneMode() const
Whether running in -prune mode.
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
Manages warning messages within a node.
std::string ToString() const
const uint256 & ToUint256() const LIFETIMEBOUND
The util::Expected class provides a standard way for low-level functions to return either error value...
The util::Unexpected class represents an unexpected value stored in util::Expected.
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
@ BLOCK_HEADER_LOW_WORK
the block header may be on a too-little-work chain
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ BLOCK_RESULT_UNSET
initial value. Block has not yet been rejected
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_NO_MEMPOOL
this node does not have a mempool so can't validate the transaction
@ TX_RESULT_UNSET
initial value. Tx has not yet been rejected
static size_t RecursiveDynamicUsage(const CScript &script)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
is a home for simple enum and struct type definitions that can be used internally by functions in the...
#define LogDebug(category,...)
Transaction validation functions.
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
TRACEPOINT_SEMAPHORE(net, inbound_message)
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" message type 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" message type and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
std::chrono::seconds time_offset
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
@ DIFFERENT_WITNESS
Valid, transaction was already in the mempool.
@ INVALID
Fully validated, valid.
const std::list< CTransactionRef > m_replaced_transactions
Mempool transactions replaced by the tx.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
Validation result for package mempool acceptance.
PackageValidationState m_state
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
std::chrono::seconds median_outbound_time_offset
Information about chainstate that notifications are sent from.
bool historical
Whether this is a historical chainstate downloading old blocks to validate an assumeutxo snapshot,...
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
std::vector< NodeId > m_senders
std::string ToString() const
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
#define TRACEPOINT(context,...)
consteval auto _(util::TranslatedLiteral str)
ReconciliationRegisterResult
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
constexpr int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...