73#include <initializer_list>
206 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
240 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
243 const bool m_is_inbound;
246 Mutex m_misbehavior_mutex;
248 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
251 Mutex m_block_inv_mutex;
255 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
259 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
270 std::atomic<int> m_starting_height{-1};
273 std::atomic<uint64_t> m_ping_nonce_sent{0};
275 std::atomic<std::chrono::microseconds> m_ping_start{0us};
277 std::atomic<bool> m_ping_queued{
false};
280 std::atomic<bool> m_wtxid_relay{
false};
292 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
294 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
305 std::set<Wtxid> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
309 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
312 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
318 std::atomic<CAmount> m_fee_filter_received{0};
324 LOCK(m_tx_relay_mutex);
326 m_tx_relay = std::make_unique<Peer::TxRelay>();
327 return m_tx_relay.get();
332 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
361 std::atomic_bool m_addr_relay_enabled{
false};
365 mutable Mutex m_addr_send_times_mutex;
367 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
369 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
372 std::atomic_bool m_wants_addrv2{
false};
381 std::atomic<uint64_t> m_addr_rate_limited{0};
383 std::atomic<uint64_t> m_addr_processed{0};
389 Mutex m_getdata_requests_mutex;
391 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
397 Mutex m_headers_sync_mutex;
400 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
403 std::atomic<bool> m_sent_sendheaders{
false};
413 std::atomic<std::chrono::seconds> m_time_offset{0
s};
417 , m_our_services{our_services}
418 , m_is_inbound{is_inbound}
422 mutable Mutex m_tx_relay_mutex;
425 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
428using PeerRef = std::shared_ptr<Peer>;
440 uint256 hashLastUnknownBlock{};
446 bool fSyncStarted{
false};
448 std::chrono::microseconds m_stalling_since{0us};
449 std::list<QueuedBlock> vBlocksInFlight;
451 std::chrono::microseconds m_downloading_since{0us};
453 bool fPreferredDownload{
false};
455 bool m_requested_hb_cmpctblocks{
false};
457 bool m_provides_cmpctblocks{
false};
483 struct ChainSyncTimeoutState {
485 std::chrono::seconds m_timeout{0
s};
489 bool m_sent_getheaders{
false};
491 bool m_protect{
false};
494 ChainSyncTimeoutState m_chain_sync;
497 int64_t m_last_block_announcement{0};
526 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
540 void SetBestBlock(
int height,
std::chrono::seconds time)
override
542 m_best_height = height;
543 m_best_block_time = time;
547 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
548 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
572 void Misbehaving(Peer& peer,
const std::string& message);
583 bool via_compact_block,
const std::string& message =
"")
592 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
606 bool first_time_failure)
631 bool ProcessOrphanTx(Peer& peer)
641 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
643 bool via_compact_block)
655 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
674 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
688 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
703 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
705 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
712 template <
typename... Args>
713 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
719 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
725 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
768 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
771 std::atomic<int> m_best_height{-1};
773 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
781 const Options m_opts;
783 bool RejectIncomingTxs(
const CNode& peer)
const;
791 mutable Mutex m_peer_mutex;
798 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
808 uint32_t GetFetchFlags(
const Peer& peer)
const;
810 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
827 std::atomic<int> m_wtxid_relay_peers{0};
844 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
849 Mutex m_most_recent_block_mutex;
850 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
851 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
853 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
857 Mutex m_headers_presync_mutex;
865 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
867 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
871 std::atomic_bool m_headers_presync_should_signal{
false};
941 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
947 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
952 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
977 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
979 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
991 int64_t ApproximateBestBlockDepth() const;
1001 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1019 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1021 const
uint256& stop_hash, uint32_t max_height_diff,
1069 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1072const CNodeState* PeerManagerImpl::State(
NodeId pnode)
const
1074 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1075 if (it == m_node_states.end())
1080CNodeState* PeerManagerImpl::State(
NodeId pnode)
1082 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1090static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1095void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1097 assert(peer.m_addr_known);
1098 peer.m_addr_known->insert(addr.
GetKey());
1101void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1106 assert(peer.m_addr_known);
1107 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1109 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1111 peer.m_addrs_to_send.push_back(addr);
1116static void AddKnownTx(Peer& peer,
const uint256& hash)
1118 auto tx_relay = peer.GetTxRelay();
1119 if (!tx_relay)
return;
1121 LOCK(tx_relay->m_tx_inventory_mutex);
1122 tx_relay->m_tx_inventory_known_filter.insert(hash);
1126static bool CanServeBlocks(
const Peer& peer)
1133static bool IsLimitedPeer(
const Peer& peer)
1140static bool CanServeWitnesses(
const Peer& peer)
1145std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1146 std::chrono::seconds average_interval)
1148 if (m_next_inv_to_inbounds.load() < now) {
1152 m_next_inv_to_inbounds = now + m_rng.rand_exp_duration(average_interval);
1154 return m_next_inv_to_inbounds;
1157bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1159 return mapBlocksInFlight.count(hash);
1162bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1164 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1165 auto [nodeid, block_it] = range.first->second;
1166 PeerRef peer{GetPeerRef(nodeid)};
1167 if (peer && !peer->m_is_inbound)
return true;
1173void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1175 auto range = mapBlocksInFlight.equal_range(hash);
1176 if (range.first == range.second) {
1184 while (range.first != range.second) {
1185 const auto& [node_id, list_it]{range.first->second};
1187 if (from_peer && *from_peer != node_id) {
1192 CNodeState& state = *
Assert(State(node_id));
1194 if (state.vBlocksInFlight.begin() == list_it) {
1196 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1198 state.vBlocksInFlight.erase(list_it);
1200 if (state.vBlocksInFlight.empty()) {
1202 m_peers_downloading_from--;
1204 state.m_stalling_since = 0us;
1206 range.first = mapBlocksInFlight.erase(range.first);
1210bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1214 CNodeState *state = State(nodeid);
1215 assert(state !=
nullptr);
1220 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1221 if (range.first->second.first == nodeid) {
1223 *pit = &range.first->second.second;
1230 RemoveBlockRequest(hash, nodeid);
1232 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1233 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1234 if (state->vBlocksInFlight.size() == 1) {
1236 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1237 m_peers_downloading_from++;
1239 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1241 *pit = &itInFlight->second.second;
1246void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1253 if (m_opts.ignore_incoming_txs)
return;
1255 CNodeState* nodestate = State(nodeid);
1256 PeerRef peer{GetPeerRef(nodeid)};
1257 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1262 int num_outbound_hb_peers = 0;
1263 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1264 if (*it == nodeid) {
1265 lNodesAnnouncingHeaderAndIDs.erase(it);
1266 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1269 PeerRef peer_ref{GetPeerRef(*it)};
1270 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1272 if (peer && peer->m_is_inbound) {
1275 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1276 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1277 if (remove_peer && !remove_peer->m_is_inbound) {
1280 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1286 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1289 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1290 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1292 pnodeStop->m_bip152_highbandwidth_to = false;
1295 lNodesAnnouncingHeaderAndIDs.pop_front();
1300 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1305bool PeerManagerImpl::TipMayBeStale()
1309 if (m_last_tip_update.load() == 0
s) {
1310 m_last_tip_update = GetTime<std::chrono::seconds>();
1312 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1315int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1320bool PeerManagerImpl::CanDirectFetch()
1327 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1329 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1334void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1335 CNodeState *state = State(nodeid);
1336 assert(state !=
nullptr);
1338 if (!state->hashLastUnknownBlock.IsNull()) {
1341 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1342 state->pindexBestKnownBlock = pindex;
1344 state->hashLastUnknownBlock.SetNull();
1349void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1350 CNodeState *state = State(nodeid);
1351 assert(state !=
nullptr);
1353 ProcessBlockAvailability(nodeid);
1358 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1359 state->pindexBestKnownBlock = pindex;
1363 state->hashLastUnknownBlock = hash;
1368void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1373 vBlocks.reserve(vBlocks.size() +
count);
1374 CNodeState *state = State(peer.m_id);
1375 assert(state !=
nullptr);
1378 ProcessBlockAvailability(peer.m_id);
1380 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1388 const CBlockIndex* snap_base{m_chainman.GetSnapshotBaseBlock()};
1389 if (snap_base && state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1390 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1397 if (state->pindexLastCommonBlock ==
nullptr ||
1398 (snap_base && state->pindexLastCommonBlock->nHeight < snap_base->nHeight)) {
1399 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1404 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1405 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1408 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1414 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1417void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1422 if (vBlocks.size() >=
count) {
1426 vBlocks.reserve(
count);
1427 CNodeState *state =
Assert(State(peer.m_id));
1429 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1446void 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)
1448 std::vector<const CBlockIndex*> vToFetch;
1449 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1450 bool is_limited_peer = IsLimitedPeer(peer);
1452 while (pindexWalk->
nHeight < nMaxHeight) {
1456 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1457 vToFetch.resize(nToFetch);
1458 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1459 vToFetch[nToFetch - 1] = pindexWalk;
1460 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1461 vToFetch[i - 1] = vToFetch[i]->
pprev;
1481 state->pindexLastCommonBlock = pindex;
1488 if (waitingfor == -1) {
1490 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1496 if (pindex->
nHeight > nWindowEnd) {
1498 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1500 if (nodeStaller) *nodeStaller = waitingfor;
1510 vBlocks.push_back(pindex);
1511 if (vBlocks.size() ==
count) {
1520void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1522 uint64_t my_services{peer.m_our_services};
1523 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1525 const int nNodeStartingHeight{m_best_height};
1532 const bool tx_relay{!RejectIncomingTxs(pnode)};
1539 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);
1545void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1548 CNodeState *state = State(
node);
1549 if (state) state->m_last_block_announcement = time_in_seconds;
1557 m_node_states.try_emplace(m_node_states.end(), nodeid);
1559 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1565 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1568 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1572void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1576 for (
const auto& txid : unbroadcast_txids) {
1579 if (tx !=
nullptr) {
1580 RelayTransaction(txid, tx->GetWitnessHash());
1589 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1592void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1603 PeerRef peer = RemovePeer(nodeid);
1605 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1606 assert(m_wtxid_relay_peers >= 0);
1608 CNodeState *state = State(nodeid);
1609 assert(state !=
nullptr);
1611 if (state->fSyncStarted)
1614 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1615 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1616 while (range.first != range.second) {
1617 auto [node_id, list_it] = range.first->second;
1618 if (node_id != nodeid) {
1621 range.first = mapBlocksInFlight.erase(range.first);
1626 LOCK(m_tx_download_mutex);
1627 m_txdownloadman.DisconnectedPeer(nodeid);
1629 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1630 m_num_preferred_download_peers -= state->fPreferredDownload;
1631 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1632 assert(m_peers_downloading_from >= 0);
1633 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1634 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1636 m_node_states.erase(nodeid);
1638 if (m_node_states.empty()) {
1640 assert(mapBlocksInFlight.empty());
1641 assert(m_num_preferred_download_peers == 0);
1642 assert(m_peers_downloading_from == 0);
1643 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1644 assert(m_wtxid_relay_peers == 0);
1645 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1648 if (
node.fSuccessfullyConnected &&
1649 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1656 LOCK(m_headers_presync_mutex);
1657 m_headers_presync_stats.erase(nodeid);
1662bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1665 return !(GetDesirableServiceFlags(services) & (~services));
1679PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1682 auto it = m_peer_map.find(
id);
1683 return it != m_peer_map.end() ? it->second :
nullptr;
1686PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1690 auto it = m_peer_map.find(
id);
1691 if (it != m_peer_map.end()) {
1692 ret = std::move(it->second);
1693 m_peer_map.erase(it);
1702 const CNodeState* state = State(nodeid);
1703 if (state ==
nullptr)
1705 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1706 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1707 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1713 PeerRef peer = GetPeerRef(nodeid);
1714 if (peer ==
nullptr)
return false;
1723 auto ping_wait{0us};
1724 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1725 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1728 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1741 LOCK(peer->m_headers_sync_mutex);
1742 if (peer->m_headers_sync) {
1751std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1753 LOCK(m_tx_download_mutex);
1754 return m_txdownloadman.GetOrphanTransactions();
1761 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1765void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1767 if (m_opts.max_extra_txs <= 0)
1769 if (!vExtraTxnForCompact.size())
1770 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1771 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1772 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1775void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1777 LOCK(peer.m_misbehavior_mutex);
1779 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1780 peer.m_should_discourage =
true;
1789 bool via_compact_block,
const std::string& message)
1791 PeerRef peer{GetPeerRef(nodeid)};
1802 if (!via_compact_block) {
1803 if (peer) Misbehaving(*peer, message);
1811 if (peer && !via_compact_block && !peer->m_is_inbound) {
1812 if (peer) Misbehaving(*peer, message);
1819 if (peer) Misbehaving(*peer, message);
1823 if (peer) Misbehaving(*peer, message);
1828 if (message !=
"") {
1833bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1842std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1847 PeerRef peer = GetPeerRef(peer_id);
1848 if (peer ==
nullptr)
return "Peer does not exist";
1851 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1856 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1859 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1871 if (!success)
return "Peer not fully connected";
1875 return std::nullopt;
1882 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1888 : m_rng{opts.deterministic_rng},
1890 m_chainparams(chainman.GetParams()),
1894 m_chainman(chainman),
1896 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
1897 m_warnings{warnings},
1902 if (opts.reconcile_txs) {
1907void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1918 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1921void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
1929 LOCK(m_tx_download_mutex);
1933 m_txdownloadman.ActiveTipChange();
1943void PeerManagerImpl::BlockConnected(
1945 const std::shared_ptr<const CBlock>& pblock,
1950 m_last_tip_update = GetTime<std::chrono::seconds>();
1953 auto stalling_timeout = m_block_stalling_timeout.load();
1957 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1967 LOCK(m_tx_download_mutex);
1968 m_txdownloadman.BlockConnected(pblock);
1971void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1973 LOCK(m_tx_download_mutex);
1974 m_txdownloadman.BlockDisconnected();
1981void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1983 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
1987 if (pindex->
nHeight <= m_highest_fast_announce)
1989 m_highest_fast_announce = pindex->
nHeight;
1993 uint256 hashBlock(pblock->GetHash());
1994 const std::shared_future<CSerializedNetMsg> lazy_ser{
1998 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
1999 for (
const auto& tx : pblock->vtx) {
2000 most_recent_block_txs->emplace(tx->GetHash(), tx);
2001 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2004 LOCK(m_most_recent_block_mutex);
2005 m_most_recent_block_hash = hashBlock;
2006 m_most_recent_block = pblock;
2007 m_most_recent_compact_block = pcmpctblock;
2008 m_most_recent_block_txs = std::move(most_recent_block_txs);
2016 ProcessBlockAvailability(pnode->
GetId());
2017 CNodeState &state = *State(pnode->
GetId());
2020 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2022 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2023 hashBlock.ToString(), pnode->
GetId());
2026 PushMessage(*pnode, ser_cmpctblock.Copy());
2027 state.pindexBestHeaderSent = pindex;
2036void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2038 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2041 if (fInitialDownload)
return;
2044 std::vector<uint256> vHashes;
2046 while (pindexToAnnounce != pindexFork) {
2048 pindexToAnnounce = pindexToAnnounce->
pprev;
2058 for (
auto& it : m_peer_map) {
2059 Peer& peer = *it.second;
2060 LOCK(peer.m_block_inv_mutex);
2061 for (
const uint256& hash : vHashes | std::views::reverse) {
2062 peer.m_blocks_for_headers_relay.push_back(hash);
2074void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2078 const uint256 hash(block->GetHash());
2079 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2084 it != mapBlockSource.end() &&
2085 State(it->second.first)) {
2086 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2096 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2097 if (it != mapBlockSource.end()) {
2098 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2101 if (it != mapBlockSource.end())
2102 mapBlockSource.erase(it);
2110bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2115void PeerManagerImpl::SendPings()
2118 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2121void PeerManagerImpl::RelayTransaction(
const Txid& txid,
const Wtxid& wtxid)
2124 for(
auto& it : m_peer_map) {
2125 Peer& peer = *it.second;
2126 auto tx_relay = peer.GetTxRelay();
2127 if (!tx_relay)
continue;
2129 LOCK(tx_relay->m_tx_inventory_mutex);
2135 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2138 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2139 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2144void PeerManagerImpl::RelayAddress(
NodeId originator,
2160 const auto current_time{GetTime<std::chrono::seconds>()};
2168 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2170 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2171 assert(nRelayNodes <= best.size());
2175 for (
auto& [
id, peer] : m_peer_map) {
2176 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2178 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2179 if (hashKey > best[i].first) {
2180 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2181 best[i] = std::make_pair(hashKey, peer.get());
2188 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2189 PushAddress(*best[i].second, addr);
2193void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2195 std::shared_ptr<const CBlock> a_recent_block;
2196 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2198 LOCK(m_most_recent_block_mutex);
2199 a_recent_block = m_most_recent_block;
2200 a_recent_compact_block = m_most_recent_compact_block;
2203 bool need_activate_chain =
false;
2215 need_activate_chain =
true;
2219 if (need_activate_chain) {
2221 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2228 bool can_direct_fetch{
false};
2236 if (!BlockRequestAllowed(pindex)) {
2237 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2264 can_direct_fetch = CanDirectFetch();
2268 std::shared_ptr<const CBlock> pblock;
2269 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2270 pblock = a_recent_block;
2274 std::vector<std::byte> block_data;
2288 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2298 pblock = pblockRead;
2306 bool sendMerkleBlock =
false;
2308 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2309 LOCK(tx_relay->m_bloom_filter_mutex);
2310 if (tx_relay->m_bloom_filter) {
2311 sendMerkleBlock =
true;
2312 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2315 if (sendMerkleBlock) {
2323 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2334 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2347 LOCK(peer.m_block_inv_mutex);
2349 if (inv.
hash == peer.m_continuation_block) {
2353 std::vector<CInv> vInv;
2354 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2356 peer.m_continuation_block.SetNull();
2364 auto txinfo{std::visit(
2366 return m_mempool.
info_for_relay(
id, tx_relay.m_last_inv_sequence);
2370 return std::move(txinfo.tx);
2375 LOCK(m_most_recent_block_mutex);
2376 if (m_most_recent_block_txs !=
nullptr) {
2377 auto it = m_most_recent_block_txs->find(gtxid);
2378 if (it != m_most_recent_block_txs->end())
return it->second;
2385void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2389 auto tx_relay = peer.GetTxRelay();
2391 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2392 std::vector<CInv> vNotFound;
2397 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2398 if (interruptMsgProc)
return;
2403 const CInv &inv = *it++;
2405 if (tx_relay ==
nullptr) {
2411 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2414 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2417 vNotFound.push_back(inv);
2423 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2424 const CInv &inv = *it++;
2426 ProcessGetBlockData(pfrom, peer, inv);
2435 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2437 if (!vNotFound.empty()) {
2456uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2458 uint32_t nFetchFlags = 0;
2459 if (CanServeWitnesses(peer)) {
2468 unsigned int tx_requested_size = 0;
2469 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2471 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2475 tx_requested_size += resp.txn[i]->GetTotalSize();
2482bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2486 Misbehaving(peer,
"header with invalid proof of work");
2491 if (!CheckHeadersAreContinuous(headers)) {
2492 Misbehaving(peer,
"non-continuous headers sequence");
2517void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2518 const std::vector<CBlockHeader>& headers)
2522 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2523 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2525 headers[0].hashPrevBlock.ToString(),
2526 best_header->nHeight,
2536bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2540 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2543 hashLastBlock = header.GetHash();
2548bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2550 if (peer.m_headers_sync) {
2551 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2553 if (result.success) peer.m_last_getheaders_timestamp = {};
2554 if (result.request_more) {
2555 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2557 Assume(!locator.vHave.empty());
2560 if (!locator.vHave.empty()) {
2563 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2566 locator.vHave.front().ToString(), pfrom.
GetId());
2571 peer.m_headers_sync.reset(
nullptr);
2576 LOCK(m_headers_presync_mutex);
2577 m_headers_presync_stats.erase(pfrom.
GetId());
2580 HeadersPresyncStats stats;
2581 stats.first = peer.m_headers_sync->GetPresyncWork();
2583 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2584 peer.m_headers_sync->GetPresyncTime()};
2588 LOCK(m_headers_presync_mutex);
2589 m_headers_presync_stats[pfrom.
GetId()] = stats;
2590 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2591 bool best_updated =
false;
2592 if (best_it == m_headers_presync_stats.end()) {
2596 const HeadersPresyncStats* stat_best{
nullptr};
2597 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2598 if (!stat_best || stat > *stat_best) {
2603 m_headers_presync_bestpeer = peer_best;
2604 best_updated = (peer_best == pfrom.
GetId());
2605 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2607 m_headers_presync_bestpeer = pfrom.
GetId();
2608 best_updated =
true;
2610 if (best_updated && stats.second.has_value()) {
2612 m_headers_presync_should_signal =
true;
2616 if (result.success) {
2619 headers.swap(result.pow_validated_headers);
2622 return result.success;
2630bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2637 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2641 if (total_work < minimum_chain_work) {
2645 if (headers.size() == m_opts.max_headers_result) {
2655 LOCK(peer.m_headers_sync_mutex);
2657 chain_start_header, minimum_chain_work));
2662 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2676bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2678 if (header ==
nullptr) {
2680 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2688bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2696 peer.m_last_getheaders_timestamp = current_time;
2707void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2710 CNodeState *nodestate = State(pfrom.
GetId());
2713 std::vector<const CBlockIndex*> vToFetch;
2721 vToFetch.push_back(pindexWalk);
2723 pindexWalk = pindexWalk->
pprev;
2734 std::vector<CInv> vGetData;
2736 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2741 uint32_t nFetchFlags = GetFetchFlags(peer);
2743 BlockRequested(pfrom.
GetId(), *pindex);
2747 if (vGetData.size() > 1) {
2752 if (vGetData.size() > 0) {
2753 if (!m_opts.ignore_incoming_txs &&
2754 nodestate->m_provides_cmpctblocks &&
2755 vGetData.size() == 1 &&
2756 mapBlocksInFlight.size() == 1 &&
2772void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2773 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2776 CNodeState *nodestate = State(pfrom.
GetId());
2785 nodestate->m_last_block_announcement =
GetTime();
2793 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2815 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) {
2817 nodestate->m_chain_sync.m_protect =
true;
2818 ++m_outbound_peers_with_protect_from_disconnect;
2823void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2824 std::vector<CBlockHeader>&& headers,
2825 bool via_compact_block)
2827 size_t nCount = headers.size();
2834 LOCK(peer.m_headers_sync_mutex);
2835 if (peer.m_headers_sync) {
2836 peer.m_headers_sync.reset(
nullptr);
2837 LOCK(m_headers_presync_mutex);
2838 m_headers_presync_stats.erase(pfrom.
GetId());
2842 peer.m_last_getheaders_timestamp = {};
2850 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2865 bool already_validated_work =
false;
2868 bool have_headers_sync =
false;
2870 LOCK(peer.m_headers_sync_mutex);
2872 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2884 if (headers.empty()) {
2888 have_headers_sync = !!peer.m_headers_sync;
2893 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2895 if (!headers_connect_blockindex) {
2899 HandleUnconnectingHeaders(pfrom, peer, headers);
2906 peer.m_last_getheaders_timestamp = {};
2916 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2917 already_validated_work =
true;
2925 already_validated_work =
true;
2931 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2932 chain_start_header, headers)) {
2944 bool received_new_header{last_received_header ==
nullptr};
2950 state, &pindexLast)};
2953 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2959 if (processed && received_new_header) {
2960 LogBlockHeader(*pindexLast, pfrom,
false);
2964 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
2966 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2968 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2972 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
2975 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
2981 bool first_time_failure)
2987 PeerRef peer{GetPeerRef(nodeid)};
2990 ptx->GetHash().ToString(),
2991 ptx->GetWitnessHash().ToString(),
2995 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
2998 AddToCompactExtraTransactions(ptx);
3000 for (
const Txid& parent_txid : unique_parents) {
3001 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3004 return package_to_validate;
3007void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3013 m_txdownloadman.MempoolAcceptedTx(tx);
3017 tx->GetHash().ToString(),
3018 tx->GetWitnessHash().ToString(),
3021 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3024 AddToCompactExtraTransactions(removedTx);
3034 const auto&
package = package_to_validate.m_txns;
3035 const auto& senders = package_to_validate.
m_senders;
3038 m_txdownloadman.MempoolRejectedPackage(package);
3041 if (!
Assume(package.size() == 2))
return;
3045 auto package_iter = package.rbegin();
3046 auto senders_iter = senders.rbegin();
3047 while (package_iter != package.rend()) {
3048 const auto& tx = *package_iter;
3049 const NodeId nodeid = *senders_iter;
3050 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3054 const auto& tx_result = it_result->second;
3055 switch (tx_result.m_result_type) {
3058 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3068 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3086bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3093 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3096 const Txid& orphanHash = porphanTx->GetHash();
3097 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3114 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3123bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3125 const uint256& stop_hash, uint32_t max_height_diff,
3129 const bool supported_filter_type =
3132 if (!supported_filter_type) {
3134 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg(
fLogIPs));
3135 node.fDisconnect =
true;
3144 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3147 node.fDisconnect =
true;
3152 uint32_t stop_height = stop_index->
nHeight;
3153 if (start_height > stop_height) {
3155 "start height %d and stop height %d, %s\n",
3156 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3157 node.fDisconnect =
true;
3160 if (stop_height - start_height >= max_height_diff) {
3162 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3163 node.fDisconnect =
true;
3168 if (!filter_index) {
3178 uint8_t filter_type_ser;
3179 uint32_t start_height;
3182 vRecv >> filter_type_ser >> start_height >> stop_hash;
3188 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3193 std::vector<BlockFilter> filters;
3195 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3200 for (
const auto& filter : filters) {
3207 uint8_t filter_type_ser;
3208 uint32_t start_height;
3211 vRecv >> filter_type_ser >> start_height >> stop_hash;
3217 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3223 if (start_height > 0) {
3225 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3227 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3233 std::vector<uint256> filter_hashes;
3235 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3249 uint8_t filter_type_ser;
3252 vRecv >> filter_type_ser >> stop_hash;
3258 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3259 std::numeric_limits<uint32_t>::max(),
3260 stop_index, filter_index)) {
3268 for (
int i = headers.size() - 1; i >= 0; i--) {
3273 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3287 bool new_block{
false};
3288 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3290 node.m_last_block_time = GetTime<std::chrono::seconds>();
3295 RemoveBlockRequest(block->GetHash(), std::nullopt);
3298 mapBlockSource.erase(block->GetHash());
3302void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3304 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3305 bool fBlockRead{
false};
3309 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3310 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3311 bool requested_block_from_this_peer{
false};
3314 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3316 while (range_flight.first != range_flight.second) {
3317 auto [node_id, block_it] = range_flight.first->second;
3318 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3319 requested_block_from_this_peer =
true;
3322 range_flight.first++;
3325 if (!requested_block_from_this_peer) {
3338 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3341 if (first_in_flight) {
3343 std::vector<CInv> invs;
3348 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3361 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3376void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3388 "Saw new %sheader hash=%s height=%d peer=%d%s",
3389 via_compact_block ?
"cmpctblock " :
"",
3402void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3403 const std::chrono::microseconds time_received,
3404 const std::atomic<bool>& interruptMsgProc)
3410 PeerRef peer = GetPeerRef(pfrom.
GetId());
3411 if (peer ==
nullptr)
return;
3421 uint64_t nNonce = 1;
3424 std::string cleanSubVer;
3425 int starting_height = -1;
3428 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3443 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3445 GetDesirableServiceFlags(nServices),
3458 if (!vRecv.
empty()) {
3466 if (!vRecv.
empty()) {
3467 std::string strSubVer;
3471 if (!vRecv.
empty()) {
3472 vRecv >> starting_height;
3492 PushNodeVersion(pfrom, *peer);
3505 if (greatest_common_version >= 70016) {
3514 peer->m_their_services = nServices;
3518 pfrom.cleanSubVer = cleanSubVer;
3520 peer->m_starting_height = starting_height;
3530 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3531 auto*
const tx_relay = peer->SetTxRelay();
3533 LOCK(tx_relay->m_bloom_filter_mutex);
3534 tx_relay->m_relay_txs = fRelay;
3546 const auto* tx_relay = peer->GetTxRelay();
3547 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3549 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3560 CNodeState* state = State(pfrom.
GetId());
3562 m_num_preferred_download_peers += state->fPreferredDownload;
3568 bool send_getaddr{
false};
3570 send_getaddr = SetupAddressRelay(pfrom, *peer);
3580 peer->m_getaddr_sent =
true;
3605 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3610 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3614 m_outbound_time_offsets.Add(peer->m_time_offset);
3615 m_outbound_time_offsets.WarnIfOutOfSync();
3619 if (greatest_common_version <= 70012) {
3620 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3621 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3648 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3651 pfrom.
nVersion.load(), peer->m_starting_height,
3653 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3665 if (m_txreconciliation) {
3666 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3670 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3674 if (
auto tx_relay = peer->GetTxRelay()) {
3683 tx_relay->m_tx_inventory_mutex,
3684 return tx_relay->m_tx_inventory_to_send.empty() &&
3685 tx_relay->m_next_inv_send_time == 0
s));
3690 const CNodeState* state = State(pfrom.
GetId());
3692 .m_preferred = state->fPreferredDownload,
3693 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3694 .m_wtxid_relay = peer->m_wtxid_relay,
3703 peer->m_prefers_headers =
true;
3708 bool sendcmpct_hb{
false};
3709 uint64_t sendcmpct_version{0};
3710 vRecv >> sendcmpct_hb >> sendcmpct_version;
3716 CNodeState* nodestate = State(pfrom.
GetId());
3717 nodestate->m_provides_cmpctblocks =
true;
3718 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3735 if (!peer->m_wtxid_relay) {
3736 peer->m_wtxid_relay =
true;
3737 m_wtxid_relay_peers++;
3756 peer->m_wants_addrv2 =
true;
3764 if (!m_txreconciliation) {
3765 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3776 if (RejectIncomingTxs(pfrom)) {
3785 const auto* tx_relay = peer->GetTxRelay();
3786 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3792 uint32_t peer_txreconcl_version;
3793 uint64_t remote_salt;
3794 vRecv >> peer_txreconcl_version >> remote_salt;
3797 peer_txreconcl_version, remote_salt);
3822 const auto ser_params{
3830 std::vector<CAddress> vAddr;
3832 vRecv >> ser_params(vAddr);
3834 if (!SetupAddressRelay(pfrom, *peer)) {
3841 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3846 std::vector<CAddress> vAddrOk;
3847 const auto current_a_time{Now<NodeSeconds>()};
3850 const auto current_time{GetTime<std::chrono::microseconds>()};
3853 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3857 peer->m_addr_token_timestamp = current_time;
3860 uint64_t num_proc = 0;
3861 uint64_t num_rate_limit = 0;
3862 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
3865 if (interruptMsgProc)
3869 if (peer->m_addr_token_bucket < 1.0) {
3875 peer->m_addr_token_bucket -= 1.0;
3884 addr.
nTime = current_a_time - 5 * 24h;
3886 AddAddressKnown(*peer, addr);
3893 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3895 RelayAddress(pfrom.
GetId(), addr, reachable);
3899 vAddrOk.push_back(addr);
3902 peer->m_addr_processed += num_proc;
3903 peer->m_addr_rate_limited += num_rate_limit;
3904 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3905 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3907 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3908 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3919 std::vector<CInv> vInv;
3923 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
3927 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3931 const auto current_time{GetTime<std::chrono::microseconds>()};
3934 for (
CInv& inv : vInv) {
3935 if (interruptMsgProc)
return;
3940 if (peer->m_wtxid_relay) {
3947 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3950 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3958 best_block = &inv.
hash;
3961 if (reject_tx_invs) {
3967 AddKnownTx(*peer, inv.
hash);
3970 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
3978 if (best_block !=
nullptr) {
3990 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
3991 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
3993 m_chainman.m_best_header->nHeight, best_block->ToString(),
3996 if (!state.fSyncStarted) {
3997 peer->m_inv_triggered_getheaders_before_sync =
true;
4001 m_last_block_inv_triggering_headers_sync = *best_block;
4010 std::vector<CInv> vInv;
4014 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
4020 if (vInv.size() > 0) {
4025 LOCK(peer->m_getdata_requests_mutex);
4026 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
4027 ProcessGetData(pfrom, *peer, interruptMsgProc);
4036 vRecv >> locator >> hashStop;
4052 std::shared_ptr<const CBlock> a_recent_block;
4054 LOCK(m_most_recent_block_mutex);
4055 a_recent_block = m_most_recent_block;
4058 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4073 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4088 if (--nLimit <= 0) {
4092 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4103 std::shared_ptr<const CBlock> recent_block;
4105 LOCK(m_most_recent_block_mutex);
4106 if (m_most_recent_block_hash == req.
blockhash)
4107 recent_block = m_most_recent_block;
4111 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4130 if (!block_pos.IsNull()) {
4137 SendBlockTransactions(pfrom, *peer, block, req);
4150 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4158 vRecv >> locator >> hashStop;
4176 if (m_chainman.
ActiveTip() ==
nullptr ||
4178 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4185 CNodeState *nodestate = State(pfrom.
GetId());
4195 if (!BlockRequestAllowed(pindex)) {
4196 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4209 std::vector<CBlock> vHeaders;
4210 int nLimit = m_opts.max_headers_result;
4212 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4215 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4230 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4236 if (RejectIncomingTxs(pfrom)) {
4250 const Txid& txid = ptx->GetHash();
4251 const Wtxid& wtxid = ptx->GetWitnessHash();
4254 AddKnownTx(*peer, hash);
4258 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4259 if (!should_validate) {
4264 if (!m_mempool.
exists(txid)) {
4265 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4268 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4270 RelayTransaction(txid, wtxid);
4274 if (package_to_validate) {
4277 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4278 ProcessPackageResult(package_to_validate.value(), package_result);
4284 Assume(!package_to_validate.has_value());
4294 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4297 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4298 ProcessPackageResult(package_to_validate.value(), package_result);
4314 vRecv >> cmpctblock;
4316 bool received_new_header =
false;
4326 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4336 received_new_header =
true;
4344 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4351 if (received_new_header) {
4352 LogBlockHeader(*pindex, pfrom,
true);
4355 bool fProcessBLOCKTXN =
false;
4359 bool fRevertToHeaderProcessing =
false;
4363 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4364 bool fBlockReconstructed =
false;
4370 CNodeState *nodestate = State(pfrom.
GetId());
4375 nodestate->m_last_block_announcement =
GetTime();
4381 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4382 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4383 bool requested_block_from_this_peer{
false};
4386 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4388 while (range_flight.first != range_flight.second) {
4389 if (range_flight.first->second.first == pfrom.
GetId()) {
4390 requested_block_from_this_peer =
true;
4393 range_flight.first++;
4398 if (requested_block_from_this_peer) {
4401 std::vector<CInv> vInv(1);
4402 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4409 if (!already_in_flight && !CanDirectFetch()) {
4417 requested_block_from_this_peer) {
4418 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4419 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4420 if (!(*queuedBlockIt)->partialBlock)
4433 Misbehaving(*peer,
"invalid compact block");
4436 if (first_in_flight) {
4438 std::vector<CInv> vInv(1);
4439 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4449 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4454 fProcessBLOCKTXN =
true;
4455 }
else if (first_in_flight) {
4462 IsBlockRequestedFromOutbound(blockhash) ||
4481 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4486 std::vector<CTransactionRef> dummy;
4488 status = tempBlock.FillBlock(*pblock, dummy,
4491 fBlockReconstructed =
true;
4495 if (requested_block_from_this_peer) {
4498 std::vector<CInv> vInv(1);
4499 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4504 fRevertToHeaderProcessing =
true;
4509 if (fProcessBLOCKTXN) {
4512 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4515 if (fRevertToHeaderProcessing) {
4521 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4524 if (fBlockReconstructed) {
4529 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4547 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4564 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4575 std::vector<CBlockHeader> headers;
4579 if (nCount > m_opts.max_headers_result) {
4580 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4583 headers.resize(nCount);
4584 for (
unsigned int n = 0; n < nCount; n++) {
4585 vRecv >> headers[n];
4589 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4593 if (m_headers_presync_should_signal.exchange(
false)) {
4594 HeadersPresyncStats stats;
4596 LOCK(m_headers_presync_mutex);
4597 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4598 if (it != m_headers_presync_stats.end()) stats = it->second;
4616 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4627 Misbehaving(*peer,
"mutated block");
4632 bool forceProcessing =
false;
4633 const uint256 hash(pblock->GetHash());
4634 bool min_pow_checked =
false;
4639 forceProcessing = IsBlockRequested(hash);
4640 RemoveBlockRequest(hash, pfrom.
GetId());
4644 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4648 min_pow_checked =
true;
4651 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4668 Assume(SetupAddressRelay(pfrom, *peer));
4672 if (peer->m_getaddr_recvd) {
4676 peer->m_getaddr_recvd =
true;
4678 peer->m_addrs_to_send.clear();
4679 std::vector<CAddress> vAddr;
4685 for (
const CAddress &addr : vAddr) {
4686 PushAddress(*peer, addr);
4714 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4715 LOCK(tx_relay->m_tx_inventory_mutex);
4716 tx_relay->m_send_mempool =
true;
4742 const auto ping_end = time_received;
4745 bool bPingFinished =
false;
4746 std::string sProblem;
4748 if (nAvail >=
sizeof(
nonce)) {
4752 if (peer->m_ping_nonce_sent != 0) {
4753 if (
nonce == peer->m_ping_nonce_sent) {
4755 bPingFinished =
true;
4756 const auto ping_time = ping_end - peer->m_ping_start.load();
4757 if (ping_time.count() >= 0) {
4762 sProblem =
"Timing mishap";
4766 sProblem =
"Nonce mismatch";
4769 bPingFinished =
true;
4770 sProblem =
"Nonce zero";
4774 sProblem =
"Unsolicited pong without ping";
4778 bPingFinished =
true;
4779 sProblem =
"Short payload";
4782 if (!(sProblem.empty())) {
4786 peer->m_ping_nonce_sent,
4790 if (bPingFinished) {
4791 peer->m_ping_nonce_sent = 0;
4808 Misbehaving(*peer,
"too-large bloom filter");
4809 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4811 LOCK(tx_relay->m_bloom_filter_mutex);
4812 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4813 tx_relay->m_relay_txs =
true;
4827 std::vector<unsigned char> vData;
4835 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4836 LOCK(tx_relay->m_bloom_filter_mutex);
4837 if (tx_relay->m_bloom_filter) {
4838 tx_relay->m_bloom_filter->insert(vData);
4844 Misbehaving(*peer,
"bad filteradd message");
4855 auto tx_relay = peer->GetTxRelay();
4856 if (!tx_relay)
return;
4859 LOCK(tx_relay->m_bloom_filter_mutex);
4860 tx_relay->m_bloom_filter =
nullptr;
4861 tx_relay->m_relay_txs =
true;
4870 vRecv >> newFeeFilter;
4872 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4873 tx_relay->m_fee_filter_received = newFeeFilter;
4881 ProcessGetCFilters(pfrom, *peer, vRecv);
4886 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4891 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4896 std::vector<CInv> vInv;
4898 std::vector<GenTxid> tx_invs;
4900 for (
CInv &inv : vInv) {
4906 LOCK(m_tx_download_mutex);
4907 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
4916bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4919 LOCK(peer.m_misbehavior_mutex);
4922 if (!peer.m_should_discourage)
return false;
4924 peer.m_should_discourage =
false;
4929 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
4935 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
4955bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4960 PeerRef peer = GetPeerRef(pfrom->
GetId());
4961 if (peer ==
nullptr)
return false;
4965 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
4968 LOCK(peer->m_getdata_requests_mutex);
4969 if (!peer->m_getdata_requests.empty()) {
4970 ProcessGetData(*pfrom, *peer, interruptMsgProc);
4974 const bool processed_orphan = ProcessOrphanTx(*peer);
4979 if (processed_orphan)
return true;
4984 LOCK(peer->m_getdata_requests_mutex);
4985 if (!peer->m_getdata_requests.empty())
return true;
4998 bool fMoreWork = poll_result->second;
5009 if (m_opts.capture_messages) {
5014 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5015 if (interruptMsgProc)
return false;
5017 LOCK(peer->m_getdata_requests_mutex);
5018 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5025 LOCK(m_tx_download_mutex);
5026 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
5027 }
catch (
const std::exception& e) {
5036void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5040 CNodeState &state = *State(pto.
GetId());
5049 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5051 if (state.m_chain_sync.m_timeout != 0
s) {
5052 state.m_chain_sync.m_timeout = 0
s;
5053 state.m_chain_sync.m_work_header =
nullptr;
5054 state.m_chain_sync.m_sent_getheaders =
false;
5056 }
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)) {
5064 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5065 state.m_chain_sync.m_sent_getheaders =
false;
5066 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5070 if (state.m_chain_sync.m_sent_getheaders) {
5072 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5075 assert(state.m_chain_sync.m_work_header);
5080 MaybeSendGetHeaders(pto,
5081 GetLocator(state.m_chain_sync.m_work_header->pprev),
5083 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());
5084 state.m_chain_sync.m_sent_getheaders =
true;
5096void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5105 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5109 if (pnode->
GetId() > youngest_peer.first) {
5110 next_youngest_peer = youngest_peer;
5111 youngest_peer.first = pnode->GetId();
5112 youngest_peer.second = pnode->m_last_block_time;
5115 NodeId to_disconnect = youngest_peer.first;
5116 if (youngest_peer.second > next_youngest_peer.second) {
5119 to_disconnect = next_youngest_peer.first;
5128 CNodeState *node_state = State(pnode->
GetId());
5129 if (node_state ==
nullptr ||
5132 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5136 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5152 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5155 AssertLockHeld(::cs_main);
5159 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5160 CNodeState *state = State(pnode->GetId());
5161 if (state == nullptr) return;
5163 if (state->m_chain_sync.m_protect) return;
5166 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5167 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5168 worst_peer = pnode->GetId();
5169 oldest_block_announcement = state->m_last_block_announcement;
5172 if (worst_peer != -1) {
5181 CNodeState &state = *State(pnode->
GetId());
5183 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5187 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5204void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5208 auto now{GetTime<std::chrono::seconds>()};
5210 EvictExtraOutboundPeers(now);
5212 if (now > m_stale_tip_check_time) {
5216 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5225 if (!m_initial_sync_finished && CanDirectFetch()) {
5227 m_initial_sync_finished =
true;
5231void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5234 peer.m_ping_nonce_sent &&
5244 bool pingSend =
false;
5246 if (peer.m_ping_queued) {
5251 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5260 }
while (
nonce == 0);
5261 peer.m_ping_queued =
false;
5262 peer.m_ping_start = now;
5264 peer.m_ping_nonce_sent =
nonce;
5268 peer.m_ping_nonce_sent = 0;
5274void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5277 if (!peer.m_addr_relay_enabled)
return;
5279 LOCK(peer.m_addr_send_times_mutex);
5282 peer.m_next_local_addr_send < current_time) {
5289 if (peer.m_next_local_addr_send != 0us) {
5290 peer.m_addr_known->reset();
5293 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5294 PushAddress(peer, local_addr);
5300 if (current_time <= peer.m_next_addr_send)
return;
5313 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5314 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5317 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5318 peer.m_addrs_to_send.end());
5321 if (peer.m_addrs_to_send.empty())
return;
5323 if (peer.m_wants_addrv2) {
5328 peer.m_addrs_to_send.clear();
5331 if (peer.m_addrs_to_send.capacity() > 40) {
5332 peer.m_addrs_to_send.shrink_to_fit();
5336void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5344 CNodeState &state = *State(
node.GetId());
5345 if (state.pindexBestKnownBlock !=
nullptr &&
5352 peer.m_sent_sendheaders =
true;
5357void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5359 if (m_opts.ignore_incoming_txs)
return;
5375 if (peer.m_fee_filter_sent == MAX_FILTER) {
5378 peer.m_next_send_feefilter = 0us;
5381 if (current_time > peer.m_next_send_feefilter) {
5382 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5385 if (filterToSend != peer.m_fee_filter_sent) {
5387 peer.m_fee_filter_sent = filterToSend;
5394 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5400class CompareInvMempoolOrder
5404 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5406 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5415bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5425bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5430 if (
node.IsBlockOnlyConn())
return false;
5432 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5436 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5442bool PeerManagerImpl::SendMessages(
CNode* pto)
5447 PeerRef peer = GetPeerRef(pto->
GetId());
5448 if (!peer)
return false;
5453 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5456 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5457 PushNodeVersion(*pto, *peer);
5458 peer->m_outbound_version_message_sent =
true;
5465 const auto current_time{GetTime<std::chrono::microseconds>()};
5473 MaybeSendPing(*pto, *peer, current_time);
5478 MaybeSendAddr(*pto, *peer, current_time);
5480 MaybeSendSendHeaders(*pto, *peer);
5485 CNodeState &state = *State(pto->
GetId());
5488 if (m_chainman.m_best_header ==
nullptr) {
5495 bool sync_blocks_and_headers_from_peer =
false;
5496 if (state.fPreferredDownload) {
5497 sync_blocks_and_headers_from_peer =
true;
5508 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5509 sync_blocks_and_headers_from_peer =
true;
5515 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5516 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5524 if (pindexStart->
pprev)
5525 pindexStart = pindexStart->
pprev;
5526 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5529 state.fSyncStarted =
true;
5553 LOCK(peer->m_block_inv_mutex);
5554 std::vector<CBlock> vHeaders;
5555 bool fRevertToInv = ((!peer->m_prefers_headers &&
5556 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5559 ProcessBlockAvailability(pto->
GetId());
5561 if (!fRevertToInv) {
5562 bool fFoundStartingHeader =
false;
5566 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5571 fRevertToInv =
true;
5574 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5586 fRevertToInv =
true;
5589 pBestIndex = pindex;
5590 if (fFoundStartingHeader) {
5593 }
else if (PeerHasHeader(&state, pindex)) {
5595 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5598 fFoundStartingHeader =
true;
5603 fRevertToInv =
true;
5608 if (!fRevertToInv && !vHeaders.empty()) {
5609 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5613 vHeaders.front().GetHash().ToString(), pto->
GetId());
5615 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5617 LOCK(m_most_recent_block_mutex);
5618 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5622 if (cached_cmpctblock_msg.has_value()) {
5623 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5631 state.pindexBestHeaderSent = pBestIndex;
5632 }
else if (peer->m_prefers_headers) {
5633 if (vHeaders.size() > 1) {
5636 vHeaders.front().GetHash().ToString(),
5637 vHeaders.back().GetHash().ToString(), pto->
GetId());
5640 vHeaders.front().GetHash().ToString(), pto->
GetId());
5643 state.pindexBestHeaderSent = pBestIndex;
5645 fRevertToInv =
true;
5651 if (!peer->m_blocks_for_headers_relay.empty()) {
5652 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5665 if (!PeerHasHeader(&state, pindex)) {
5666 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5672 peer->m_blocks_for_headers_relay.clear();
5678 std::vector<CInv> vInv;
5680 LOCK(peer->m_block_inv_mutex);
5684 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5691 peer->m_blocks_for_inv_relay.clear();
5694 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5695 LOCK(tx_relay->m_tx_inventory_mutex);
5698 if (tx_relay->m_next_inv_send_time < current_time) {
5699 fSendTrickle =
true;
5709 LOCK(tx_relay->m_bloom_filter_mutex);
5710 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5714 if (fSendTrickle && tx_relay->m_send_mempool) {
5715 auto vtxinfo = m_mempool.
infoAll();
5716 tx_relay->m_send_mempool =
false;
5717 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5719 LOCK(tx_relay->m_bloom_filter_mutex);
5721 for (
const auto& txinfo : vtxinfo) {
5722 const Txid& txid{txinfo.tx->GetHash()};
5723 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
5724 const auto inv = peer->m_wtxid_relay ?
5727 tx_relay->m_tx_inventory_to_send.erase(wtxid);
5730 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5733 if (tx_relay->m_bloom_filter) {
5734 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5736 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5737 vInv.push_back(inv);
5748 std::vector<std::set<Wtxid>::iterator> vInvTx;
5749 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5750 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5751 vInvTx.push_back(it);
5753 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5756 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
5757 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5760 unsigned int nRelayedTransactions = 0;
5761 LOCK(tx_relay->m_bloom_filter_mutex);
5764 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5766 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5767 std::set<Wtxid>::iterator it = vInvTx.back();
5771 tx_relay->m_tx_inventory_to_send.erase(it);
5773 auto txinfo = m_mempool.
info(wtxid);
5780 const auto inv = peer->m_wtxid_relay ?
5782 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
5784 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
5788 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5791 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5793 vInv.push_back(inv);
5794 nRelayedTransactions++;
5799 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5804 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5811 auto stalling_timeout = m_block_stalling_timeout.load();
5812 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5821 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5831 if (state.vBlocksInFlight.size() > 0) {
5832 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5833 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5841 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5843 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5844 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5861 state.fSyncStarted =
false;
5863 peer->m_headers_sync_timeout = 0us;
5869 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5875 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5880 std::vector<CInv> vGetData;
5882 std::vector<const CBlockIndex*> vToDownload;
5884 auto get_inflight_budget = [&state]() {
5890 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5895 TryDownloadingHistoricalBlocks(
5897 get_inflight_budget(),
5898 vToDownload, from_tip,
5899 Assert(m_chainman.GetSnapshotBaseBlock()));
5902 uint32_t nFetchFlags = GetFetchFlags(*peer);
5904 BlockRequested(pto->
GetId(), *pindex);
5908 if (state.vBlocksInFlight.empty() && staller != -1) {
5909 if (State(staller)->m_stalling_since == 0us) {
5910 State(staller)->m_stalling_since = current_time;
5920 LOCK(m_tx_download_mutex);
5921 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
5930 if (!vGetData.empty())
5933 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 Consensus::Params & GetConsensus() const
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool GetTryNewOutboundPeer() const
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(const std::string &node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
bool CheckIncomingNonce(uint64_t nonce)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per 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
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
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 CompareDepthAndScore(const Wtxid &hasha, const Wtxid &hashb) const
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 BlockConnected(ChainstateRole role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
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.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
const CBlockIndex * GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The tip of the background sync chain.
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
bool ProcessNewBlockHeaders(std::span< const CBlockHeader > headers, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const arith_uint256 & MinimumChainWork() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Double ended buffer combining vector and stream-like interfaces.
void ignore(size_t num_ignore)
uint64_t rand64() noexcept
Generate a random 64-bit integer.
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 std::optional< std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, DataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
virtual 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 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
bool ReadRawBlock(std::vector< std::byte > &block, const FlatFilePos &pos) 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
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.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
#define LogDebug(category,...)
Transaction validation functions.
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
TRACEPOINT_SEMAPHORE(net, inbound_message)
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" command for wtxid-based relay starts with this version
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
std::chrono::seconds time_offset
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
@ DIFFERENT_WITNESS
Valid, transaction was already in the mempool.
@ INVALID
Fully validated, valid.
const std::list< CTransactionRef > m_replaced_transactions
Mempool transactions replaced by the tx.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
Validation result for package mempool acceptance.
PackageValidationState m_state
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
std::chrono::seconds median_outbound_time_offset
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
std::vector< NodeId > m_senders
std::string ToString() const
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
#define TRACEPOINT(context,...)
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...