73#include <initializer_list>
206 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
240 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
243 const bool m_is_inbound;
246 Mutex m_misbehavior_mutex;
248 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
251 Mutex m_block_inv_mutex;
255 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
259 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
270 std::atomic<int> m_starting_height{-1};
273 std::atomic<uint64_t> m_ping_nonce_sent{0};
275 std::atomic<std::chrono::microseconds> m_ping_start{0us};
277 std::atomic<bool> m_ping_queued{
false};
280 std::atomic<bool> m_wtxid_relay{
false};
292 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
294 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
305 std::set<uint256> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
309 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
312 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
318 std::atomic<CAmount> m_fee_filter_received{0};
324 LOCK(m_tx_relay_mutex);
326 m_tx_relay = std::make_unique<Peer::TxRelay>();
327 return m_tx_relay.get();
332 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
361 std::atomic_bool m_addr_relay_enabled{
false};
365 mutable Mutex m_addr_send_times_mutex;
367 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
369 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
372 std::atomic_bool m_wants_addrv2{
false};
381 std::atomic<uint64_t> m_addr_rate_limited{0};
383 std::atomic<uint64_t> m_addr_processed{0};
389 Mutex m_getdata_requests_mutex;
391 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
397 Mutex m_headers_sync_mutex;
400 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
403 std::atomic<bool> m_sent_sendheaders{
false};
413 std::atomic<std::chrono::seconds> m_time_offset{0
s};
417 , m_our_services{our_services}
418 , m_is_inbound{is_inbound}
422 mutable Mutex m_tx_relay_mutex;
425 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
428using PeerRef = std::shared_ptr<Peer>;
440 uint256 hashLastUnknownBlock{};
446 bool fSyncStarted{
false};
448 std::chrono::microseconds m_stalling_since{0us};
449 std::list<QueuedBlock> vBlocksInFlight;
451 std::chrono::microseconds m_downloading_since{0us};
453 bool fPreferredDownload{
false};
455 bool m_requested_hb_cmpctblocks{
false};
457 bool m_provides_cmpctblocks{
false};
483 struct ChainSyncTimeoutState {
485 std::chrono::seconds m_timeout{0
s};
489 bool m_sent_getheaders{
false};
491 bool m_protect{
false};
494 ChainSyncTimeoutState m_chain_sync;
497 int64_t m_last_block_announcement{0};
526 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
540 void SetBestBlock(
int height,
std::chrono::seconds time)
override
542 m_best_height = height;
543 m_best_block_time = time;
547 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
548 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
572 void Misbehaving(Peer& peer,
const std::string& message);
583 bool via_compact_block,
const std::string& message =
"")
598 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
612 bool first_time_failure)
637 bool ProcessOrphanTx(Peer& peer)
647 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
649 bool via_compact_block)
661 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
680 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
694 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
709 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
711 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
718 template <
typename... Args>
719 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
725 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
731 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
774 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
777 std::atomic<int> m_best_height{-1};
779 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
787 const Options m_opts;
789 bool RejectIncomingTxs(
const CNode& peer)
const;
797 mutable Mutex m_peer_mutex;
804 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
814 uint32_t GetFetchFlags(
const Peer& peer)
const;
816 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
833 std::atomic<int> m_wtxid_relay_peers{0};
850 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
855 Mutex m_most_recent_block_mutex;
856 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
857 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
859 std::unique_ptr<const std::map<uint256, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
863 Mutex m_headers_presync_mutex;
871 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
873 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
877 std::atomic_bool m_headers_presync_should_signal{
false};
947 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
953 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
958 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
983 std::vector<CTransactionRef> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
985 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
997 int64_t ApproximateBestBlockDepth() const;
1007 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1025 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1027 const
uint256& stop_hash, uint32_t max_height_diff,
1075 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1078const CNodeState* PeerManagerImpl::State(
NodeId pnode)
const
1080 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1081 if (it == m_node_states.end())
1086CNodeState* PeerManagerImpl::State(
NodeId pnode)
1088 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1096static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1101void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1103 assert(peer.m_addr_known);
1104 peer.m_addr_known->insert(addr.
GetKey());
1107void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1112 assert(peer.m_addr_known);
1113 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1115 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1117 peer.m_addrs_to_send.push_back(addr);
1122static void AddKnownTx(Peer& peer,
const uint256& hash)
1124 auto tx_relay = peer.GetTxRelay();
1125 if (!tx_relay)
return;
1127 LOCK(tx_relay->m_tx_inventory_mutex);
1128 tx_relay->m_tx_inventory_known_filter.insert(hash);
1132static bool CanServeBlocks(
const Peer& peer)
1139static bool IsLimitedPeer(
const Peer& peer)
1146static bool CanServeWitnesses(
const Peer& peer)
1151std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1152 std::chrono::seconds average_interval)
1154 if (m_next_inv_to_inbounds.load() < now) {
1158 m_next_inv_to_inbounds = now + m_rng.rand_exp_duration(average_interval);
1160 return m_next_inv_to_inbounds;
1163bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1165 return mapBlocksInFlight.count(hash);
1168bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1170 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1171 auto [nodeid, block_it] = range.first->second;
1172 PeerRef peer{GetPeerRef(nodeid)};
1173 if (peer && !peer->m_is_inbound)
return true;
1179void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1181 auto range = mapBlocksInFlight.equal_range(hash);
1182 if (range.first == range.second) {
1190 while (range.first != range.second) {
1191 const auto& [node_id, list_it]{range.first->second};
1193 if (from_peer && *from_peer != node_id) {
1198 CNodeState& state = *
Assert(State(node_id));
1200 if (state.vBlocksInFlight.begin() == list_it) {
1202 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1204 state.vBlocksInFlight.erase(list_it);
1206 if (state.vBlocksInFlight.empty()) {
1208 m_peers_downloading_from--;
1210 state.m_stalling_since = 0us;
1212 range.first = mapBlocksInFlight.erase(range.first);
1216bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1220 CNodeState *state = State(nodeid);
1221 assert(state !=
nullptr);
1226 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1227 if (range.first->second.first == nodeid) {
1229 *pit = &range.first->second.second;
1236 RemoveBlockRequest(hash, nodeid);
1238 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1239 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1240 if (state->vBlocksInFlight.size() == 1) {
1242 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1243 m_peers_downloading_from++;
1245 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1247 *pit = &itInFlight->second.second;
1252void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1259 if (m_opts.ignore_incoming_txs)
return;
1261 CNodeState* nodestate = State(nodeid);
1262 PeerRef peer{GetPeerRef(nodeid)};
1263 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1268 int num_outbound_hb_peers = 0;
1269 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1270 if (*it == nodeid) {
1271 lNodesAnnouncingHeaderAndIDs.erase(it);
1272 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1275 PeerRef peer_ref{GetPeerRef(*it)};
1276 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1278 if (peer && peer->m_is_inbound) {
1281 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1282 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1283 if (remove_peer && !remove_peer->m_is_inbound) {
1286 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1292 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1295 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1296 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1298 pnodeStop->m_bip152_highbandwidth_to = false;
1301 lNodesAnnouncingHeaderAndIDs.pop_front();
1306 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1311bool PeerManagerImpl::TipMayBeStale()
1315 if (m_last_tip_update.load() == 0
s) {
1316 m_last_tip_update = GetTime<std::chrono::seconds>();
1318 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1321int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1326bool PeerManagerImpl::CanDirectFetch()
1333 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1335 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1340void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1341 CNodeState *state = State(nodeid);
1342 assert(state !=
nullptr);
1344 if (!state->hashLastUnknownBlock.IsNull()) {
1347 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1348 state->pindexBestKnownBlock = pindex;
1350 state->hashLastUnknownBlock.SetNull();
1355void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1356 CNodeState *state = State(nodeid);
1357 assert(state !=
nullptr);
1359 ProcessBlockAvailability(nodeid);
1364 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1365 state->pindexBestKnownBlock = pindex;
1369 state->hashLastUnknownBlock = hash;
1374void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1379 vBlocks.reserve(vBlocks.size() +
count);
1380 CNodeState *state = State(peer.m_id);
1381 assert(state !=
nullptr);
1384 ProcessBlockAvailability(peer.m_id);
1386 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1394 const CBlockIndex* snap_base{m_chainman.GetSnapshotBaseBlock()};
1395 if (snap_base && state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1396 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1403 if (state->pindexLastCommonBlock ==
nullptr ||
1404 (snap_base && state->pindexLastCommonBlock->nHeight < snap_base->nHeight)) {
1405 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1410 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1411 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1414 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1420 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1423void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1428 if (vBlocks.size() >=
count) {
1432 vBlocks.reserve(
count);
1433 CNodeState *state =
Assert(State(peer.m_id));
1435 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1452void 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)
1454 std::vector<const CBlockIndex*> vToFetch;
1455 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1456 bool is_limited_peer = IsLimitedPeer(peer);
1458 while (pindexWalk->
nHeight < nMaxHeight) {
1462 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1463 vToFetch.resize(nToFetch);
1464 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1465 vToFetch[nToFetch - 1] = pindexWalk;
1466 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1467 vToFetch[i - 1] = vToFetch[i]->
pprev;
1487 state->pindexLastCommonBlock = pindex;
1494 if (waitingfor == -1) {
1496 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1502 if (pindex->
nHeight > nWindowEnd) {
1504 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1506 if (nodeStaller) *nodeStaller = waitingfor;
1516 vBlocks.push_back(pindex);
1517 if (vBlocks.size() ==
count) {
1526void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1528 uint64_t my_services{peer.m_our_services};
1529 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1531 const int nNodeStartingHeight{m_best_height};
1538 const bool tx_relay{!RejectIncomingTxs(pnode)};
1545 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);
1551void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1554 CNodeState *state = State(
node);
1555 if (state) state->m_last_block_announcement = time_in_seconds;
1563 m_node_states.try_emplace(m_node_states.end(), nodeid);
1565 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1571 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1574 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1578void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1582 for (
const auto& txid : unbroadcast_txids) {
1585 if (tx !=
nullptr) {
1586 RelayTransaction(txid, tx->GetWitnessHash());
1595 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1598void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1609 PeerRef peer = RemovePeer(nodeid);
1611 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1612 assert(m_wtxid_relay_peers >= 0);
1614 CNodeState *state = State(nodeid);
1615 assert(state !=
nullptr);
1617 if (state->fSyncStarted)
1620 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1621 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1622 while (range.first != range.second) {
1623 auto [node_id, list_it] = range.first->second;
1624 if (node_id != nodeid) {
1627 range.first = mapBlocksInFlight.erase(range.first);
1632 LOCK(m_tx_download_mutex);
1633 m_txdownloadman.DisconnectedPeer(nodeid);
1635 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1636 m_num_preferred_download_peers -= state->fPreferredDownload;
1637 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1638 assert(m_peers_downloading_from >= 0);
1639 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1640 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1642 m_node_states.erase(nodeid);
1644 if (m_node_states.empty()) {
1646 assert(mapBlocksInFlight.empty());
1647 assert(m_num_preferred_download_peers == 0);
1648 assert(m_peers_downloading_from == 0);
1649 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1650 assert(m_wtxid_relay_peers == 0);
1651 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1654 if (
node.fSuccessfullyConnected &&
1655 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1662 LOCK(m_headers_presync_mutex);
1663 m_headers_presync_stats.erase(nodeid);
1668bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1671 return !(GetDesirableServiceFlags(services) & (~services));
1685PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1688 auto it = m_peer_map.find(
id);
1689 return it != m_peer_map.end() ? it->second :
nullptr;
1692PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1696 auto it = m_peer_map.find(
id);
1697 if (it != m_peer_map.end()) {
1698 ret = std::move(it->second);
1699 m_peer_map.erase(it);
1708 const CNodeState* state = State(nodeid);
1709 if (state ==
nullptr)
1711 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1712 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1713 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1719 PeerRef peer = GetPeerRef(nodeid);
1720 if (peer ==
nullptr)
return false;
1729 auto ping_wait{0us};
1730 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1731 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1734 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1747 LOCK(peer->m_headers_sync_mutex);
1748 if (peer->m_headers_sync) {
1757std::vector<TxOrphanage::OrphanTxBase> PeerManagerImpl::GetOrphanTransactions()
1759 LOCK(m_tx_download_mutex);
1760 return m_txdownloadman.GetOrphanTransactions();
1767 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1771void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1773 if (m_opts.max_extra_txs <= 0)
1775 if (!vExtraTxnForCompact.size())
1776 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1777 vExtraTxnForCompact[vExtraTxnForCompactIt] = tx;
1778 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1781void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1783 LOCK(peer.m_misbehavior_mutex);
1785 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1786 peer.m_should_discourage =
true;
1795 bool via_compact_block,
const std::string& message)
1797 PeerRef peer{GetPeerRef(nodeid)};
1808 if (!via_compact_block) {
1809 if (peer) Misbehaving(*peer, message);
1817 if (peer && !via_compact_block && !peer->m_is_inbound) {
1818 if (peer) Misbehaving(*peer, message);
1825 if (peer) Misbehaving(*peer, message);
1829 if (peer) Misbehaving(*peer, message);
1834 if (message !=
"") {
1841 PeerRef peer{GetPeerRef(nodeid)};
1847 if (peer) Misbehaving(*peer,
"");
1865bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1874std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1879 PeerRef peer = GetPeerRef(peer_id);
1880 if (peer ==
nullptr)
return "Peer does not exist";
1883 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1888 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1891 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1903 if (!success)
return "Peer not fully connected";
1907 return std::nullopt;
1914 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1920 : m_rng{opts.deterministic_rng},
1922 m_chainparams(chainman.GetParams()),
1926 m_chainman(chainman),
1928 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.max_orphan_txs, opts.deterministic_rng}),
1929 m_warnings{warnings},
1934 if (opts.reconcile_txs) {
1939void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1950 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1953void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
1961 LOCK(m_tx_download_mutex);
1965 m_txdownloadman.ActiveTipChange();
1975void PeerManagerImpl::BlockConnected(
1977 const std::shared_ptr<const CBlock>& pblock,
1982 m_last_tip_update = GetTime<std::chrono::seconds>();
1985 auto stalling_timeout = m_block_stalling_timeout.load();
1989 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1999 LOCK(m_tx_download_mutex);
2000 m_txdownloadman.BlockConnected(pblock);
2003void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2005 LOCK(m_tx_download_mutex);
2006 m_txdownloadman.BlockDisconnected();
2013void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2015 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2019 if (pindex->
nHeight <= m_highest_fast_announce)
2021 m_highest_fast_announce = pindex->
nHeight;
2025 uint256 hashBlock(pblock->GetHash());
2026 const std::shared_future<CSerializedNetMsg> lazy_ser{
2030 auto most_recent_block_txs = std::make_unique<std::map<uint256, CTransactionRef>>();
2031 for (
const auto& tx : pblock->vtx) {
2032 most_recent_block_txs->emplace(tx->GetHash(), tx);
2033 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2036 LOCK(m_most_recent_block_mutex);
2037 m_most_recent_block_hash = hashBlock;
2038 m_most_recent_block = pblock;
2039 m_most_recent_compact_block = pcmpctblock;
2040 m_most_recent_block_txs = std::move(most_recent_block_txs);
2048 ProcessBlockAvailability(pnode->
GetId());
2049 CNodeState &state = *State(pnode->
GetId());
2052 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2054 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2055 hashBlock.ToString(), pnode->
GetId());
2058 PushMessage(*pnode, ser_cmpctblock.Copy());
2059 state.pindexBestHeaderSent = pindex;
2068void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2070 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2073 if (fInitialDownload)
return;
2076 std::vector<uint256> vHashes;
2078 while (pindexToAnnounce != pindexFork) {
2080 pindexToAnnounce = pindexToAnnounce->
pprev;
2090 for (
auto& it : m_peer_map) {
2091 Peer& peer = *it.second;
2092 LOCK(peer.m_block_inv_mutex);
2093 for (
const uint256& hash : vHashes | std::views::reverse) {
2094 peer.m_blocks_for_headers_relay.push_back(hash);
2111 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2116 it != mapBlockSource.end() &&
2117 State(it->second.first)) {
2118 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2128 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2129 if (it != mapBlockSource.end()) {
2130 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2133 if (it != mapBlockSource.end())
2134 mapBlockSource.erase(it);
2142bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2147void PeerManagerImpl::SendPings()
2150 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2153void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2156 for(
auto& it : m_peer_map) {
2157 Peer& peer = *it.second;
2158 auto tx_relay = peer.GetTxRelay();
2159 if (!tx_relay)
continue;
2161 LOCK(tx_relay->m_tx_inventory_mutex);
2167 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2169 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2170 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2171 tx_relay->m_tx_inventory_to_send.insert(hash);
2176void PeerManagerImpl::RelayAddress(
NodeId originator,
2192 const auto current_time{GetTime<std::chrono::seconds>()};
2200 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2202 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2203 assert(nRelayNodes <= best.size());
2207 for (
auto& [
id, peer] : m_peer_map) {
2208 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2210 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2211 if (hashKey > best[i].first) {
2212 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2213 best[i] = std::make_pair(hashKey, peer.get());
2220 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2221 PushAddress(*best[i].second, addr);
2225void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2227 std::shared_ptr<const CBlock> a_recent_block;
2228 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2230 LOCK(m_most_recent_block_mutex);
2231 a_recent_block = m_most_recent_block;
2232 a_recent_compact_block = m_most_recent_compact_block;
2235 bool need_activate_chain =
false;
2247 need_activate_chain =
true;
2251 if (need_activate_chain) {
2253 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2260 bool can_direct_fetch{
false};
2268 if (!BlockRequestAllowed(pindex)) {
2269 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2296 can_direct_fetch = CanDirectFetch();
2300 std::shared_ptr<const CBlock> pblock;
2301 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2302 pblock = a_recent_block;
2306 std::vector<std::byte> block_data;
2320 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2330 pblock = pblockRead;
2338 bool sendMerkleBlock =
false;
2340 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2341 LOCK(tx_relay->m_bloom_filter_mutex);
2342 if (tx_relay->m_bloom_filter) {
2343 sendMerkleBlock =
true;
2344 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2347 if (sendMerkleBlock) {
2355 typedef std::pair<unsigned int, uint256> PairType;
2367 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2380 LOCK(peer.m_block_inv_mutex);
2382 if (inv.
hash == peer.m_continuation_block) {
2386 std::vector<CInv> vInv;
2387 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2389 peer.m_continuation_block.SetNull();
2397 auto txinfo = m_mempool.
info_for_relay(gtxid, tx_relay.m_last_inv_sequence);
2399 return std::move(txinfo.tx);
2404 LOCK(m_most_recent_block_mutex);
2405 if (m_most_recent_block_txs !=
nullptr) {
2406 auto it = m_most_recent_block_txs->find(gtxid.
GetHash());
2407 if (it != m_most_recent_block_txs->end())
return it->second;
2414void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2418 auto tx_relay = peer.GetTxRelay();
2420 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2421 std::vector<CInv> vNotFound;
2426 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2427 if (interruptMsgProc)
return;
2432 const CInv &inv = *it++;
2434 if (tx_relay ==
nullptr) {
2444 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2447 vNotFound.push_back(inv);
2453 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2454 const CInv &inv = *it++;
2456 ProcessGetBlockData(pfrom, peer, inv);
2465 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2467 if (!vNotFound.empty()) {
2486uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2488 uint32_t nFetchFlags = 0;
2489 if (CanServeWitnesses(peer)) {
2498 unsigned int tx_requested_size = 0;
2499 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2501 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2505 tx_requested_size += resp.txn[i]->GetTotalSize();
2512bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2516 Misbehaving(peer,
"header with invalid proof of work");
2521 if (!CheckHeadersAreContinuous(headers)) {
2522 Misbehaving(peer,
"non-continuous headers sequence");
2547void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2548 const std::vector<CBlockHeader>& headers)
2552 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2553 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2555 headers[0].hashPrevBlock.ToString(),
2556 best_header->nHeight,
2566bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2570 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2573 hashLastBlock = header.GetHash();
2578bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2580 if (peer.m_headers_sync) {
2581 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2583 if (result.success) peer.m_last_getheaders_timestamp = {};
2584 if (result.request_more) {
2585 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2587 Assume(!locator.vHave.empty());
2590 if (!locator.vHave.empty()) {
2593 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2596 locator.vHave.front().ToString(), pfrom.
GetId());
2601 peer.m_headers_sync.reset(
nullptr);
2606 LOCK(m_headers_presync_mutex);
2607 m_headers_presync_stats.erase(pfrom.
GetId());
2610 HeadersPresyncStats stats;
2611 stats.first = peer.m_headers_sync->GetPresyncWork();
2613 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2614 peer.m_headers_sync->GetPresyncTime()};
2618 LOCK(m_headers_presync_mutex);
2619 m_headers_presync_stats[pfrom.
GetId()] = stats;
2620 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2621 bool best_updated =
false;
2622 if (best_it == m_headers_presync_stats.end()) {
2626 const HeadersPresyncStats* stat_best{
nullptr};
2627 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2628 if (!stat_best || stat > *stat_best) {
2633 m_headers_presync_bestpeer = peer_best;
2634 best_updated = (peer_best == pfrom.
GetId());
2635 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2637 m_headers_presync_bestpeer = pfrom.
GetId();
2638 best_updated =
true;
2640 if (best_updated && stats.second.has_value()) {
2642 m_headers_presync_should_signal =
true;
2646 if (result.success) {
2649 headers.swap(result.pow_validated_headers);
2652 return result.success;
2660bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2667 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2671 if (total_work < minimum_chain_work) {
2675 if (headers.size() == m_opts.max_headers_result) {
2685 LOCK(peer.m_headers_sync_mutex);
2687 chain_start_header, minimum_chain_work));
2692 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2706bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2708 if (header ==
nullptr) {
2710 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2718bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2726 peer.m_last_getheaders_timestamp = current_time;
2737void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2740 CNodeState *nodestate = State(pfrom.
GetId());
2743 std::vector<const CBlockIndex*> vToFetch;
2751 vToFetch.push_back(pindexWalk);
2753 pindexWalk = pindexWalk->
pprev;
2764 std::vector<CInv> vGetData;
2766 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2771 uint32_t nFetchFlags = GetFetchFlags(peer);
2773 BlockRequested(pfrom.
GetId(), *pindex);
2777 if (vGetData.size() > 1) {
2782 if (vGetData.size() > 0) {
2783 if (!m_opts.ignore_incoming_txs &&
2784 nodestate->m_provides_cmpctblocks &&
2785 vGetData.size() == 1 &&
2786 mapBlocksInFlight.size() == 1 &&
2802void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2803 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2806 CNodeState *nodestate = State(pfrom.
GetId());
2815 nodestate->m_last_block_announcement =
GetTime();
2823 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2845 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) {
2847 nodestate->m_chain_sync.m_protect =
true;
2848 ++m_outbound_peers_with_protect_from_disconnect;
2853void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2854 std::vector<CBlockHeader>&& headers,
2855 bool via_compact_block)
2857 size_t nCount = headers.size();
2864 LOCK(peer.m_headers_sync_mutex);
2865 if (peer.m_headers_sync) {
2866 peer.m_headers_sync.reset(
nullptr);
2867 LOCK(m_headers_presync_mutex);
2868 m_headers_presync_stats.erase(pfrom.
GetId());
2872 peer.m_last_getheaders_timestamp = {};
2880 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2895 bool already_validated_work =
false;
2898 bool have_headers_sync =
false;
2900 LOCK(peer.m_headers_sync_mutex);
2902 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2914 if (headers.empty()) {
2918 have_headers_sync = !!peer.m_headers_sync;
2923 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2925 if (!headers_connect_blockindex) {
2929 HandleUnconnectingHeaders(pfrom, peer, headers);
2936 peer.m_last_getheaders_timestamp = {};
2946 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2947 already_validated_work =
true;
2955 already_validated_work =
true;
2961 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2962 chain_start_header, headers)) {
2974 bool received_new_header{last_received_header ==
nullptr};
2980 state, &pindexLast)};
2983 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2989 if (processed && received_new_header) {
2990 LogBlockHeader(*pindexLast, pfrom,
false);
2994 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
2996 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2998 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
3002 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3005 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3011 bool first_time_failure)
3017 PeerRef peer{GetPeerRef(nodeid)};
3020 ptx->GetHash().ToString(),
3021 ptx->GetWitnessHash().ToString(),
3025 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3028 AddToCompactExtraTransactions(ptx);
3030 for (
const Txid& parent_txid : unique_parents) {
3031 if (peer) AddKnownTx(*peer, parent_txid);
3034 MaybePunishNodeForTx(nodeid, state);
3036 return package_to_validate;
3039void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3045 m_txdownloadman.MempoolAcceptedTx(tx);
3049 tx->GetHash().ToString(),
3050 tx->GetWitnessHash().ToString(),
3053 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3056 AddToCompactExtraTransactions(removedTx);
3066 const auto&
package = package_to_validate.m_txns;
3067 const auto& senders = package_to_validate.
m_senders;
3070 m_txdownloadman.MempoolRejectedPackage(package);
3073 if (!
Assume(package.size() == 2))
return;
3077 auto package_iter = package.rbegin();
3078 auto senders_iter = senders.rbegin();
3079 while (package_iter != package.rend()) {
3080 const auto& tx = *package_iter;
3081 const NodeId nodeid = *senders_iter;
3082 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3086 const auto& tx_result = it_result->second;
3087 switch (tx_result.m_result_type) {
3090 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3100 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3118bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3125 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3128 const Txid& orphanHash = porphanTx->GetHash();
3129 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3146 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3155bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3157 const uint256& stop_hash, uint32_t max_height_diff,
3161 const bool supported_filter_type =
3164 if (!supported_filter_type) {
3166 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg(
fLogIPs));
3167 node.fDisconnect =
true;
3176 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3179 node.fDisconnect =
true;
3184 uint32_t stop_height = stop_index->
nHeight;
3185 if (start_height > stop_height) {
3187 "start height %d and stop height %d, %s\n",
3188 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3189 node.fDisconnect =
true;
3192 if (stop_height - start_height >= max_height_diff) {
3194 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3195 node.fDisconnect =
true;
3200 if (!filter_index) {
3210 uint8_t filter_type_ser;
3211 uint32_t start_height;
3214 vRecv >> filter_type_ser >> start_height >> stop_hash;
3220 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3225 std::vector<BlockFilter> filters;
3227 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3232 for (
const auto& filter : filters) {
3239 uint8_t filter_type_ser;
3240 uint32_t start_height;
3243 vRecv >> filter_type_ser >> start_height >> stop_hash;
3249 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3255 if (start_height > 0) {
3257 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3259 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3265 std::vector<uint256> filter_hashes;
3267 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3281 uint8_t filter_type_ser;
3284 vRecv >> filter_type_ser >> stop_hash;
3290 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3291 std::numeric_limits<uint32_t>::max(),
3292 stop_index, filter_index)) {
3300 for (
int i = headers.size() - 1; i >= 0; i--) {
3305 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3319 bool new_block{
false};
3320 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3322 node.m_last_block_time = GetTime<std::chrono::seconds>();
3327 RemoveBlockRequest(block->GetHash(), std::nullopt);
3330 mapBlockSource.erase(block->GetHash());
3334void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3336 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3337 bool fBlockRead{
false};
3341 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3342 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3343 bool requested_block_from_this_peer{
false};
3346 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3348 while (range_flight.first != range_flight.second) {
3349 auto [node_id, block_it] = range_flight.first->second;
3350 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3351 requested_block_from_this_peer =
true;
3354 range_flight.first++;
3357 if (!requested_block_from_this_peer) {
3366 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3369 if (first_in_flight) {
3371 std::vector<CInv> invs;
3376 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3405 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3420void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3432 "Saw new %sheader hash=%s height=%d peer=%d%s",
3433 via_compact_block ?
"cmpctblock " :
"",
3446void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3447 const std::chrono::microseconds time_received,
3448 const std::atomic<bool>& interruptMsgProc)
3454 PeerRef peer = GetPeerRef(pfrom.
GetId());
3455 if (peer ==
nullptr)
return;
3465 uint64_t nNonce = 1;
3468 std::string cleanSubVer;
3469 int starting_height = -1;
3472 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3487 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3489 GetDesirableServiceFlags(nServices),
3502 if (!vRecv.
empty()) {
3510 if (!vRecv.
empty()) {
3511 std::string strSubVer;
3515 if (!vRecv.
empty()) {
3516 vRecv >> starting_height;
3536 PushNodeVersion(pfrom, *peer);
3549 if (greatest_common_version >= 70016) {
3558 peer->m_their_services = nServices;
3562 pfrom.cleanSubVer = cleanSubVer;
3564 peer->m_starting_height = starting_height;
3574 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3575 auto*
const tx_relay = peer->SetTxRelay();
3577 LOCK(tx_relay->m_bloom_filter_mutex);
3578 tx_relay->m_relay_txs = fRelay;
3590 const auto* tx_relay = peer->GetTxRelay();
3591 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3593 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3604 CNodeState* state = State(pfrom.
GetId());
3606 m_num_preferred_download_peers += state->fPreferredDownload;
3612 bool send_getaddr{
false};
3614 send_getaddr = SetupAddressRelay(pfrom, *peer);
3624 peer->m_getaddr_sent =
true;
3649 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3654 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3658 m_outbound_time_offsets.Add(peer->m_time_offset);
3659 m_outbound_time_offsets.WarnIfOutOfSync();
3663 if (greatest_common_version <= 70012) {
3664 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3665 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3692 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3695 pfrom.
nVersion.load(), peer->m_starting_height,
3697 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3709 if (m_txreconciliation) {
3710 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3714 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3718 if (
auto tx_relay = peer->GetTxRelay()) {
3727 tx_relay->m_tx_inventory_mutex,
3728 return tx_relay->m_tx_inventory_to_send.empty() &&
3729 tx_relay->m_next_inv_send_time == 0
s));
3734 const CNodeState* state = State(pfrom.
GetId());
3736 .m_preferred = state->fPreferredDownload,
3737 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3738 .m_wtxid_relay = peer->m_wtxid_relay,
3747 peer->m_prefers_headers =
true;
3752 bool sendcmpct_hb{
false};
3753 uint64_t sendcmpct_version{0};
3754 vRecv >> sendcmpct_hb >> sendcmpct_version;
3760 CNodeState* nodestate = State(pfrom.
GetId());
3761 nodestate->m_provides_cmpctblocks =
true;
3762 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3779 if (!peer->m_wtxid_relay) {
3780 peer->m_wtxid_relay =
true;
3781 m_wtxid_relay_peers++;
3800 peer->m_wants_addrv2 =
true;
3808 if (!m_txreconciliation) {
3809 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3820 if (RejectIncomingTxs(pfrom)) {
3829 const auto* tx_relay = peer->GetTxRelay();
3830 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3836 uint32_t peer_txreconcl_version;
3837 uint64_t remote_salt;
3838 vRecv >> peer_txreconcl_version >> remote_salt;
3841 peer_txreconcl_version, remote_salt);
3866 const auto ser_params{
3874 std::vector<CAddress> vAddr;
3876 vRecv >> ser_params(vAddr);
3878 if (!SetupAddressRelay(pfrom, *peer)) {
3885 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3890 std::vector<CAddress> vAddrOk;
3891 const auto current_a_time{Now<NodeSeconds>()};
3894 const auto current_time{GetTime<std::chrono::microseconds>()};
3897 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3901 peer->m_addr_token_timestamp = current_time;
3904 uint64_t num_proc = 0;
3905 uint64_t num_rate_limit = 0;
3906 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
3909 if (interruptMsgProc)
3913 if (peer->m_addr_token_bucket < 1.0) {
3919 peer->m_addr_token_bucket -= 1.0;
3928 addr.
nTime = current_a_time - 5 * 24h;
3930 AddAddressKnown(*peer, addr);
3937 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3939 RelayAddress(pfrom.
GetId(), addr, reachable);
3943 vAddrOk.push_back(addr);
3946 peer->m_addr_processed += num_proc;
3947 peer->m_addr_rate_limited += num_rate_limit;
3948 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3949 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3951 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3952 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3963 std::vector<CInv> vInv;
3967 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
3971 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3975 const auto current_time{GetTime<std::chrono::microseconds>()};
3978 for (
CInv& inv : vInv) {
3979 if (interruptMsgProc)
return;
3984 if (peer->m_wtxid_relay) {
3991 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3994 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4002 best_block = &inv.
hash;
4005 if (reject_tx_invs) {
4011 AddKnownTx(*peer, inv.
hash);
4014 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4022 if (best_block !=
nullptr) {
4034 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4035 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
4037 m_chainman.m_best_header->nHeight, best_block->ToString(),
4040 if (!state.fSyncStarted) {
4041 peer->m_inv_triggered_getheaders_before_sync =
true;
4045 m_last_block_inv_triggering_headers_sync = *best_block;
4054 std::vector<CInv> vInv;
4058 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
4064 if (vInv.size() > 0) {
4069 LOCK(peer->m_getdata_requests_mutex);
4070 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
4071 ProcessGetData(pfrom, *peer, interruptMsgProc);
4080 vRecv >> locator >> hashStop;
4096 std::shared_ptr<const CBlock> a_recent_block;
4098 LOCK(m_most_recent_block_mutex);
4099 a_recent_block = m_most_recent_block;
4102 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4117 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4132 if (--nLimit <= 0) {
4136 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4147 std::shared_ptr<const CBlock> recent_block;
4149 LOCK(m_most_recent_block_mutex);
4150 if (m_most_recent_block_hash == req.
blockhash)
4151 recent_block = m_most_recent_block;
4155 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4174 if (!block_pos.IsNull()) {
4181 SendBlockTransactions(pfrom, *peer, block, req);
4194 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4202 vRecv >> locator >> hashStop;
4220 if (m_chainman.
ActiveTip() ==
nullptr ||
4222 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4229 CNodeState *nodestate = State(pfrom.
GetId());
4239 if (!BlockRequestAllowed(pindex)) {
4240 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4253 std::vector<CBlock> vHeaders;
4254 int nLimit = m_opts.max_headers_result;
4256 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4259 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4274 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4280 if (RejectIncomingTxs(pfrom)) {
4295 const uint256& txid = ptx->GetHash();
4296 const uint256& wtxid = ptx->GetWitnessHash();
4298 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4299 AddKnownTx(*peer, hash);
4303 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4304 if (!should_validate) {
4310 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4313 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4319 if (package_to_validate) {
4322 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4323 ProcessPackageResult(package_to_validate.value(), package_result);
4329 Assume(!package_to_validate.has_value());
4339 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4342 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4343 ProcessPackageResult(package_to_validate.value(), package_result);
4359 vRecv >> cmpctblock;
4361 bool received_new_header =
false;
4371 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4381 received_new_header =
true;
4389 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4396 if (received_new_header) {
4397 LogBlockHeader(*pindex, pfrom,
true);
4400 bool fProcessBLOCKTXN =
false;
4404 bool fRevertToHeaderProcessing =
false;
4408 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4409 bool fBlockReconstructed =
false;
4415 CNodeState *nodestate = State(pfrom.
GetId());
4420 nodestate->m_last_block_announcement =
GetTime();
4426 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4427 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4428 bool requested_block_from_this_peer{
false};
4431 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4433 while (range_flight.first != range_flight.second) {
4434 if (range_flight.first->second.first == pfrom.
GetId()) {
4435 requested_block_from_this_peer =
true;
4438 range_flight.first++;
4443 if (requested_block_from_this_peer) {
4446 std::vector<CInv> vInv(1);
4447 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4454 if (!already_in_flight && !CanDirectFetch()) {
4462 requested_block_from_this_peer) {
4463 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4464 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4465 if (!(*queuedBlockIt)->partialBlock)
4478 Misbehaving(*peer,
"invalid compact block");
4481 if (first_in_flight) {
4483 std::vector<CInv> vInv(1);
4484 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4494 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4499 fProcessBLOCKTXN =
true;
4500 }
else if (first_in_flight) {
4507 IsBlockRequestedFromOutbound(blockhash) ||
4526 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4531 std::vector<CTransactionRef> dummy;
4532 status = tempBlock.FillBlock(*pblock, dummy);
4534 fBlockReconstructed =
true;
4538 if (requested_block_from_this_peer) {
4541 std::vector<CInv> vInv(1);
4542 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4547 fRevertToHeaderProcessing =
true;
4552 if (fProcessBLOCKTXN) {
4555 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4558 if (fRevertToHeaderProcessing) {
4564 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4567 if (fBlockReconstructed) {
4572 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4590 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4607 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4618 std::vector<CBlockHeader> headers;
4622 if (nCount > m_opts.max_headers_result) {
4623 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4626 headers.resize(nCount);
4627 for (
unsigned int n = 0; n < nCount; n++) {
4628 vRecv >> headers[n];
4632 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4636 if (m_headers_presync_should_signal.exchange(
false)) {
4637 HeadersPresyncStats stats;
4639 LOCK(m_headers_presync_mutex);
4640 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4641 if (it != m_headers_presync_stats.end()) stats = it->second;
4659 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4670 Misbehaving(*peer,
"mutated block");
4675 bool forceProcessing =
false;
4676 const uint256 hash(pblock->GetHash());
4677 bool min_pow_checked =
false;
4682 forceProcessing = IsBlockRequested(hash);
4683 RemoveBlockRequest(hash, pfrom.
GetId());
4687 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4691 min_pow_checked =
true;
4694 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4711 Assume(SetupAddressRelay(pfrom, *peer));
4715 if (peer->m_getaddr_recvd) {
4719 peer->m_getaddr_recvd =
true;
4721 peer->m_addrs_to_send.clear();
4722 std::vector<CAddress> vAddr;
4728 for (
const CAddress &addr : vAddr) {
4729 PushAddress(*peer, addr);
4757 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4758 LOCK(tx_relay->m_tx_inventory_mutex);
4759 tx_relay->m_send_mempool =
true;
4785 const auto ping_end = time_received;
4788 bool bPingFinished =
false;
4789 std::string sProblem;
4791 if (nAvail >=
sizeof(
nonce)) {
4795 if (peer->m_ping_nonce_sent != 0) {
4796 if (
nonce == peer->m_ping_nonce_sent) {
4798 bPingFinished =
true;
4799 const auto ping_time = ping_end - peer->m_ping_start.load();
4800 if (ping_time.count() >= 0) {
4805 sProblem =
"Timing mishap";
4809 sProblem =
"Nonce mismatch";
4812 bPingFinished =
true;
4813 sProblem =
"Nonce zero";
4817 sProblem =
"Unsolicited pong without ping";
4821 bPingFinished =
true;
4822 sProblem =
"Short payload";
4825 if (!(sProblem.empty())) {
4829 peer->m_ping_nonce_sent,
4833 if (bPingFinished) {
4834 peer->m_ping_nonce_sent = 0;
4851 Misbehaving(*peer,
"too-large bloom filter");
4852 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4854 LOCK(tx_relay->m_bloom_filter_mutex);
4855 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4856 tx_relay->m_relay_txs =
true;
4870 std::vector<unsigned char> vData;
4878 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4879 LOCK(tx_relay->m_bloom_filter_mutex);
4880 if (tx_relay->m_bloom_filter) {
4881 tx_relay->m_bloom_filter->insert(vData);
4887 Misbehaving(*peer,
"bad filteradd message");
4898 auto tx_relay = peer->GetTxRelay();
4899 if (!tx_relay)
return;
4902 LOCK(tx_relay->m_bloom_filter_mutex);
4903 tx_relay->m_bloom_filter =
nullptr;
4904 tx_relay->m_relay_txs =
true;
4913 vRecv >> newFeeFilter;
4915 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4916 tx_relay->m_fee_filter_received = newFeeFilter;
4924 ProcessGetCFilters(pfrom, *peer, vRecv);
4929 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4934 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4939 std::vector<CInv> vInv;
4941 std::vector<uint256> tx_invs;
4943 for (
CInv &inv : vInv) {
4945 tx_invs.emplace_back(inv.
hash);
4949 LOCK(m_tx_download_mutex);
4950 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
4959bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4962 LOCK(peer.m_misbehavior_mutex);
4965 if (!peer.m_should_discourage)
return false;
4967 peer.m_should_discourage =
false;
4972 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
4978 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
4998bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
5003 PeerRef peer = GetPeerRef(pfrom->
GetId());
5004 if (peer ==
nullptr)
return false;
5008 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
5011 LOCK(peer->m_getdata_requests_mutex);
5012 if (!peer->m_getdata_requests.empty()) {
5013 ProcessGetData(*pfrom, *peer, interruptMsgProc);
5017 const bool processed_orphan = ProcessOrphanTx(*peer);
5022 if (processed_orphan)
return true;
5027 LOCK(peer->m_getdata_requests_mutex);
5028 if (!peer->m_getdata_requests.empty())
return true;
5041 bool fMoreWork = poll_result->second;
5052 if (m_opts.capture_messages) {
5057 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5058 if (interruptMsgProc)
return false;
5060 LOCK(peer->m_getdata_requests_mutex);
5061 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5068 LOCK(m_tx_download_mutex);
5069 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
5070 }
catch (
const std::exception& e) {
5079void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5083 CNodeState &state = *State(pto.
GetId());
5092 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5094 if (state.m_chain_sync.m_timeout != 0
s) {
5095 state.m_chain_sync.m_timeout = 0
s;
5096 state.m_chain_sync.m_work_header =
nullptr;
5097 state.m_chain_sync.m_sent_getheaders =
false;
5099 }
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)) {
5107 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5108 state.m_chain_sync.m_sent_getheaders =
false;
5109 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5113 if (state.m_chain_sync.m_sent_getheaders) {
5115 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5118 assert(state.m_chain_sync.m_work_header);
5123 MaybeSendGetHeaders(pto,
5124 GetLocator(state.m_chain_sync.m_work_header->pprev),
5126 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());
5127 state.m_chain_sync.m_sent_getheaders =
true;
5139void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5148 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5152 if (pnode->
GetId() > youngest_peer.first) {
5153 next_youngest_peer = youngest_peer;
5154 youngest_peer.first = pnode->GetId();
5155 youngest_peer.second = pnode->m_last_block_time;
5158 NodeId to_disconnect = youngest_peer.first;
5159 if (youngest_peer.second > next_youngest_peer.second) {
5162 to_disconnect = next_youngest_peer.first;
5171 CNodeState *node_state = State(pnode->
GetId());
5172 if (node_state ==
nullptr ||
5175 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5179 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5195 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5198 AssertLockHeld(::cs_main);
5202 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5203 CNodeState *state = State(pnode->GetId());
5204 if (state == nullptr) return;
5206 if (state->m_chain_sync.m_protect) return;
5209 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5210 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5211 worst_peer = pnode->GetId();
5212 oldest_block_announcement = state->m_last_block_announcement;
5215 if (worst_peer != -1) {
5224 CNodeState &state = *State(pnode->
GetId());
5226 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5230 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5247void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5251 auto now{GetTime<std::chrono::seconds>()};
5253 EvictExtraOutboundPeers(now);
5255 if (now > m_stale_tip_check_time) {
5259 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5268 if (!m_initial_sync_finished && CanDirectFetch()) {
5270 m_initial_sync_finished =
true;
5274void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5277 peer.m_ping_nonce_sent &&
5287 bool pingSend =
false;
5289 if (peer.m_ping_queued) {
5294 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5303 }
while (
nonce == 0);
5304 peer.m_ping_queued =
false;
5305 peer.m_ping_start = now;
5307 peer.m_ping_nonce_sent =
nonce;
5311 peer.m_ping_nonce_sent = 0;
5317void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5320 if (!peer.m_addr_relay_enabled)
return;
5322 LOCK(peer.m_addr_send_times_mutex);
5325 peer.m_next_local_addr_send < current_time) {
5332 if (peer.m_next_local_addr_send != 0us) {
5333 peer.m_addr_known->reset();
5336 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5337 PushAddress(peer, local_addr);
5343 if (current_time <= peer.m_next_addr_send)
return;
5356 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5357 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5360 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5361 peer.m_addrs_to_send.end());
5364 if (peer.m_addrs_to_send.empty())
return;
5366 if (peer.m_wants_addrv2) {
5371 peer.m_addrs_to_send.clear();
5374 if (peer.m_addrs_to_send.capacity() > 40) {
5375 peer.m_addrs_to_send.shrink_to_fit();
5379void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5387 CNodeState &state = *State(
node.GetId());
5388 if (state.pindexBestKnownBlock !=
nullptr &&
5395 peer.m_sent_sendheaders =
true;
5400void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5402 if (m_opts.ignore_incoming_txs)
return;
5418 if (peer.m_fee_filter_sent == MAX_FILTER) {
5421 peer.m_next_send_feefilter = 0us;
5424 if (current_time > peer.m_next_send_feefilter) {
5425 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5428 if (filterToSend != peer.m_fee_filter_sent) {
5430 peer.m_fee_filter_sent = filterToSend;
5437 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5443class CompareInvMempoolOrder
5448 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5451 m_wtxid_relay = use_wtxid;
5454 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5458 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5463bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5473bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5478 if (
node.IsBlockOnlyConn())
return false;
5480 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5484 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5490bool PeerManagerImpl::SendMessages(
CNode* pto)
5495 PeerRef peer = GetPeerRef(pto->
GetId());
5496 if (!peer)
return false;
5501 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5504 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5505 PushNodeVersion(*pto, *peer);
5506 peer->m_outbound_version_message_sent =
true;
5513 const auto current_time{GetTime<std::chrono::microseconds>()};
5521 MaybeSendPing(*pto, *peer, current_time);
5526 MaybeSendAddr(*pto, *peer, current_time);
5528 MaybeSendSendHeaders(*pto, *peer);
5533 CNodeState &state = *State(pto->
GetId());
5536 if (m_chainman.m_best_header ==
nullptr) {
5543 bool sync_blocks_and_headers_from_peer =
false;
5544 if (state.fPreferredDownload) {
5545 sync_blocks_and_headers_from_peer =
true;
5556 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5557 sync_blocks_and_headers_from_peer =
true;
5563 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5564 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5572 if (pindexStart->
pprev)
5573 pindexStart = pindexStart->
pprev;
5574 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5577 state.fSyncStarted =
true;
5601 LOCK(peer->m_block_inv_mutex);
5602 std::vector<CBlock> vHeaders;
5603 bool fRevertToInv = ((!peer->m_prefers_headers &&
5604 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5607 ProcessBlockAvailability(pto->
GetId());
5609 if (!fRevertToInv) {
5610 bool fFoundStartingHeader =
false;
5614 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5619 fRevertToInv =
true;
5622 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5634 fRevertToInv =
true;
5637 pBestIndex = pindex;
5638 if (fFoundStartingHeader) {
5641 }
else if (PeerHasHeader(&state, pindex)) {
5643 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5646 fFoundStartingHeader =
true;
5651 fRevertToInv =
true;
5656 if (!fRevertToInv && !vHeaders.empty()) {
5657 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5661 vHeaders.front().GetHash().ToString(), pto->
GetId());
5663 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5665 LOCK(m_most_recent_block_mutex);
5666 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5670 if (cached_cmpctblock_msg.has_value()) {
5671 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5679 state.pindexBestHeaderSent = pBestIndex;
5680 }
else if (peer->m_prefers_headers) {
5681 if (vHeaders.size() > 1) {
5684 vHeaders.front().GetHash().ToString(),
5685 vHeaders.back().GetHash().ToString(), pto->
GetId());
5688 vHeaders.front().GetHash().ToString(), pto->
GetId());
5691 state.pindexBestHeaderSent = pBestIndex;
5693 fRevertToInv =
true;
5699 if (!peer->m_blocks_for_headers_relay.empty()) {
5700 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5713 if (!PeerHasHeader(&state, pindex)) {
5714 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5720 peer->m_blocks_for_headers_relay.clear();
5726 std::vector<CInv> vInv;
5728 LOCK(peer->m_block_inv_mutex);
5732 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5739 peer->m_blocks_for_inv_relay.clear();
5742 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5743 LOCK(tx_relay->m_tx_inventory_mutex);
5746 if (tx_relay->m_next_inv_send_time < current_time) {
5747 fSendTrickle =
true;
5757 LOCK(tx_relay->m_bloom_filter_mutex);
5758 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5762 if (fSendTrickle && tx_relay->m_send_mempool) {
5763 auto vtxinfo = m_mempool.
infoAll();
5764 tx_relay->m_send_mempool =
false;
5765 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5767 LOCK(tx_relay->m_bloom_filter_mutex);
5769 for (
const auto& txinfo : vtxinfo) {
5772 peer->m_wtxid_relay ?
5773 txinfo.tx->GetWitnessHash().ToUint256() :
5774 txinfo.tx->GetHash().ToUint256(),
5776 tx_relay->m_tx_inventory_to_send.erase(inv.
hash);
5779 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5782 if (tx_relay->m_bloom_filter) {
5783 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5785 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5786 vInv.push_back(inv);
5797 std::vector<std::set<uint256>::iterator> vInvTx;
5798 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5799 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5800 vInvTx.push_back(it);
5802 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5805 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
5806 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5809 unsigned int nRelayedTransactions = 0;
5810 LOCK(tx_relay->m_bloom_filter_mutex);
5813 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5815 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5816 std::set<uint256>::iterator it = vInvTx.back();
5821 tx_relay->m_tx_inventory_to_send.erase(it);
5823 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
5832 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5835 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5837 vInv.push_back(inv);
5838 nRelayedTransactions++;
5843 tx_relay->m_tx_inventory_known_filter.insert(hash);
5848 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5855 auto stalling_timeout = m_block_stalling_timeout.load();
5856 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5865 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5875 if (state.vBlocksInFlight.size() > 0) {
5876 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5877 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5885 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5887 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5888 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5905 state.fSyncStarted =
false;
5907 peer->m_headers_sync_timeout = 0us;
5913 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5919 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5924 std::vector<CInv> vGetData;
5926 std::vector<const CBlockIndex*> vToDownload;
5928 auto get_inflight_budget = [&state]() {
5934 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5939 TryDownloadingHistoricalBlocks(
5941 get_inflight_budget(),
5942 vToDownload, from_tip,
5943 Assert(m_chainman.GetSnapshotBaseBlock()));
5946 uint32_t nFetchFlags = GetFetchFlags(*peer);
5948 BlockRequested(pto->
GetId(), *pindex);
5952 if (state.vBlocksInFlight.empty() && staller != -1) {
5953 if (State(staller)->m_stalling_since == 0us) {
5954 State(staller)->m_stalling_since = current_time;
5964 LOCK(m_tx_download_mutex);
5965 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
5974 if (!vGetData.empty())
5977 MaybeSendFeefilter(*pto, *peer, current_time);
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
arith_uint256 GetBlockProof(const CBlockIndex &block)
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
@ BLOCK_VALID_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous.
@ BLOCK_HAVE_DATA
full block available in blk*.dat
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< CTransactionRef > txn
std::vector< uint16_t > indexes
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
static constexpr SerParams V1_NETWORK
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V2_NETWORK
size_t BlockTxCount() const
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
unsigned int nTx
Number of transactions in this block.
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
An in-memory indexed chain of blocks.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const Consensus::Params & GetConsensus() const
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool GetTryNewOutboundPeer() const
void SetTryNewOutboundPeer(bool flag)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
bool DisconnectNode(const std::string &node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return all or many randomly selected addresses, optionally by network.
bool CheckIncomingNonce(uint64_t nonce)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, uint256 > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
const std::string m_addr_name
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
std::atomic< bool > m_bip152_highbandwidth_from
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
The basic transaction that is broadcasted on the network and contained in blocks.
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
const Txid & GetHash() const LIFETIMEBOUND
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
std::set< uint256 > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
CFeeRate GetMinFee(size_t sizelimit) const
CTransactionRef get(const uint256 &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
TxMempoolInfo info(const GenTxid >xid) const
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
bool exists(const GenTxid >xid) const
unsigned long size() const
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void BlockConnected(ChainstateRole role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void ActiveTipChange(const CBlockIndex &new_tip, bool is_ibd)
Notifies listeners any time the block chain tip changes, synchronously.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected Provides the block that was disconnected.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
const CBlockIndex * GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The tip of the background sync chain.
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
bool ProcessNewBlockHeaders(std::span< const CBlockHeader > headers, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const arith_uint256 & MinimumChainWork() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Double ended buffer combining vector and stream-like interfaces.
void ignore(size_t num_ignore)
uint64_t rand64() noexcept
Generate a random 64-bit integer.
A generic txid reference (txid or wtxid).
const uint256 & GetHash() const LIFETIMEBOUND
static GenTxid Txid(const uint256 &hash)
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< CTransactionRef > &extra_txn)
bool IsTxAvailable(size_t index) const
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
virtual std::optional< std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, DataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
virtual std::vector< TxOrphanage::OrphanTxBase > GetOrphanTransactions()=0
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
virtual void UnitTestMisbehaving(NodeId peer_id)=0
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests....
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
std::string ToString() const
256-bit unsigned big integer.
constexpr bool IsNull() const
std::string ToString() const
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash={}) const
Functions for disk access for blocks.
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 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
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
@ BLOCK_HEADER_LOW_WORK
the block header may be on a too-little-work chain
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ BLOCK_RESULT_UNSET
initial value. Block has not yet been rejected
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_MEMPOOL_POLICY
violated mempool's fee/size/descendant/RBF/etc limits
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_PREMATURE_SPEND
transaction spends a coinbase too early, or violates locktime/sequence locks
@ TX_INPUTS_NOT_STANDARD
inputs (covered by txid) failed policy rules
@ TX_WITNESS_STRIPPED
Transaction is missing a witness.
@ TX_CONFLICT
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
@ TX_WITNESS_MUTATED
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
@ TX_NO_MEMPOOL
this node does not have a mempool so can't validate the transaction
@ TX_RESULT_UNSET
initial value. Tx has not yet been rejected
@ TX_CONSENSUS
invalid by consensus rules
@ TX_RECONSIDERABLE
fails some policy, but might be acceptable if submitted in a (different) package
static size_t RecursiveDynamicUsage(const CScript &script)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
#define LogDebug(category,...)
Transaction validation functions.
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
Functions to serialize / deserialize common bitcoin types.
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
TRACEPOINT_SEMAPHORE(net, inbound_message)
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" command for wtxid-based relay starts with this version
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
std::chrono::seconds time_offset
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
@ DIFFERENT_WITNESS
Valid, transaction was already in the mempool.
@ INVALID
Fully validated, valid.
const std::list< CTransactionRef > m_replaced_transactions
Mempool transactions replaced by the tx.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
Validation result for package mempool acceptance.
PackageValidationState m_state
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
std::chrono::seconds median_outbound_time_offset
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
std::vector< NodeId > m_senders
std::string ToString() const
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
#define TRACEPOINT(context,...)
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
ReconciliationRegisterResult
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
constexpr int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...