175 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
209 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
212 const bool m_is_inbound;
215 Mutex m_misbehavior_mutex;
217 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
220 Mutex m_block_inv_mutex;
224 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
228 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
239 std::atomic<int> m_starting_height{-1};
242 std::atomic<uint64_t> m_ping_nonce_sent{0};
244 std::atomic<std::chrono::microseconds> m_ping_start{0us};
246 std::atomic<bool> m_ping_queued{
false};
249 std::atomic<bool> m_wtxid_relay{
false};
261 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
263 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
274 std::set<uint256> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
278 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
281 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
287 std::atomic<CAmount> m_fee_filter_received{0};
293 LOCK(m_tx_relay_mutex);
295 m_tx_relay = std::make_unique<Peer::TxRelay>();
296 return m_tx_relay.get();
301 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
330 std::atomic_bool m_addr_relay_enabled{
false};
334 mutable Mutex m_addr_send_times_mutex;
336 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
338 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
341 std::atomic_bool m_wants_addrv2{
false};
350 std::atomic<uint64_t> m_addr_rate_limited{0};
352 std::atomic<uint64_t> m_addr_processed{0};
358 Mutex m_getdata_requests_mutex;
360 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
366 Mutex m_headers_sync_mutex;
369 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
372 std::atomic<bool> m_sent_sendheaders{
false};
382 std::atomic<std::chrono::seconds> m_time_offset{0
s};
386 , m_our_services{our_services}
387 , m_is_inbound{is_inbound}
391 mutable Mutex m_tx_relay_mutex;
394 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
397using PeerRef = std::shared_ptr<Peer>;
409 uint256 hashLastUnknownBlock{};
415 bool fSyncStarted{
false};
417 std::chrono::microseconds m_stalling_since{0us};
418 std::list<QueuedBlock> vBlocksInFlight;
420 std::chrono::microseconds m_downloading_since{0us};
422 bool fPreferredDownload{
false};
424 bool m_requested_hb_cmpctblocks{
false};
426 bool m_provides_cmpctblocks{
false};
452 struct ChainSyncTimeoutState {
454 std::chrono::seconds m_timeout{0
s};
458 bool m_sent_getheaders{
false};
460 bool m_protect{
false};
463 ChainSyncTimeoutState m_chain_sync;
466 int64_t m_last_block_announcement{0};
495 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
509 void SetBestBlock(
int height,
std::chrono::seconds time)
override
511 m_best_height = height;
512 m_best_block_time = time;
516 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
517 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
541 void Misbehaving(Peer& peer,
const std::string& message);
552 bool via_compact_block,
const std::string& message =
"")
567 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
581 bool first_time_failure)
606 bool ProcessOrphanTx(Peer& peer)
616 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
618 bool via_compact_block)
630 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
649 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
663 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
678 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
680 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
687 template <
typename... Args>
688 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
694 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
700 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
743 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
746 std::atomic<int> m_best_height{-1};
748 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
756 const Options m_opts;
758 bool RejectIncomingTxs(
const CNode& peer)
const;
766 mutable Mutex m_peer_mutex;
773 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
783 uint32_t GetFetchFlags(
const Peer& peer)
const;
785 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
802 std::atomic<int> m_wtxid_relay_peers{0};
819 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
824 Mutex m_most_recent_block_mutex;
825 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
826 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
828 std::unique_ptr<const std::map<uint256, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
832 Mutex m_headers_presync_mutex;
840 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
842 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
846 std::atomic_bool m_headers_presync_should_signal{
false};
916 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
922 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
927 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
952 std::vector<CTransactionRef> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
954 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
966 int64_t ApproximateBestBlockDepth() const;
976 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
994 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
996 const
uint256& stop_hash, uint32_t max_height_diff,
1045const CNodeState* PeerManagerImpl::State(
NodeId pnode)
const
1047 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1048 if (it == m_node_states.end())
1053CNodeState* PeerManagerImpl::State(
NodeId pnode)
1055 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1063static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1068void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1070 assert(peer.m_addr_known);
1071 peer.m_addr_known->insert(addr.
GetKey());
1074void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1079 assert(peer.m_addr_known);
1080 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1082 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1084 peer.m_addrs_to_send.push_back(addr);
1089static void AddKnownTx(Peer& peer,
const uint256& hash)
1091 auto tx_relay = peer.GetTxRelay();
1092 if (!tx_relay)
return;
1094 LOCK(tx_relay->m_tx_inventory_mutex);
1095 tx_relay->m_tx_inventory_known_filter.insert(hash);
1099static bool CanServeBlocks(
const Peer& peer)
1106static bool IsLimitedPeer(
const Peer& peer)
1113static bool CanServeWitnesses(
const Peer& peer)
1118std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1119 std::chrono::seconds average_interval)
1121 if (m_next_inv_to_inbounds.load() < now) {
1125 m_next_inv_to_inbounds = now + m_rng.rand_exp_duration(average_interval);
1127 return m_next_inv_to_inbounds;
1130bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1132 return mapBlocksInFlight.count(hash);
1135bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1137 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1138 auto [nodeid, block_it] = range.first->second;
1139 PeerRef peer{GetPeerRef(nodeid)};
1140 if (peer && !peer->m_is_inbound)
return true;
1146void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1148 auto range = mapBlocksInFlight.equal_range(hash);
1149 if (range.first == range.second) {
1157 while (range.first != range.second) {
1158 auto [node_id, list_it] = range.first->second;
1160 if (from_peer && *from_peer != node_id) {
1165 CNodeState& state = *
Assert(State(node_id));
1167 if (state.vBlocksInFlight.begin() == list_it) {
1169 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1171 state.vBlocksInFlight.erase(list_it);
1173 if (state.vBlocksInFlight.empty()) {
1175 m_peers_downloading_from--;
1177 state.m_stalling_since = 0us;
1179 range.first = mapBlocksInFlight.erase(range.first);
1183bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1187 CNodeState *state = State(nodeid);
1188 assert(state !=
nullptr);
1193 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1194 if (range.first->second.first == nodeid) {
1196 *pit = &range.first->second.second;
1203 RemoveBlockRequest(hash, nodeid);
1205 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1206 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1207 if (state->vBlocksInFlight.size() == 1) {
1209 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1210 m_peers_downloading_from++;
1212 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1214 *pit = &itInFlight->second.second;
1219void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1226 if (m_opts.ignore_incoming_txs)
return;
1228 CNodeState* nodestate = State(nodeid);
1229 PeerRef peer{GetPeerRef(nodeid)};
1230 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1235 int num_outbound_hb_peers = 0;
1236 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1237 if (*it == nodeid) {
1238 lNodesAnnouncingHeaderAndIDs.erase(it);
1239 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1242 PeerRef peer_ref{GetPeerRef(*it)};
1243 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1245 if (peer && peer->m_is_inbound) {
1248 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1249 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1250 if (remove_peer && !remove_peer->m_is_inbound) {
1253 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1259 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1262 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1263 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1265 pnodeStop->m_bip152_highbandwidth_to = false;
1268 lNodesAnnouncingHeaderAndIDs.pop_front();
1273 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1278bool PeerManagerImpl::TipMayBeStale()
1282 if (m_last_tip_update.load() == 0
s) {
1283 m_last_tip_update = GetTime<std::chrono::seconds>();
1285 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1288int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1293bool PeerManagerImpl::CanDirectFetch()
1300 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1302 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1307void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1308 CNodeState *state = State(nodeid);
1309 assert(state !=
nullptr);
1311 if (!state->hashLastUnknownBlock.IsNull()) {
1314 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1315 state->pindexBestKnownBlock = pindex;
1317 state->hashLastUnknownBlock.SetNull();
1322void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1323 CNodeState *state = State(nodeid);
1324 assert(state !=
nullptr);
1326 ProcessBlockAvailability(nodeid);
1331 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1332 state->pindexBestKnownBlock = pindex;
1336 state->hashLastUnknownBlock = hash;
1341void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1346 vBlocks.reserve(vBlocks.size() +
count);
1347 CNodeState *state = State(peer.m_id);
1348 assert(state !=
nullptr);
1351 ProcessBlockAvailability(peer.m_id);
1353 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1361 const CBlockIndex* snap_base{m_chainman.GetSnapshotBaseBlock()};
1362 if (snap_base && state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1363 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1370 if (state->pindexLastCommonBlock ==
nullptr ||
1371 (snap_base && state->pindexLastCommonBlock->nHeight < snap_base->nHeight)) {
1372 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1377 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1378 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1381 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1387 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1390void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1395 if (vBlocks.size() >=
count) {
1399 vBlocks.reserve(
count);
1400 CNodeState *state =
Assert(State(peer.m_id));
1402 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1419void 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)
1421 std::vector<const CBlockIndex*> vToFetch;
1422 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1423 bool is_limited_peer = IsLimitedPeer(peer);
1425 while (pindexWalk->
nHeight < nMaxHeight) {
1429 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1430 vToFetch.resize(nToFetch);
1431 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1432 vToFetch[nToFetch - 1] = pindexWalk;
1433 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1434 vToFetch[i - 1] = vToFetch[i]->
pprev;
1454 state->pindexLastCommonBlock = pindex;
1461 if (waitingfor == -1) {
1463 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1469 if (pindex->
nHeight > nWindowEnd) {
1471 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1473 if (nodeStaller) *nodeStaller = waitingfor;
1483 vBlocks.push_back(pindex);
1484 if (vBlocks.size() ==
count) {
1493void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1495 uint64_t my_services{peer.m_our_services};
1496 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1498 const int nNodeStartingHeight{m_best_height};
1505 const bool tx_relay{!RejectIncomingTxs(pnode)};
1512 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);
1518void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1521 CNodeState *state = State(
node);
1522 if (state) state->m_last_block_announcement = time_in_seconds;
1530 m_node_states.try_emplace(m_node_states.end(), nodeid);
1532 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1538 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1541 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1545void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1549 for (
const auto& txid : unbroadcast_txids) {
1552 if (tx !=
nullptr) {
1553 RelayTransaction(txid, tx->GetWitnessHash());
1562 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1565void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1576 PeerRef peer = RemovePeer(nodeid);
1578 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1579 assert(m_wtxid_relay_peers >= 0);
1581 CNodeState *state = State(nodeid);
1582 assert(state !=
nullptr);
1584 if (state->fSyncStarted)
1587 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1588 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1589 while (range.first != range.second) {
1590 auto [node_id, list_it] = range.first->second;
1591 if (node_id != nodeid) {
1594 range.first = mapBlocksInFlight.erase(range.first);
1599 LOCK(m_tx_download_mutex);
1600 m_txdownloadman.DisconnectedPeer(nodeid);
1602 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1603 m_num_preferred_download_peers -= state->fPreferredDownload;
1604 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1605 assert(m_peers_downloading_from >= 0);
1606 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1607 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1609 m_node_states.erase(nodeid);
1611 if (m_node_states.empty()) {
1613 assert(mapBlocksInFlight.empty());
1614 assert(m_num_preferred_download_peers == 0);
1615 assert(m_peers_downloading_from == 0);
1616 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1617 assert(m_wtxid_relay_peers == 0);
1618 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1621 if (
node.fSuccessfullyConnected &&
1622 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1629 LOCK(m_headers_presync_mutex);
1630 m_headers_presync_stats.erase(nodeid);
1635bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1638 return !(GetDesirableServiceFlags(services) & (~services));
1652PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1655 auto it = m_peer_map.find(
id);
1656 return it != m_peer_map.end() ? it->second :
nullptr;
1659PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1663 auto it = m_peer_map.find(
id);
1664 if (it != m_peer_map.end()) {
1665 ret = std::move(it->second);
1666 m_peer_map.erase(it);
1675 const CNodeState* state = State(nodeid);
1676 if (state ==
nullptr)
1678 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1679 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1680 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1686 PeerRef peer = GetPeerRef(nodeid);
1687 if (peer ==
nullptr)
return false;
1696 auto ping_wait{0us};
1697 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1698 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1701 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1714 LOCK(peer->m_headers_sync_mutex);
1715 if (peer->m_headers_sync) {
1724std::vector<TxOrphanage::OrphanTxBase> PeerManagerImpl::GetOrphanTransactions()
1726 LOCK(m_tx_download_mutex);
1727 return m_txdownloadman.GetOrphanTransactions();
1734 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1738void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1740 if (m_opts.max_extra_txs <= 0)
1742 if (!vExtraTxnForCompact.size())
1743 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1744 vExtraTxnForCompact[vExtraTxnForCompactIt] = tx;
1745 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1748void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1750 LOCK(peer.m_misbehavior_mutex);
1752 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1753 peer.m_should_discourage =
true;
1758 bool via_compact_block,
const std::string& message)
1760 PeerRef peer{GetPeerRef(nodeid)};
1771 if (!via_compact_block) {
1772 if (peer) Misbehaving(*peer, message);
1780 if (peer && !via_compact_block && !peer->m_is_inbound) {
1781 if (peer) Misbehaving(*peer, message);
1789 if (peer) Misbehaving(*peer, message);
1793 if (peer) Misbehaving(*peer, message);
1798 if (message !=
"") {
1805 PeerRef peer{GetPeerRef(nodeid)};
1811 if (peer) Misbehaving(*peer,
"");
1829bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1838std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1843 PeerRef peer = GetPeerRef(peer_id);
1844 if (peer ==
nullptr)
return "Peer does not exist";
1847 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1852 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1855 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1867 if (!success)
return "Peer not fully connected";
1871 return std::nullopt;
1878 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1884 : m_rng{opts.deterministic_rng},
1886 m_chainparams(chainman.GetParams()),
1890 m_chainman(chainman),
1892 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.max_orphan_txs, opts.deterministic_rng}),
1893 m_warnings{warnings},
1898 if (opts.reconcile_txs) {
1903void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1914 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1917void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
1925 LOCK(m_tx_download_mutex);
1929 m_txdownloadman.ActiveTipChange();
1939void PeerManagerImpl::BlockConnected(
1941 const std::shared_ptr<const CBlock>& pblock,
1946 m_last_tip_update = GetTime<std::chrono::seconds>();
1949 auto stalling_timeout = m_block_stalling_timeout.load();
1953 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1963 LOCK(m_tx_download_mutex);
1964 m_txdownloadman.BlockConnected(pblock);
1967void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1969 LOCK(m_tx_download_mutex);
1970 m_txdownloadman.BlockDisconnected();
1977void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1979 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
1983 if (pindex->
nHeight <= m_highest_fast_announce)
1985 m_highest_fast_announce = pindex->
nHeight;
1989 uint256 hashBlock(pblock->GetHash());
1990 const std::shared_future<CSerializedNetMsg> lazy_ser{
1994 auto most_recent_block_txs = std::make_unique<std::map<uint256, CTransactionRef>>();
1995 for (
const auto& tx : pblock->vtx) {
1996 most_recent_block_txs->emplace(tx->GetHash(), tx);
1997 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2000 LOCK(m_most_recent_block_mutex);
2001 m_most_recent_block_hash = hashBlock;
2002 m_most_recent_block = pblock;
2003 m_most_recent_compact_block = pcmpctblock;
2004 m_most_recent_block_txs = std::move(most_recent_block_txs);
2012 ProcessBlockAvailability(pnode->
GetId());
2013 CNodeState &state = *State(pnode->
GetId());
2016 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2018 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2019 hashBlock.ToString(), pnode->
GetId());
2022 PushMessage(*pnode, ser_cmpctblock.Copy());
2023 state.pindexBestHeaderSent = pindex;
2032void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2034 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2037 if (fInitialDownload)
return;
2040 std::vector<uint256> vHashes;
2042 while (pindexToAnnounce != pindexFork) {
2044 pindexToAnnounce = pindexToAnnounce->
pprev;
2054 for (
auto& it : m_peer_map) {
2055 Peer& peer = *it.second;
2056 LOCK(peer.m_block_inv_mutex);
2057 for (
const uint256& hash : vHashes | std::views::reverse) {
2058 peer.m_blocks_for_headers_relay.push_back(hash);
2075 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2080 it != mapBlockSource.end() &&
2081 State(it->second.first)) {
2082 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2092 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2093 if (it != mapBlockSource.end()) {
2094 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2097 if (it != mapBlockSource.end())
2098 mapBlockSource.erase(it);
2106bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2111void PeerManagerImpl::SendPings()
2114 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2117void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2120 for(
auto& it : m_peer_map) {
2121 Peer& peer = *it.second;
2122 auto tx_relay = peer.GetTxRelay();
2123 if (!tx_relay)
continue;
2125 LOCK(tx_relay->m_tx_inventory_mutex);
2131 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2133 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2134 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2135 tx_relay->m_tx_inventory_to_send.insert(hash);
2140void PeerManagerImpl::RelayAddress(
NodeId originator,
2156 const auto current_time{GetTime<std::chrono::seconds>()};
2164 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2166 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2167 assert(nRelayNodes <= best.size());
2171 for (
auto& [
id, peer] : m_peer_map) {
2172 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2174 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2175 if (hashKey > best[i].first) {
2176 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2177 best[i] = std::make_pair(hashKey, peer.get());
2184 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2185 PushAddress(*best[i].second, addr);
2189void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2191 std::shared_ptr<const CBlock> a_recent_block;
2192 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2194 LOCK(m_most_recent_block_mutex);
2195 a_recent_block = m_most_recent_block;
2196 a_recent_compact_block = m_most_recent_compact_block;
2199 bool need_activate_chain =
false;
2211 need_activate_chain =
true;
2215 if (need_activate_chain) {
2217 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2224 bool can_direct_fetch{
false};
2232 if (!BlockRequestAllowed(pindex)) {
2233 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2250 LogDebug(
BCLog::NET,
"Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.
GetId());
2260 can_direct_fetch = CanDirectFetch();
2264 std::shared_ptr<const CBlock> pblock;
2265 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2266 pblock = a_recent_block;
2270 std::vector<uint8_t> block_data;
2275 LogError(
"Cannot load block from disk, disconnect peer=%d\n", pfrom.
GetId());
2284 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2289 LogError(
"Cannot load block from disk, disconnect peer=%d\n", pfrom.
GetId());
2294 pblock = pblockRead;
2302 bool sendMerkleBlock =
false;
2304 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2305 LOCK(tx_relay->m_bloom_filter_mutex);
2306 if (tx_relay->m_bloom_filter) {
2307 sendMerkleBlock =
true;
2308 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2311 if (sendMerkleBlock) {
2319 typedef std::pair<unsigned int, uint256> PairType;
2331 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2344 LOCK(peer.m_block_inv_mutex);
2346 if (inv.
hash == peer.m_continuation_block) {
2350 std::vector<CInv> vInv;
2351 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2353 peer.m_continuation_block.SetNull();
2361 auto txinfo = m_mempool.
info_for_relay(gtxid, tx_relay.m_last_inv_sequence);
2363 return std::move(txinfo.tx);
2368 LOCK(m_most_recent_block_mutex);
2369 if (m_most_recent_block_txs !=
nullptr) {
2370 auto it = m_most_recent_block_txs->find(gtxid.
GetHash());
2371 if (it != m_most_recent_block_txs->end())
return it->second;
2378void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2382 auto tx_relay = peer.GetTxRelay();
2384 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2385 std::vector<CInv> vNotFound;
2390 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2391 if (interruptMsgProc)
return;
2396 const CInv &inv = *it++;
2398 if (tx_relay ==
nullptr) {
2408 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2411 vNotFound.push_back(inv);
2417 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2418 const CInv &inv = *it++;
2420 ProcessGetBlockData(pfrom, peer, inv);
2426 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2428 if (!vNotFound.empty()) {
2447uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2449 uint32_t nFetchFlags = 0;
2450 if (CanServeWitnesses(peer)) {
2459 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2461 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2470bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2474 Misbehaving(peer,
"header with invalid proof of work");
2479 if (!CheckHeadersAreContinuous(headers)) {
2480 Misbehaving(peer,
"non-continuous headers sequence");
2505void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2506 const std::vector<CBlockHeader>& headers)
2510 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2511 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2513 headers[0].hashPrevBlock.ToString(),
2514 best_header->nHeight,
2524bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2528 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2531 hashLastBlock = header.GetHash();
2536bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2538 if (peer.m_headers_sync) {
2539 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2541 if (result.success) peer.m_last_getheaders_timestamp = {};
2542 if (result.request_more) {
2543 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2545 Assume(!locator.vHave.empty());
2548 if (!locator.vHave.empty()) {
2551 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2554 locator.vHave.front().ToString(), pfrom.
GetId());
2559 peer.m_headers_sync.reset(
nullptr);
2564 LOCK(m_headers_presync_mutex);
2565 m_headers_presync_stats.erase(pfrom.
GetId());
2568 HeadersPresyncStats stats;
2569 stats.first = peer.m_headers_sync->GetPresyncWork();
2571 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2572 peer.m_headers_sync->GetPresyncTime()};
2576 LOCK(m_headers_presync_mutex);
2577 m_headers_presync_stats[pfrom.
GetId()] = stats;
2578 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2579 bool best_updated =
false;
2580 if (best_it == m_headers_presync_stats.end()) {
2584 const HeadersPresyncStats* stat_best{
nullptr};
2585 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2586 if (!stat_best || stat > *stat_best) {
2591 m_headers_presync_bestpeer = peer_best;
2592 best_updated = (peer_best == pfrom.
GetId());
2593 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2595 m_headers_presync_bestpeer = pfrom.
GetId();
2596 best_updated =
true;
2598 if (best_updated && stats.second.has_value()) {
2600 m_headers_presync_should_signal =
true;
2604 if (result.success) {
2607 headers.swap(result.pow_validated_headers);
2610 return result.success;
2618bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2625 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2629 if (total_work < minimum_chain_work) {
2633 if (headers.size() == m_opts.max_headers_result) {
2643 LOCK(peer.m_headers_sync_mutex);
2645 chain_start_header, minimum_chain_work));
2650 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2664bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2666 if (header ==
nullptr) {
2668 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2676bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2684 peer.m_last_getheaders_timestamp = current_time;
2695void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2698 CNodeState *nodestate = State(pfrom.
GetId());
2701 std::vector<const CBlockIndex*> vToFetch;
2709 vToFetch.push_back(pindexWalk);
2711 pindexWalk = pindexWalk->
pprev;
2722 std::vector<CInv> vGetData;
2724 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2729 uint32_t nFetchFlags = GetFetchFlags(peer);
2731 BlockRequested(pfrom.
GetId(), *pindex);
2735 if (vGetData.size() > 1) {
2740 if (vGetData.size() > 0) {
2741 if (!m_opts.ignore_incoming_txs &&
2742 nodestate->m_provides_cmpctblocks &&
2743 vGetData.size() == 1 &&
2744 mapBlocksInFlight.size() == 1 &&
2760void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2761 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2764 CNodeState *nodestate = State(pfrom.
GetId());
2773 nodestate->m_last_block_announcement =
GetTime();
2781 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2791 LogPrintf(
"Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.
GetId());
2803 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) {
2805 nodestate->m_chain_sync.m_protect =
true;
2806 ++m_outbound_peers_with_protect_from_disconnect;
2811void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2812 std::vector<CBlockHeader>&& headers,
2813 bool via_compact_block)
2815 size_t nCount = headers.size();
2822 LOCK(peer.m_headers_sync_mutex);
2823 if (peer.m_headers_sync) {
2824 peer.m_headers_sync.reset(
nullptr);
2825 LOCK(m_headers_presync_mutex);
2826 m_headers_presync_stats.erase(pfrom.
GetId());
2830 peer.m_last_getheaders_timestamp = {};
2838 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2853 bool already_validated_work =
false;
2856 bool have_headers_sync =
false;
2858 LOCK(peer.m_headers_sync_mutex);
2860 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2872 if (headers.empty()) {
2876 have_headers_sync = !!peer.m_headers_sync;
2881 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2883 if (!headers_connect_blockindex) {
2887 HandleUnconnectingHeaders(pfrom, peer, headers);
2894 peer.m_last_getheaders_timestamp = {};
2904 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2905 already_validated_work =
true;
2913 already_validated_work =
true;
2919 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2920 chain_start_header, headers)) {
2932 bool received_new_header{last_received_header ==
nullptr};
2938 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2945 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
2947 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2949 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2953 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
2956 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
2962 bool first_time_failure)
2968 PeerRef peer{GetPeerRef(nodeid)};
2971 ptx->GetHash().ToString(),
2972 ptx->GetWitnessHash().ToString(),
2976 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
2979 AddToCompactExtraTransactions(ptx);
2981 for (
const uint256& parent_txid : unique_parents) {
2982 if (peer) AddKnownTx(*peer, parent_txid);
2985 MaybePunishNodeForTx(nodeid, state);
2987 return package_to_validate;
2990void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
2996 m_txdownloadman.MempoolAcceptedTx(tx);
3000 tx->GetHash().ToString(),
3001 tx->GetWitnessHash().ToString(),
3004 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3007 AddToCompactExtraTransactions(removedTx);
3017 const auto&
package = package_to_validate.m_txns;
3018 const auto& senders = package_to_validate.
m_senders;
3021 m_txdownloadman.MempoolRejectedPackage(package);
3024 if (!
Assume(package.size() == 2))
return;
3028 auto package_iter = package.rbegin();
3029 auto senders_iter = senders.rbegin();
3030 while (package_iter != package.rend()) {
3031 const auto& tx = *package_iter;
3032 const NodeId nodeid = *senders_iter;
3033 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3037 const auto& tx_result = it_result->second;
3038 switch (tx_result.m_result_type) {
3041 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3051 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3067bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3074 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3077 const Txid& orphanHash = porphanTx->GetHash();
3078 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3095 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3104bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3106 const uint256& stop_hash, uint32_t max_height_diff,
3110 const bool supported_filter_type =
3113 if (!supported_filter_type) {
3115 node.GetId(),
static_cast<uint8_t
>(filter_type));
3116 node.fDisconnect =
true;
3125 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3128 node.fDisconnect =
true;
3133 uint32_t stop_height = stop_index->
nHeight;
3134 if (start_height > stop_height) {
3136 "start height %d and stop height %d\n",
3137 node.GetId(), start_height, stop_height);
3138 node.fDisconnect =
true;
3141 if (stop_height - start_height >= max_height_diff) {
3143 node.GetId(), stop_height - start_height + 1, max_height_diff);
3144 node.fDisconnect =
true;
3149 if (!filter_index) {
3159 uint8_t filter_type_ser;
3160 uint32_t start_height;
3163 vRecv >> filter_type_ser >> start_height >> stop_hash;
3169 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3174 std::vector<BlockFilter> filters;
3176 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3181 for (
const auto& filter : filters) {
3188 uint8_t filter_type_ser;
3189 uint32_t start_height;
3192 vRecv >> filter_type_ser >> start_height >> stop_hash;
3198 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3204 if (start_height > 0) {
3206 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3208 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3214 std::vector<uint256> filter_hashes;
3216 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3230 uint8_t filter_type_ser;
3233 vRecv >> filter_type_ser >> stop_hash;
3239 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3240 std::numeric_limits<uint32_t>::max(),
3241 stop_index, filter_index)) {
3249 for (
int i = headers.size() - 1; i >= 0; i--) {
3254 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3266void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked)
3268 bool new_block{
false};
3269 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3271 node.m_last_block_time = GetTime<std::chrono::seconds>();
3276 RemoveBlockRequest(block->GetHash(), std::nullopt);
3279 mapBlockSource.erase(block->GetHash());
3283void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3285 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3286 bool fBlockRead{
false};
3290 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3291 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3292 bool requested_block_from_this_peer{
false};
3295 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3297 while (range_flight.first != range_flight.second) {
3298 auto [node_id, block_it] = range_flight.first->second;
3299 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3300 requested_block_from_this_peer =
true;
3303 range_flight.first++;
3306 if (!requested_block_from_this_peer) {
3315 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3318 if (first_in_flight) {
3320 std::vector<CInv> invs;
3325 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3354 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3364 ProcessBlock(pfrom, pblock,
true,
true);
3369void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3370 const std::chrono::microseconds time_received,
3371 const std::atomic<bool>& interruptMsgProc)
3377 PeerRef peer = GetPeerRef(pfrom.
GetId());
3378 if (peer ==
nullptr)
return;
3388 uint64_t nNonce = 1;
3391 std::string cleanSubVer;
3392 int starting_height = -1;
3395 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3410 LogDebug(
BCLog::NET,
"peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom.
GetId(), nServices, GetDesirableServiceFlags(nServices));
3422 if (!vRecv.
empty()) {
3430 if (!vRecv.
empty()) {
3431 std::string strSubVer;
3435 if (!vRecv.
empty()) {
3436 vRecv >> starting_height;
3456 PushNodeVersion(pfrom, *peer);
3469 if (greatest_common_version >= 70016) {
3478 peer->m_their_services = nServices;
3482 pfrom.cleanSubVer = cleanSubVer;
3484 peer->m_starting_height = starting_height;
3494 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3495 auto*
const tx_relay = peer->SetTxRelay();
3497 LOCK(tx_relay->m_bloom_filter_mutex);
3498 tx_relay->m_relay_txs = fRelay;
3510 const auto* tx_relay = peer->GetTxRelay();
3511 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3513 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3524 CNodeState* state = State(pfrom.
GetId());
3526 m_num_preferred_download_peers += state->fPreferredDownload;
3532 bool send_getaddr{
false};
3534 send_getaddr = SetupAddressRelay(pfrom, *peer);
3544 peer->m_getaddr_sent =
true;
3568 std::string remoteAddr;
3573 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3576 remoteAddr, (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3578 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3582 m_outbound_time_offsets.Add(peer->m_time_offset);
3583 m_outbound_time_offsets.WarnIfOutOfSync();
3587 if (greatest_common_version <= 70012) {
3588 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3589 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3616 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3619 pfrom.
nVersion.load(), peer->m_starting_height,
3621 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3633 if (m_txreconciliation) {
3634 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3638 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3642 if (
auto tx_relay = peer->GetTxRelay()) {
3651 tx_relay->m_tx_inventory_mutex,
3652 return tx_relay->m_tx_inventory_to_send.empty() &&
3653 tx_relay->m_next_inv_send_time == 0
s));
3658 const CNodeState* state = State(pfrom.
GetId());
3660 .m_preferred = state->fPreferredDownload,
3661 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3662 .m_wtxid_relay = peer->m_wtxid_relay,
3671 peer->m_prefers_headers =
true;
3676 bool sendcmpct_hb{
false};
3677 uint64_t sendcmpct_version{0};
3678 vRecv >> sendcmpct_hb >> sendcmpct_version;
3684 CNodeState* nodestate = State(pfrom.
GetId());
3685 nodestate->m_provides_cmpctblocks =
true;
3686 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3703 if (!peer->m_wtxid_relay) {
3704 peer->m_wtxid_relay =
true;
3705 m_wtxid_relay_peers++;
3724 peer->m_wants_addrv2 =
true;
3732 if (!m_txreconciliation) {
3744 if (RejectIncomingTxs(pfrom)) {
3753 const auto* tx_relay = peer->GetTxRelay();
3754 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3760 uint32_t peer_txreconcl_version;
3761 uint64_t remote_salt;
3762 vRecv >> peer_txreconcl_version >> remote_salt;
3765 peer_txreconcl_version, remote_salt);
3790 const auto ser_params{
3798 std::vector<CAddress> vAddr;
3800 vRecv >> ser_params(vAddr);
3802 if (!SetupAddressRelay(pfrom, *peer)) {
3809 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3814 std::vector<CAddress> vAddrOk;
3815 const auto current_a_time{Now<NodeSeconds>()};
3818 const auto current_time{GetTime<std::chrono::microseconds>()};
3821 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3825 peer->m_addr_token_timestamp = current_time;
3828 uint64_t num_proc = 0;
3829 uint64_t num_rate_limit = 0;
3830 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
3833 if (interruptMsgProc)
3837 if (peer->m_addr_token_bucket < 1.0) {
3843 peer->m_addr_token_bucket -= 1.0;
3852 addr.
nTime = current_a_time - 5 * 24h;
3854 AddAddressKnown(*peer, addr);
3861 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3863 RelayAddress(pfrom.
GetId(), addr, reachable);
3867 vAddrOk.push_back(addr);
3870 peer->m_addr_processed += num_proc;
3871 peer->m_addr_rate_limited += num_rate_limit;
3872 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3873 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3875 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3876 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3887 std::vector<CInv> vInv;
3891 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
3895 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3899 const auto current_time{GetTime<std::chrono::microseconds>()};
3902 for (
CInv& inv : vInv) {
3903 if (interruptMsgProc)
return;
3908 if (peer->m_wtxid_relay) {
3915 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3918 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3926 best_block = &inv.
hash;
3929 if (reject_tx_invs) {
3935 AddKnownTx(*peer, inv.
hash);
3938 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time,
true)};
3946 if (best_block !=
nullptr) {
3958 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
3959 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
3961 m_chainman.m_best_header->nHeight, best_block->ToString(),
3964 if (!state.fSyncStarted) {
3965 peer->m_inv_triggered_getheaders_before_sync =
true;
3969 m_last_block_inv_triggering_headers_sync = *best_block;
3978 std::vector<CInv> vInv;
3982 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
3988 if (vInv.size() > 0) {
3993 LOCK(peer->m_getdata_requests_mutex);
3994 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
3995 ProcessGetData(pfrom, *peer, interruptMsgProc);
4004 vRecv >> locator >> hashStop;
4020 std::shared_ptr<const CBlock> a_recent_block;
4022 LOCK(m_most_recent_block_mutex);
4023 a_recent_block = m_most_recent_block;
4026 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4041 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4056 if (--nLimit <= 0) {
4060 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4071 std::shared_ptr<const CBlock> recent_block;
4073 LOCK(m_most_recent_block_mutex);
4074 if (m_most_recent_block_hash == req.
blockhash)
4075 recent_block = m_most_recent_block;
4079 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4098 if (!block_pos.IsNull()) {
4105 SendBlockTransactions(pfrom, *peer, block, req);
4118 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4126 vRecv >> locator >> hashStop;
4148 if (m_chainman.
ActiveTip() ==
nullptr ||
4150 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4157 CNodeState *nodestate = State(pfrom.
GetId());
4167 if (!BlockRequestAllowed(pindex)) {
4168 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4181 std::vector<CBlock> vHeaders;
4182 int nLimit = m_opts.max_headers_result;
4184 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4187 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4202 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4208 if (RejectIncomingTxs(pfrom)) {
4223 const uint256& txid = ptx->GetHash();
4224 const uint256& wtxid = ptx->GetWitnessHash();
4226 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4227 AddKnownTx(*peer, hash);
4231 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4232 if (!should_validate) {
4238 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4241 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4247 if (package_to_validate) {
4250 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4251 ProcessPackageResult(package_to_validate.value(), package_result);
4257 Assume(!package_to_validate.has_value());
4267 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4270 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4271 ProcessPackageResult(package_to_validate.value(), package_result);
4287 vRecv >> cmpctblock;
4289 bool received_new_header =
false;
4299 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4309 received_new_header =
true;
4317 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4322 if (received_new_header) {
4323 LogInfo(
"Saw new cmpctblock header hash=%s peer=%d\n",
4324 blockhash.ToString(), pfrom.
GetId());
4327 bool fProcessBLOCKTXN =
false;
4331 bool fRevertToHeaderProcessing =
false;
4335 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4336 bool fBlockReconstructed =
false;
4344 CNodeState *nodestate = State(pfrom.
GetId());
4349 nodestate->m_last_block_announcement =
GetTime();
4355 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4356 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4357 bool requested_block_from_this_peer{
false};
4360 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4362 while (range_flight.first != range_flight.second) {
4363 if (range_flight.first->second.first == pfrom.
GetId()) {
4364 requested_block_from_this_peer =
true;
4367 range_flight.first++;
4372 if (requested_block_from_this_peer) {
4375 std::vector<CInv> vInv(1);
4376 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4383 if (!already_in_flight && !CanDirectFetch()) {
4391 requested_block_from_this_peer) {
4392 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4393 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4394 if (!(*queuedBlockIt)->partialBlock)
4407 Misbehaving(*peer,
"invalid compact block");
4410 if (first_in_flight) {
4412 std::vector<CInv> vInv(1);
4413 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4423 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4428 fProcessBLOCKTXN =
true;
4429 }
else if (first_in_flight) {
4436 IsBlockRequestedFromOutbound(blockhash) ||
4455 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4460 std::vector<CTransactionRef> dummy;
4461 status = tempBlock.FillBlock(*pblock, dummy);
4463 fBlockReconstructed =
true;
4467 if (requested_block_from_this_peer) {
4470 std::vector<CInv> vInv(1);
4471 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4476 fRevertToHeaderProcessing =
true;
4481 if (fProcessBLOCKTXN) {
4484 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4487 if (fRevertToHeaderProcessing) {
4493 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4496 if (fBlockReconstructed) {
4501 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4512 ProcessBlock(pfrom, pblock,
true,
true);
4519 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4536 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4547 std::vector<CBlockHeader> headers;
4551 if (nCount > m_opts.max_headers_result) {
4552 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4555 headers.resize(nCount);
4556 for (
unsigned int n = 0; n < nCount; n++) {
4557 vRecv >> headers[n];
4561 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4565 if (m_headers_presync_should_signal.exchange(
false)) {
4566 HeadersPresyncStats stats;
4568 LOCK(m_headers_presync_mutex);
4569 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4570 if (it != m_headers_presync_stats.end()) stats = it->second;
4588 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4599 Misbehaving(*peer,
"mutated block");
4604 bool forceProcessing =
false;
4605 const uint256 hash(pblock->GetHash());
4606 bool min_pow_checked =
false;
4611 forceProcessing = IsBlockRequested(hash);
4612 RemoveBlockRequest(hash, pfrom.
GetId());
4616 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4620 min_pow_checked =
true;
4623 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4640 Assume(SetupAddressRelay(pfrom, *peer));
4644 if (peer->m_getaddr_recvd) {
4648 peer->m_getaddr_recvd =
true;
4650 peer->m_addrs_to_send.clear();
4651 std::vector<CAddress> vAddr;
4657 for (
const CAddress &addr : vAddr) {
4658 PushAddress(*peer, addr);
4686 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4687 LOCK(tx_relay->m_tx_inventory_mutex);
4688 tx_relay->m_send_mempool =
true;
4714 const auto ping_end = time_received;
4717 bool bPingFinished =
false;
4718 std::string sProblem;
4720 if (nAvail >=
sizeof(
nonce)) {
4724 if (peer->m_ping_nonce_sent != 0) {
4725 if (
nonce == peer->m_ping_nonce_sent) {
4727 bPingFinished =
true;
4728 const auto ping_time = ping_end - peer->m_ping_start.load();
4729 if (ping_time.count() >= 0) {
4734 sProblem =
"Timing mishap";
4738 sProblem =
"Nonce mismatch";
4741 bPingFinished =
true;
4742 sProblem =
"Nonce zero";
4746 sProblem =
"Unsolicited pong without ping";
4750 bPingFinished =
true;
4751 sProblem =
"Short payload";
4754 if (!(sProblem.empty())) {
4758 peer->m_ping_nonce_sent,
4762 if (bPingFinished) {
4763 peer->m_ping_nonce_sent = 0;
4770 LogDebug(
BCLog::NET,
"filterload received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4780 Misbehaving(*peer,
"too-large bloom filter");
4781 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4783 LOCK(tx_relay->m_bloom_filter_mutex);
4784 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4785 tx_relay->m_relay_txs =
true;
4795 LogDebug(
BCLog::NET,
"filteradd received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4799 std::vector<unsigned char> vData;
4807 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4808 LOCK(tx_relay->m_bloom_filter_mutex);
4809 if (tx_relay->m_bloom_filter) {
4810 tx_relay->m_bloom_filter->insert(vData);
4816 Misbehaving(*peer,
"bad filteradd message");
4823 LogDebug(
BCLog::NET,
"filterclear received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4827 auto tx_relay = peer->GetTxRelay();
4828 if (!tx_relay)
return;
4831 LOCK(tx_relay->m_bloom_filter_mutex);
4832 tx_relay->m_bloom_filter =
nullptr;
4833 tx_relay->m_relay_txs =
true;
4842 vRecv >> newFeeFilter;
4844 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4845 tx_relay->m_fee_filter_received = newFeeFilter;
4853 ProcessGetCFilters(pfrom, *peer, vRecv);
4858 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4863 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4868 std::vector<CInv> vInv;
4870 std::vector<uint256> tx_invs;
4872 for (
CInv &inv : vInv) {
4874 tx_invs.emplace_back(inv.
hash);
4878 LOCK(m_tx_download_mutex);
4879 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
4888bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4891 LOCK(peer.m_misbehavior_mutex);
4894 if (!peer.m_should_discourage)
return false;
4896 peer.m_should_discourage =
false;
4901 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
4907 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
4927bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4932 PeerRef peer = GetPeerRef(pfrom->
GetId());
4933 if (peer ==
nullptr)
return false;
4937 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
4940 LOCK(peer->m_getdata_requests_mutex);
4941 if (!peer->m_getdata_requests.empty()) {
4942 ProcessGetData(*pfrom, *peer, interruptMsgProc);
4946 const bool processed_orphan = ProcessOrphanTx(*peer);
4951 if (processed_orphan)
return true;
4956 LOCK(peer->m_getdata_requests_mutex);
4957 if (!peer->m_getdata_requests.empty())
return true;
4970 bool fMoreWork = poll_result->second;
4981 if (m_opts.capture_messages) {
4986 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
4987 if (interruptMsgProc)
return false;
4989 LOCK(peer->m_getdata_requests_mutex);
4990 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
4997 LOCK(m_tx_download_mutex);
4998 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
4999 }
catch (
const std::exception& e) {
5008void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5012 CNodeState &state = *State(pto.
GetId());
5021 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5023 if (state.m_chain_sync.m_timeout != 0
s) {
5024 state.m_chain_sync.m_timeout = 0
s;
5025 state.m_chain_sync.m_work_header =
nullptr;
5026 state.m_chain_sync.m_sent_getheaders =
false;
5028 }
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)) {
5036 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5037 state.m_chain_sync.m_sent_getheaders =
false;
5038 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5042 if (state.m_chain_sync.m_sent_getheaders) {
5044 LogPrintf(
"Disconnecting outbound peer %d for old chain, best known block = %s\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>");
5047 assert(state.m_chain_sync.m_work_header);
5052 MaybeSendGetHeaders(pto,
5053 GetLocator(state.m_chain_sync.m_work_header->pprev),
5055 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());
5056 state.m_chain_sync.m_sent_getheaders =
true;
5068void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5077 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5081 if (pnode->
GetId() > youngest_peer.first) {
5082 next_youngest_peer = youngest_peer;
5083 youngest_peer.first = pnode->GetId();
5084 youngest_peer.second = pnode->m_last_block_time;
5087 NodeId to_disconnect = youngest_peer.first;
5088 if (youngest_peer.second > next_youngest_peer.second) {
5091 to_disconnect = next_youngest_peer.first;
5100 CNodeState *node_state = State(pnode->
GetId());
5101 if (node_state ==
nullptr ||
5104 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5108 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5124 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5127 AssertLockHeld(::cs_main);
5131 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5132 CNodeState *state = State(pnode->GetId());
5133 if (state == nullptr) return;
5135 if (state->m_chain_sync.m_protect) return;
5138 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5139 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5140 worst_peer = pnode->GetId();
5141 oldest_block_announcement = state->m_last_block_announcement;
5144 if (worst_peer != -1) {
5153 CNodeState &state = *State(pnode->
GetId());
5155 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5159 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5176void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5180 auto now{GetTime<std::chrono::seconds>()};
5182 EvictExtraOutboundPeers(now);
5184 if (now > m_stale_tip_check_time) {
5188 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5197 if (!m_initial_sync_finished && CanDirectFetch()) {
5199 m_initial_sync_finished =
true;
5203void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5206 peer.m_ping_nonce_sent &&
5216 bool pingSend =
false;
5218 if (peer.m_ping_queued) {
5223 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5232 }
while (
nonce == 0);
5233 peer.m_ping_queued =
false;
5234 peer.m_ping_start = now;
5236 peer.m_ping_nonce_sent =
nonce;
5240 peer.m_ping_nonce_sent = 0;
5246void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5249 if (!peer.m_addr_relay_enabled)
return;
5251 LOCK(peer.m_addr_send_times_mutex);
5254 peer.m_next_local_addr_send < current_time) {
5261 if (peer.m_next_local_addr_send != 0us) {
5262 peer.m_addr_known->reset();
5265 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5266 PushAddress(peer, local_addr);
5272 if (current_time <= peer.m_next_addr_send)
return;
5285 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5286 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5289 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5290 peer.m_addrs_to_send.end());
5293 if (peer.m_addrs_to_send.empty())
return;
5295 if (peer.m_wants_addrv2) {
5300 peer.m_addrs_to_send.clear();
5303 if (peer.m_addrs_to_send.capacity() > 40) {
5304 peer.m_addrs_to_send.shrink_to_fit();
5308void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5316 CNodeState &state = *State(
node.GetId());
5317 if (state.pindexBestKnownBlock !=
nullptr &&
5324 peer.m_sent_sendheaders =
true;
5329void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5331 if (m_opts.ignore_incoming_txs)
return;
5347 if (peer.m_fee_filter_sent == MAX_FILTER) {
5350 peer.m_next_send_feefilter = 0us;
5353 if (current_time > peer.m_next_send_feefilter) {
5354 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5357 if (filterToSend != peer.m_fee_filter_sent) {
5359 peer.m_fee_filter_sent = filterToSend;
5366 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5372class CompareInvMempoolOrder
5377 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5380 m_wtxid_relay = use_wtxid;
5383 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5387 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5392bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5402bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5407 if (
node.IsBlockOnlyConn())
return false;
5409 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5413 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5419bool PeerManagerImpl::SendMessages(
CNode* pto)
5424 PeerRef peer = GetPeerRef(pto->
GetId());
5425 if (!peer)
return false;
5430 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5433 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5434 PushNodeVersion(*pto, *peer);
5435 peer->m_outbound_version_message_sent =
true;
5442 const auto current_time{GetTime<std::chrono::microseconds>()};
5450 MaybeSendPing(*pto, *peer, current_time);
5455 MaybeSendAddr(*pto, *peer, current_time);
5457 MaybeSendSendHeaders(*pto, *peer);
5462 CNodeState &state = *State(pto->
GetId());
5465 if (m_chainman.m_best_header ==
nullptr) {
5472 bool sync_blocks_and_headers_from_peer =
false;
5473 if (state.fPreferredDownload) {
5474 sync_blocks_and_headers_from_peer =
true;
5485 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5486 sync_blocks_and_headers_from_peer =
true;
5492 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5493 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5501 if (pindexStart->
pprev)
5502 pindexStart = pindexStart->
pprev;
5503 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5506 state.fSyncStarted =
true;
5530 LOCK(peer->m_block_inv_mutex);
5531 std::vector<CBlock> vHeaders;
5532 bool fRevertToInv = ((!peer->m_prefers_headers &&
5533 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5536 ProcessBlockAvailability(pto->
GetId());
5538 if (!fRevertToInv) {
5539 bool fFoundStartingHeader =
false;
5543 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5548 fRevertToInv =
true;
5551 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5563 fRevertToInv =
true;
5566 pBestIndex = pindex;
5567 if (fFoundStartingHeader) {
5570 }
else if (PeerHasHeader(&state, pindex)) {
5572 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5575 fFoundStartingHeader =
true;
5580 fRevertToInv =
true;
5585 if (!fRevertToInv && !vHeaders.empty()) {
5586 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5590 vHeaders.front().GetHash().ToString(), pto->
GetId());
5592 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5594 LOCK(m_most_recent_block_mutex);
5595 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5599 if (cached_cmpctblock_msg.has_value()) {
5600 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5608 state.pindexBestHeaderSent = pBestIndex;
5609 }
else if (peer->m_prefers_headers) {
5610 if (vHeaders.size() > 1) {
5613 vHeaders.front().GetHash().ToString(),
5614 vHeaders.back().GetHash().ToString(), pto->
GetId());
5617 vHeaders.front().GetHash().ToString(), pto->
GetId());
5620 state.pindexBestHeaderSent = pBestIndex;
5622 fRevertToInv =
true;
5628 if (!peer->m_blocks_for_headers_relay.empty()) {
5629 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5642 if (!PeerHasHeader(&state, pindex)) {
5643 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5649 peer->m_blocks_for_headers_relay.clear();
5655 std::vector<CInv> vInv;
5657 LOCK(peer->m_block_inv_mutex);
5661 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5668 peer->m_blocks_for_inv_relay.clear();
5671 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5672 LOCK(tx_relay->m_tx_inventory_mutex);
5675 if (tx_relay->m_next_inv_send_time < current_time) {
5676 fSendTrickle =
true;
5686 LOCK(tx_relay->m_bloom_filter_mutex);
5687 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5691 if (fSendTrickle && tx_relay->m_send_mempool) {
5692 auto vtxinfo = m_mempool.
infoAll();
5693 tx_relay->m_send_mempool =
false;
5694 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5696 LOCK(tx_relay->m_bloom_filter_mutex);
5698 for (
const auto& txinfo : vtxinfo) {
5701 peer->m_wtxid_relay ?
5702 txinfo.tx->GetWitnessHash().ToUint256() :
5703 txinfo.tx->GetHash().ToUint256(),
5705 tx_relay->m_tx_inventory_to_send.erase(inv.
hash);
5708 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5711 if (tx_relay->m_bloom_filter) {
5712 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5714 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5715 vInv.push_back(inv);
5726 std::vector<std::set<uint256>::iterator> vInvTx;
5727 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5728 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5729 vInvTx.push_back(it);
5731 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5734 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
5735 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5738 unsigned int nRelayedTransactions = 0;
5739 LOCK(tx_relay->m_bloom_filter_mutex);
5742 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5744 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5745 std::set<uint256>::iterator it = vInvTx.back();
5750 tx_relay->m_tx_inventory_to_send.erase(it);
5752 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
5761 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5764 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5766 vInv.push_back(inv);
5767 nRelayedTransactions++;
5772 tx_relay->m_tx_inventory_known_filter.insert(hash);
5777 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5784 auto stalling_timeout = m_block_stalling_timeout.load();
5785 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5794 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5804 if (state.vBlocksInFlight.size() > 0) {
5805 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5806 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5814 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5816 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5817 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5834 state.fSyncStarted =
false;
5836 peer->m_headers_sync_timeout = 0us;
5842 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5848 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5853 std::vector<CInv> vGetData;
5855 std::vector<const CBlockIndex*> vToDownload;
5857 auto get_inflight_budget = [&state]() {
5863 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5868 TryDownloadingHistoricalBlocks(
5870 get_inflight_budget(),
5871 vToDownload, from_tip,
5872 Assert(m_chainman.GetSnapshotBaseBlock()));
5875 uint32_t nFetchFlags = GetFetchFlags(*peer);
5877 BlockRequested(pto->
GetId(), *pindex);
5881 if (state.vBlocksInFlight.empty() && staller != -1) {
5882 if (State(staller)->m_stalling_since == 0us) {
5883 State(staller)->m_stalling_since = current_time;
5893 LOCK(m_tx_download_mutex);
5894 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
5903 if (!vGetData.empty())
5906 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, checkpoint.
@ 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.
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::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)
A Span is an object that can refer to a contiguous sequence of objects.
std::string ToString() const
256-bit unsigned big integer.
constexpr bool IsNull() const
std::string ToString() const
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool ReadRawBlockFromDisk(std::vector< uint8_t > &block, const FlatFilePos &pos) const
bool LoadingBlocks() 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_CHECKPOINT
the block failed to meet one of our checkpoints
@ 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.
#define LogPrintLevel(category, level,...)
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, 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(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the 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< uint256, 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.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
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
#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.
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...