74#include <initializer_list>
212 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
246 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
249 const bool m_is_inbound;
252 Mutex m_misbehavior_mutex;
254 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
257 Mutex m_block_inv_mutex;
261 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
265 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
277 std::atomic<int> m_starting_height{-1};
280 std::atomic<uint64_t> m_ping_nonce_sent{0};
282 std::atomic<std::chrono::microseconds> m_ping_start{0us};
284 std::atomic<bool> m_ping_queued{
false};
287 std::atomic<bool> m_wtxid_relay{
false};
299 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
301 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
312 std::set<Wtxid> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
316 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
319 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
322 uint64_t m_last_inv_sequence
GUARDED_BY(m_tx_inventory_mutex){1};
325 std::atomic<CAmount> m_fee_filter_received{0};
331 LOCK(m_tx_relay_mutex);
333 m_tx_relay = std::make_unique<Peer::TxRelay>();
334 return m_tx_relay.get();
339 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
368 std::atomic_bool m_addr_relay_enabled{
false};
372 mutable Mutex m_addr_send_times_mutex;
374 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
376 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
379 std::atomic_bool m_wants_addrv2{
false};
388 std::atomic<uint64_t> m_addr_rate_limited{0};
390 std::atomic<uint64_t> m_addr_processed{0};
396 Mutex m_getdata_requests_mutex;
398 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
404 Mutex m_headers_sync_mutex;
407 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
410 std::atomic<bool> m_sent_sendheaders{
false};
420 std::atomic<std::chrono::seconds> m_time_offset{0
s};
424 , m_our_services{our_services}
425 , m_is_inbound{is_inbound}
429 mutable Mutex m_tx_relay_mutex;
432 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
435using PeerRef = std::shared_ptr<Peer>;
447 uint256 hashLastUnknownBlock{};
453 bool fSyncStarted{
false};
455 std::chrono::microseconds m_stalling_since{0us};
456 std::list<QueuedBlock> vBlocksInFlight;
458 std::chrono::microseconds m_downloading_since{0us};
460 bool fPreferredDownload{
false};
462 bool m_requested_hb_cmpctblocks{
false};
464 bool m_provides_cmpctblocks{
false};
490 struct ChainSyncTimeoutState {
492 std::chrono::seconds m_timeout{0
s};
496 bool m_sent_getheaders{
false};
498 bool m_protect{
false};
501 ChainSyncTimeoutState m_chain_sync;
504 int64_t m_last_block_announcement{0};
533 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
548 void SetBestBlock(
int height,
std::chrono::seconds time)
override
550 m_best_height = height;
551 m_best_block_time = time;
555 std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
556 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
571 void ReattemptPrivateBroadcast(
CScheduler& scheduler);
583 void Misbehaving(Peer& peer,
const std::string& message);
594 bool via_compact_block,
const std::string& message =
"")
603 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
617 bool first_time_failure)
642 bool ProcessOrphanTx(Peer& peer)
652 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
654 bool via_compact_block)
658 bool CheckHeadersPoW(const
std::vector<
CBlockHeader>& headers, Peer& peer);
666 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
685 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
699 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
714 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
716 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
723 template <
typename... Args>
724 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
730 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
736 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
779 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
782 std::atomic<int> m_best_height{-1};
784 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
792 const Options m_opts;
794 bool RejectIncomingTxs(
const CNode& peer)
const;
802 mutable Mutex m_peer_mutex;
809 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
819 uint32_t GetFetchFlags(
const Peer& peer)
const;
821 std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key
GUARDED_BY(g_msgproc_mutex);
838 std::atomic<int> m_wtxid_relay_peers{0};
856 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
857 std::chrono::seconds average_interval,
862 Mutex m_most_recent_block_mutex;
863 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
864 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
866 std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
870 Mutex m_headers_presync_mutex;
878 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
880 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
884 std::atomic_bool m_headers_presync_should_signal{
false};
954 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
960 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
965 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
998 std::vector<std::pair<Wtxid, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
1000 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1012 int64_t ApproximateBestBlockDepth() const;
1022 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1040 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1042 const
uint256& stop_hash, uint32_t max_height_diff,
1090 void LogBlockHeader(const
CBlockIndex& index, const
CNode& peer,
bool via_compact_block);
1096const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const
1098 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1099 if (it == m_node_states.end())
1106 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1114static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1119void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1121 assert(peer.m_addr_known);
1122 peer.m_addr_known->insert(addr.
GetKey());
1125void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1130 assert(peer.m_addr_known);
1131 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1133 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1135 peer.m_addrs_to_send.push_back(addr);
1140static void AddKnownTx(Peer& peer,
const uint256& hash)
1142 auto tx_relay = peer.GetTxRelay();
1143 if (!tx_relay)
return;
1145 LOCK(tx_relay->m_tx_inventory_mutex);
1146 tx_relay->m_tx_inventory_known_filter.insert(hash);
1150static bool CanServeBlocks(
const Peer& peer)
1157static bool IsLimitedPeer(
const Peer& peer)
1164static bool CanServeWitnesses(
const Peer& peer)
1169std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1170 std::chrono::seconds average_interval,
1171 uint64_t network_key)
1173 auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
1174 auto& timer{it->second};
1176 timer = now + m_rng.rand_exp_duration(average_interval);
1181bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1183 return mapBlocksInFlight.contains(hash);
1186bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1188 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1189 auto [nodeid, block_it] = range.first->second;
1190 PeerRef peer{GetPeerRef(nodeid)};
1191 if (peer && !peer->m_is_inbound)
return true;
1197void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1199 auto range = mapBlocksInFlight.equal_range(hash);
1200 if (range.first == range.second) {
1208 while (range.first != range.second) {
1209 const auto& [node_id, list_it]{range.first->second};
1211 if (from_peer && *from_peer != node_id) {
1218 if (state.vBlocksInFlight.begin() == list_it) {
1220 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1222 state.vBlocksInFlight.erase(list_it);
1224 if (state.vBlocksInFlight.empty()) {
1226 m_peers_downloading_from--;
1228 state.m_stalling_since = 0us;
1230 range.first = mapBlocksInFlight.erase(range.first);
1234bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1238 CNodeState *state =
State(nodeid);
1239 assert(state !=
nullptr);
1244 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1245 if (range.first->second.first == nodeid) {
1247 *pit = &range.first->second.second;
1254 RemoveBlockRequest(hash, nodeid);
1256 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1257 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1258 if (state->vBlocksInFlight.size() == 1) {
1260 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1261 m_peers_downloading_from++;
1263 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1265 *pit = &itInFlight->second.second;
1270void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1277 if (m_opts.ignore_incoming_txs)
return;
1279 CNodeState* nodestate =
State(nodeid);
1280 PeerRef peer{GetPeerRef(nodeid)};
1281 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1286 int num_outbound_hb_peers = 0;
1287 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1288 if (*it == nodeid) {
1289 lNodesAnnouncingHeaderAndIDs.erase(it);
1290 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1293 PeerRef peer_ref{GetPeerRef(*it)};
1294 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1296 if (peer && peer->m_is_inbound) {
1299 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1300 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1301 if (remove_peer && !remove_peer->m_is_inbound) {
1304 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1310 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1313 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1314 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1316 pnodeStop->m_bip152_highbandwidth_to = false;
1319 lNodesAnnouncingHeaderAndIDs.pop_front();
1324 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1329bool PeerManagerImpl::TipMayBeStale()
1333 if (m_last_tip_update.load() == 0
s) {
1334 m_last_tip_update = GetTime<std::chrono::seconds>();
1336 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1339int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1344bool PeerManagerImpl::CanDirectFetch()
1351 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1353 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1358void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1359 CNodeState *state =
State(nodeid);
1360 assert(state !=
nullptr);
1362 if (!state->hashLastUnknownBlock.IsNull()) {
1365 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1366 state->pindexBestKnownBlock = pindex;
1368 state->hashLastUnknownBlock.SetNull();
1373void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1374 CNodeState *state =
State(nodeid);
1375 assert(state !=
nullptr);
1377 ProcessBlockAvailability(nodeid);
1382 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1383 state->pindexBestKnownBlock = pindex;
1387 state->hashLastUnknownBlock = hash;
1392void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1397 vBlocks.reserve(vBlocks.size() +
count);
1398 CNodeState *state =
State(peer.m_id);
1399 assert(state !=
nullptr);
1402 ProcessBlockAvailability(peer.m_id);
1404 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1413 if (snap_base && state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1414 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1423 if (state->pindexLastCommonBlock ==
nullptr ||
1424 fork_point->nChainWork > state->pindexLastCommonBlock->nChainWork ||
1425 state->pindexBestKnownBlock->GetAncestor(state->pindexLastCommonBlock->nHeight) != state->pindexLastCommonBlock) {
1426 state->pindexLastCommonBlock = fork_point;
1428 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1431 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1437 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1440void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1445 if (vBlocks.size() >=
count) {
1449 vBlocks.reserve(
count);
1452 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1469void 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)
1471 std::vector<const CBlockIndex*> vToFetch;
1472 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1473 bool is_limited_peer = IsLimitedPeer(peer);
1475 while (pindexWalk->
nHeight < nMaxHeight) {
1479 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1480 vToFetch.resize(nToFetch);
1481 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1482 vToFetch[nToFetch - 1] = pindexWalk;
1483 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1484 vToFetch[i - 1] = vToFetch[i]->
pprev;
1504 state->pindexLastCommonBlock = pindex;
1511 if (waitingfor == -1) {
1513 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1519 if (pindex->
nHeight > nWindowEnd) {
1521 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1523 if (nodeStaller) *nodeStaller = waitingfor;
1533 vBlocks.push_back(pindex);
1534 if (vBlocks.size() ==
count) {
1543void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1545 uint64_t my_services;
1547 uint64_t your_services;
1549 std::string my_user_agent;
1557 my_user_agent =
"/pynode:0.0.1/";
1559 my_tx_relay =
false;
1562 my_services = peer.m_our_services;
1567 my_height = m_best_height;
1568 my_tx_relay = !RejectIncomingTxs(pnode);
1587 BCLog::NET,
"send version message: version=%d, blocks=%d%s, txrelay=%d, peer=%d\n",
1590 my_tx_relay, pnode.
GetId());
1593void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1597 if (state) state->m_last_block_announcement = time_in_seconds;
1605 m_node_states.try_emplace(m_node_states.end(), nodeid);
1607 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1613 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1616 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1620void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1624 for (
const auto& txid : unbroadcast_txids) {
1627 if (tx !=
nullptr) {
1628 InitiateTxBroadcastToAll(txid, tx->GetWitnessHash());
1637 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1640void PeerManagerImpl::ReattemptPrivateBroadcast(
CScheduler& scheduler)
1644 size_t num_for_rebroadcast{0};
1645 const auto stale_txs = m_tx_for_private_broadcast.
GetStale();
1646 if (!stale_txs.empty()) {
1648 for (
const auto& stale_tx : stale_txs) {
1652 "Reattempting broadcast of stale txid=%s wtxid=%s",
1653 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString());
1654 ++num_for_rebroadcast;
1656 LogInfo(
"[privatebroadcast] Giving up broadcast attempts for txid=%s wtxid=%s: %s",
1657 stale_tx->GetHash().ToString(), stale_tx->GetWitnessHash().ToString(),
1658 mempool_acceptable.m_state.ToString());
1659 m_tx_for_private_broadcast.
Remove(stale_tx);
1668 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, delta);
1671void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1682 PeerRef peer = RemovePeer(nodeid);
1684 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1685 assert(m_wtxid_relay_peers >= 0);
1687 CNodeState *state =
State(nodeid);
1688 assert(state !=
nullptr);
1690 if (state->fSyncStarted)
1693 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1694 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1695 while (range.first != range.second) {
1696 auto [node_id, list_it] = range.first->second;
1697 if (node_id != nodeid) {
1700 range.first = mapBlocksInFlight.erase(range.first);
1705 LOCK(m_tx_download_mutex);
1706 m_txdownloadman.DisconnectedPeer(nodeid);
1708 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1709 m_num_preferred_download_peers -= state->fPreferredDownload;
1710 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1711 assert(m_peers_downloading_from >= 0);
1712 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1713 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1715 m_node_states.erase(nodeid);
1717 if (m_node_states.empty()) {
1719 assert(mapBlocksInFlight.empty());
1720 assert(m_num_preferred_download_peers == 0);
1721 assert(m_peers_downloading_from == 0);
1722 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1723 assert(m_wtxid_relay_peers == 0);
1724 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1727 if (
node.fSuccessfullyConnected &&
1728 !
node.IsBlockOnlyConn() && !
node.IsPrivateBroadcastConn() && !
node.IsInboundConn()) {
1736 LOCK(m_headers_presync_mutex);
1737 m_headers_presync_stats.erase(nodeid);
1739 if (
node.IsPrivateBroadcastConn() &&
1748bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1751 return !(GetDesirableServiceFlags(services) & (~services));
1765PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1768 auto it = m_peer_map.find(
id);
1769 return it != m_peer_map.end() ? it->second :
nullptr;
1772PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1776 auto it = m_peer_map.find(
id);
1777 if (it != m_peer_map.end()) {
1778 ret = std::move(it->second);
1779 m_peer_map.erase(it);
1788 const CNodeState* state =
State(nodeid);
1789 if (state ==
nullptr)
1791 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1792 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1793 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1799 PeerRef peer = GetPeerRef(nodeid);
1800 if (peer ==
nullptr)
return false;
1809 auto ping_wait{0us};
1810 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1811 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1814 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1817 LOCK(tx_relay->m_tx_inventory_mutex);
1819 stats.
m_inv_to_send = tx_relay->m_tx_inventory_to_send.size();
1831 LOCK(peer->m_headers_sync_mutex);
1832 if (peer->m_headers_sync) {
1841std::vector<node::TxOrphanage::OrphanInfo> PeerManagerImpl::GetOrphanTransactions()
1843 LOCK(m_tx_download_mutex);
1844 return m_txdownloadman.GetOrphanTransactions();
1851 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1855void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1857 if (m_opts.max_extra_txs <= 0)
1859 if (!vExtraTxnForCompact.size())
1860 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1861 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1862 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1865void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1867 LOCK(peer.m_misbehavior_mutex);
1869 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1870 peer.m_should_discourage =
true;
1879 bool via_compact_block,
const std::string& message)
1881 PeerRef peer{GetPeerRef(nodeid)};
1892 if (!via_compact_block) {
1893 if (peer) Misbehaving(*peer, message);
1901 if (peer && !via_compact_block && !peer->m_is_inbound) {
1902 if (peer) Misbehaving(*peer, message);
1909 if (peer) Misbehaving(*peer, message);
1913 if (peer) Misbehaving(*peer, message);
1918 if (message !=
"") {
1923bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1937 PeerRef peer = GetPeerRef(peer_id);
1946 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1949 if (!BlockRequested(peer_id, block_index))
return util::Unexpected{
"Already requested from this peer"};
1972 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1978 : m_rng{opts.deterministic_rng},
1980 m_chainparams(chainman.GetParams()),
1984 m_chainman(chainman),
1986 m_txdownloadman(
node::TxDownloadOptions{pool, m_rng, opts.deterministic_rng}),
1987 m_warnings{warnings},
1992 if (opts.reconcile_txs) {
1997void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
2008 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2010 if (m_opts.private_broadcast) {
2011 scheduler.
scheduleFromNow([&] { ReattemptPrivateBroadcast(scheduler); }, 0min);
2015void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
2023 LOCK(m_tx_download_mutex);
2027 m_txdownloadman.ActiveTipChange();
2037void PeerManagerImpl::BlockConnected(
2039 const std::shared_ptr<const CBlock>& pblock,
2044 m_last_tip_update = GetTime<std::chrono::seconds>();
2047 auto stalling_timeout = m_block_stalling_timeout.load();
2051 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2061 LOCK(m_tx_download_mutex);
2062 m_txdownloadman.BlockConnected(pblock);
2065void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2067 LOCK(m_tx_download_mutex);
2068 m_txdownloadman.BlockDisconnected();
2075void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2077 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock,
FastRandomContext().rand64());
2081 if (pindex->
nHeight <= m_highest_fast_announce)
2083 m_highest_fast_announce = pindex->
nHeight;
2087 uint256 hashBlock(pblock->GetHash());
2088 const std::shared_future<CSerializedNetMsg> lazy_ser{
2092 auto most_recent_block_txs = std::make_unique<std::map<GenTxid, CTransactionRef>>();
2093 for (
const auto& tx : pblock->vtx) {
2094 most_recent_block_txs->emplace(tx->GetHash(), tx);
2095 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2098 LOCK(m_most_recent_block_mutex);
2099 m_most_recent_block_hash = hashBlock;
2100 m_most_recent_block = pblock;
2101 m_most_recent_compact_block = pcmpctblock;
2102 m_most_recent_block_txs = std::move(most_recent_block_txs);
2110 ProcessBlockAvailability(pnode->
GetId());
2114 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2116 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2117 hashBlock.ToString(), pnode->
GetId());
2120 PushMessage(*pnode, ser_cmpctblock.Copy());
2121 state.pindexBestHeaderSent = pindex;
2130void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2132 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2135 if (fInitialDownload)
return;
2138 std::vector<uint256> vHashes;
2140 while (pindexToAnnounce != pindexFork) {
2142 pindexToAnnounce = pindexToAnnounce->
pprev;
2152 for (
auto& it : m_peer_map) {
2153 Peer& peer = *it.second;
2154 LOCK(peer.m_block_inv_mutex);
2155 for (
const uint256& hash : vHashes | std::views::reverse) {
2156 peer.m_blocks_for_headers_relay.push_back(hash);
2168void PeerManagerImpl::BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
2172 const uint256 hash(block->GetHash());
2173 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2178 it != mapBlockSource.end() &&
2179 State(it->second.first)) {
2180 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2190 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2191 if (it != mapBlockSource.end()) {
2192 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2195 if (it != mapBlockSource.end())
2196 mapBlockSource.erase(it);
2204bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2209void PeerManagerImpl::SendPings()
2212 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2215void PeerManagerImpl::InitiateTxBroadcastToAll(
const Txid& txid,
const Wtxid& wtxid)
2218 for(
auto& it : m_peer_map) {
2219 Peer& peer = *it.second;
2220 auto tx_relay = peer.GetTxRelay();
2221 if (!tx_relay)
continue;
2223 LOCK(tx_relay->m_tx_inventory_mutex);
2229 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2232 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2233 tx_relay->m_tx_inventory_to_send.insert(wtxid);
2238void PeerManagerImpl::InitiateTxBroadcastPrivate(
const CTransactionRef& tx)
2240 const auto txstr{
strprintf(
"txid=%s, wtxid=%s", tx->GetHash().ToString(), tx->GetWitnessHash().ToString())};
2241 if (m_tx_for_private_broadcast.
Add(tx)) {
2249void PeerManagerImpl::RelayAddress(
NodeId originator,
2265 const auto current_time{GetTime<std::chrono::seconds>()};
2273 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2275 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2276 assert(nRelayNodes <= best.size());
2280 for (
auto& [
id, peer] : m_peer_map) {
2281 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2283 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2284 if (hashKey > best[i].first) {
2285 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2286 best[i] = std::make_pair(hashKey, peer.get());
2293 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2294 PushAddress(*best[i].second, addr);
2298void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2300 std::shared_ptr<const CBlock> a_recent_block;
2301 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2303 LOCK(m_most_recent_block_mutex);
2304 a_recent_block = m_most_recent_block;
2305 a_recent_compact_block = m_most_recent_compact_block;
2308 bool need_activate_chain =
false;
2320 need_activate_chain =
true;
2324 if (need_activate_chain) {
2326 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2333 bool can_direct_fetch{
false};
2341 if (!BlockRequestAllowed(pindex)) {
2342 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2369 can_direct_fetch = CanDirectFetch();
2373 std::shared_ptr<const CBlock> pblock;
2374 if (a_recent_block && a_recent_block->GetHash() == inv.
hash) {
2375 pblock = a_recent_block;
2393 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2403 pblock = pblockRead;
2411 bool sendMerkleBlock =
false;
2413 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2414 LOCK(tx_relay->m_bloom_filter_mutex);
2415 if (tx_relay->m_bloom_filter) {
2416 sendMerkleBlock =
true;
2417 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2420 if (sendMerkleBlock) {
2428 for (
const auto& [tx_idx,
_] : merkleBlock.
vMatchedTxn)
2439 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == inv.
hash) {
2452 LOCK(peer.m_block_inv_mutex);
2454 if (inv.
hash == peer.m_continuation_block) {
2458 std::vector<CInv> vInv;
2459 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2461 peer.m_continuation_block.SetNull();
2469 auto txinfo{std::visit(
2470 [&](
const auto&
id) {
2471 return m_mempool.
info_for_relay(
id,
WITH_LOCK(tx_relay.m_tx_inventory_mutex,
return tx_relay.m_last_inv_sequence));
2475 return std::move(txinfo.tx);
2480 LOCK(m_most_recent_block_mutex);
2481 if (m_most_recent_block_txs !=
nullptr) {
2482 auto it = m_most_recent_block_txs->find(gtxid);
2483 if (it != m_most_recent_block_txs->end())
return it->second;
2490void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2494 auto tx_relay = peer.GetTxRelay();
2496 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2497 std::vector<CInv> vNotFound;
2502 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2503 if (interruptMsgProc)
return;
2508 const CInv &inv = *it++;
2510 if (tx_relay ==
nullptr) {
2516 if (
auto tx{FindTxForGetData(*tx_relay,
ToGenTxid(inv))}) {
2519 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2522 vNotFound.push_back(inv);
2528 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2529 const CInv &inv = *it++;
2531 ProcessGetBlockData(pfrom, peer, inv);
2540 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2542 if (!vNotFound.empty()) {
2561uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2563 uint32_t nFetchFlags = 0;
2564 if (CanServeWitnesses(peer)) {
2573 unsigned int tx_requested_size = 0;
2574 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2576 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2580 tx_requested_size += resp.txn[i]->GetTotalSize();
2587bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers, Peer& peer)
2591 Misbehaving(peer,
"header with invalid proof of work");
2596 if (!CheckHeadersAreContinuous(headers)) {
2597 Misbehaving(peer,
"non-continuous headers sequence");
2622void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2623 const std::vector<CBlockHeader>& headers)
2627 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2628 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2630 headers[0].hashPrevBlock.ToString(),
2631 best_header->nHeight,
2641bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2645 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2648 hashLastBlock = header.GetHash();
2653bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2655 if (peer.m_headers_sync) {
2656 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2658 if (result.success) peer.m_last_getheaders_timestamp = {};
2659 if (result.request_more) {
2660 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2662 Assume(!locator.vHave.empty());
2665 if (!locator.vHave.empty()) {
2668 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2671 locator.vHave.front().ToString(), pfrom.
GetId());
2676 peer.m_headers_sync.reset(
nullptr);
2681 LOCK(m_headers_presync_mutex);
2682 m_headers_presync_stats.erase(pfrom.
GetId());
2685 HeadersPresyncStats stats;
2686 stats.first = peer.m_headers_sync->GetPresyncWork();
2688 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2689 peer.m_headers_sync->GetPresyncTime()};
2693 LOCK(m_headers_presync_mutex);
2694 m_headers_presync_stats[pfrom.
GetId()] = stats;
2695 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2696 bool best_updated =
false;
2697 if (best_it == m_headers_presync_stats.end()) {
2701 const HeadersPresyncStats* stat_best{
nullptr};
2702 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2703 if (!stat_best || stat > *stat_best) {
2708 m_headers_presync_bestpeer = peer_best;
2709 best_updated = (peer_best == pfrom.
GetId());
2710 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2712 m_headers_presync_bestpeer = pfrom.
GetId();
2713 best_updated =
true;
2715 if (best_updated && stats.second.has_value()) {
2717 m_headers_presync_should_signal =
true;
2721 if (result.success) {
2724 headers.swap(result.pow_validated_headers);
2727 return result.success;
2735bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex& chain_start_header, std::vector<CBlockHeader>& headers)
2742 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2746 if (total_work < minimum_chain_work) {
2750 if (headers.size() == m_opts.max_headers_result) {
2760 LOCK(peer.m_headers_sync_mutex);
2762 m_chainparams.
HeadersSync(), chain_start_header, minimum_chain_work));
2767 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2781bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2783 if (header ==
nullptr) {
2785 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2793bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2801 peer.m_last_getheaders_timestamp = current_time;
2812void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2815 CNodeState *nodestate =
State(pfrom.
GetId());
2818 std::vector<const CBlockIndex*> vToFetch;
2826 vToFetch.push_back(pindexWalk);
2828 pindexWalk = pindexWalk->
pprev;
2839 std::vector<CInv> vGetData;
2841 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2846 uint32_t nFetchFlags = GetFetchFlags(peer);
2848 BlockRequested(pfrom.
GetId(), *pindex);
2852 if (vGetData.size() > 1) {
2857 if (vGetData.size() > 0) {
2858 if (!m_opts.ignore_incoming_txs &&
2859 nodestate->m_provides_cmpctblocks &&
2860 vGetData.size() == 1 &&
2861 mapBlocksInFlight.size() == 1 &&
2877void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2878 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2881 CNodeState *nodestate =
State(pfrom.
GetId());
2890 nodestate->m_last_block_announcement =
GetTime();
2898 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2920 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) {
2922 nodestate->m_chain_sync.m_protect =
true;
2923 ++m_outbound_peers_with_protect_from_disconnect;
2928void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2929 std::vector<CBlockHeader>&& headers,
2930 bool via_compact_block)
2932 size_t nCount = headers.size();
2939 LOCK(peer.m_headers_sync_mutex);
2940 if (peer.m_headers_sync) {
2941 peer.m_headers_sync.reset(
nullptr);
2942 LOCK(m_headers_presync_mutex);
2943 m_headers_presync_stats.erase(pfrom.
GetId());
2947 peer.m_last_getheaders_timestamp = {};
2955 if (!CheckHeadersPoW(headers, peer)) {
2970 bool already_validated_work =
false;
2973 bool have_headers_sync =
false;
2975 LOCK(peer.m_headers_sync_mutex);
2977 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2989 if (headers.empty()) {
2993 have_headers_sync = !!peer.m_headers_sync;
2998 bool headers_connect_blockindex{chain_start_header !=
nullptr};
3000 if (!headers_connect_blockindex) {
3004 HandleUnconnectingHeaders(pfrom, peer, headers);
3011 peer.m_last_getheaders_timestamp = {};
3021 already_validated_work = already_validated_work || IsAncestorOfBestHeaderOrTip(last_received_header);
3028 already_validated_work =
true;
3034 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3035 *chain_start_header, headers)) {
3047 bool received_new_header{last_received_header ==
nullptr};
3053 state, &pindexLast)};
3059 "If this happens with all peers, consider database corruption (that -reindex may fix) "
3060 "or a potential consensus incompatibility.",
3063 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3069 if (processed && received_new_header) {
3070 LogBlockHeader(*pindexLast, pfrom,
false);
3074 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
3076 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3078 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
3082 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
3085 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3091 bool first_time_failure)
3097 PeerRef peer{GetPeerRef(nodeid)};
3100 ptx->GetHash().ToString(),
3101 ptx->GetWitnessHash().ToString(),
3105 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
3108 AddToCompactExtraTransactions(ptx);
3110 for (
const Txid& parent_txid : unique_parents) {
3111 if (peer) AddKnownTx(*peer, parent_txid.ToUint256());
3114 return package_to_validate;
3117void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3123 m_txdownloadman.MempoolAcceptedTx(tx);
3127 tx->GetHash().ToString(),
3128 tx->GetWitnessHash().ToString(),
3131 InitiateTxBroadcastToAll(tx->GetHash(), tx->GetWitnessHash());
3134 AddToCompactExtraTransactions(removedTx);
3144 const auto&
package = package_to_validate.m_txns;
3145 const auto& senders = package_to_validate.
m_senders;
3148 m_txdownloadman.MempoolRejectedPackage(package);
3151 if (!
Assume(package.size() == 2))
return;
3155 auto package_iter = package.rbegin();
3156 auto senders_iter = senders.rbegin();
3157 while (package_iter != package.rend()) {
3158 const auto& tx = *package_iter;
3159 const NodeId nodeid = *senders_iter;
3160 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3164 const auto& tx_result = it_result->second;
3165 switch (tx_result.m_result_type) {
3168 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3178 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3196bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3203 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3206 const Txid& orphanHash = porphanTx->GetHash();
3207 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3224 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3233bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3235 const uint256& stop_hash, uint32_t max_height_diff,
3239 const bool supported_filter_type =
3242 if (!supported_filter_type) {
3244 static_cast<uint8_t
>(filter_type),
node.DisconnectMsg(
fLogIPs));
3245 node.fDisconnect =
true;
3254 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3257 node.fDisconnect =
true;
3262 uint32_t stop_height = stop_index->
nHeight;
3263 if (start_height > stop_height) {
3265 "start height %d and stop height %d, %s\n",
3266 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3267 node.fDisconnect =
true;
3270 if (stop_height - start_height >= max_height_diff) {
3272 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3273 node.fDisconnect =
true;
3278 if (!filter_index) {
3288 uint8_t filter_type_ser;
3289 uint32_t start_height;
3292 vRecv >> filter_type_ser >> start_height >> stop_hash;
3298 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3303 std::vector<BlockFilter> filters;
3305 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3310 for (
const auto& filter : filters) {
3317 uint8_t filter_type_ser;
3318 uint32_t start_height;
3321 vRecv >> filter_type_ser >> start_height >> stop_hash;
3327 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3333 if (start_height > 0) {
3335 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3337 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3343 std::vector<uint256> filter_hashes;
3345 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3359 uint8_t filter_type_ser;
3362 vRecv >> filter_type_ser >> stop_hash;
3368 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3369 std::numeric_limits<uint32_t>::max(),
3370 stop_index, filter_index)) {
3378 for (
int i = headers.size() - 1; i >= 0; i--) {
3383 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3397 bool new_block{
false};
3398 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3400 node.m_last_block_time = GetTime<std::chrono::seconds>();
3405 RemoveBlockRequest(block->GetHash(), std::nullopt);
3408 mapBlockSource.erase(block->GetHash());
3412void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3414 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3415 bool fBlockRead{
false};
3419 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3420 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3421 bool requested_block_from_this_peer{
false};
3424 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3426 while (range_flight.first != range_flight.second) {
3427 auto [node_id, block_it] = range_flight.first->second;
3428 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3429 requested_block_from_this_peer =
true;
3432 range_flight.first++;
3435 if (!requested_block_from_this_peer) {
3447 Misbehaving(peer,
"previous compact block reconstruction attempt failed");
3458 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3461 if (first_in_flight) {
3466 std::vector<CInv> invs;
3471 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3484 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3499void PeerManagerImpl::LogBlockHeader(
const CBlockIndex& index,
const CNode& peer,
bool via_compact_block) {
3511 "Saw new %sheader hash=%s height=%d peer=%d%s",
3512 via_compact_block ?
"cmpctblock " :
"",
3525void PeerManagerImpl::PushPrivateBroadcastTx(
CNode&
node)
3532 node.fDisconnect =
true;
3537 LogInfo(
"[privatebroadcast] P2P handshake completed, sending INV for txid=%s%s, peer=%d%s",
3538 tx->GetHash().ToString(), tx->HasWitness() ?
strprintf(
", wtxid=%s", tx->GetWitnessHash().ToString()) :
"",
3544void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3545 const std::chrono::microseconds time_received,
3546 const std::atomic<bool>& interruptMsgProc)
3552 PeerRef peer = GetPeerRef(pfrom.
GetId());
3553 if (peer ==
nullptr)
return;
3563 uint64_t nNonce = 1;
3566 std::string cleanSubVer;
3567 int starting_height = -1;
3570 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3585 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3587 GetDesirableServiceFlags(nServices),
3600 if (!vRecv.
empty()) {
3608 if (!vRecv.
empty()) {
3609 std::string strSubVer;
3613 if (!vRecv.
empty()) {
3614 vRecv >> starting_height;
3634 PushNodeVersion(pfrom, *peer);
3643 peer->m_their_services = nServices;
3647 pfrom.cleanSubVer = cleanSubVer;
3649 peer->m_starting_height = starting_height;
3659 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3660 auto*
const tx_relay = peer->SetTxRelay();
3662 LOCK(tx_relay->m_bloom_filter_mutex);
3663 tx_relay->m_relay_txs = fRelay;
3669 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3678 LogInfo(
"[privatebroadcast] Disconnecting: does not support transactions relay (connected in vain), peer=%d%s",
3690 if (greatest_common_version >= 70016) {
3705 const auto* tx_relay = peer->GetTxRelay();
3706 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3708 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3721 m_num_preferred_download_peers += state->fPreferredDownload;
3727 bool send_getaddr{
false};
3729 send_getaddr = SetupAddressRelay(pfrom, *peer);
3739 peer->m_getaddr_sent =
true;
3763 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3767 m_outbound_time_offsets.Add(peer->m_time_offset);
3768 m_outbound_time_offsets.WarnIfOutOfSync();
3772 if (greatest_common_version <= 70012) {
3773 constexpr auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3774 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3797 auto new_peer_msg = [&]() {
3799 return strprintf(
"New %s peer connected: transport: %s, version: %d, blocks=%d peer=%d%s%s\n",
3802 pfrom.
nVersion.load(), peer->m_starting_height,
3804 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3812 LogInfo(
"%s", new_peer_msg());
3815 if (
auto tx_relay = peer->GetTxRelay()) {
3824 tx_relay->m_tx_inventory_mutex,
3825 return tx_relay->m_tx_inventory_to_send.empty() &&
3826 tx_relay->m_next_inv_send_time == 0
s));
3836 PushPrivateBroadcastTx(pfrom);
3849 if (m_txreconciliation) {
3850 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3854 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3860 const CNodeState* state =
State(pfrom.
GetId());
3862 .m_preferred = state->fPreferredDownload,
3863 .m_relay_permissions = pfrom.HasPermission(NetPermissionFlags::Relay),
3864 .m_wtxid_relay = peer->m_wtxid_relay,
3873 peer->m_prefers_headers =
true;
3878 bool sendcmpct_hb{
false};
3879 uint64_t sendcmpct_version{0};
3880 vRecv >> sendcmpct_hb >> sendcmpct_version;
3886 CNodeState* nodestate =
State(pfrom.
GetId());
3887 nodestate->m_provides_cmpctblocks =
true;
3888 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3905 if (!peer->m_wtxid_relay) {
3906 peer->m_wtxid_relay =
true;
3907 m_wtxid_relay_peers++;
3926 peer->m_wants_addrv2 =
true;
3934 if (!m_txreconciliation) {
3935 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3946 if (RejectIncomingTxs(pfrom)) {
3955 const auto* tx_relay = peer->GetTxRelay();
3956 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3962 uint32_t peer_txreconcl_version;
3963 uint64_t remote_salt;
3964 vRecv >> peer_txreconcl_version >> remote_salt;
3967 peer_txreconcl_version, remote_salt);
3999 const auto ser_params{
4007 std::vector<CAddress> vAddr;
4009 vRecv >> ser_params(vAddr);
4011 if (!SetupAddressRelay(pfrom, *peer)) {
4018 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
4023 std::vector<CAddress> vAddrOk;
4024 const auto current_a_time{Now<NodeSeconds>()};
4027 const auto current_time{GetTime<std::chrono::microseconds>()};
4030 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
4034 peer->m_addr_token_timestamp = current_time;
4037 uint64_t num_proc = 0;
4038 uint64_t num_rate_limit = 0;
4039 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
4042 if (interruptMsgProc)
4046 if (peer->m_addr_token_bucket < 1.0) {
4052 peer->m_addr_token_bucket -= 1.0;
4061 addr.
nTime = current_a_time - 5 * 24h;
4063 AddAddressKnown(*peer, addr);
4070 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
4072 RelayAddress(pfrom.
GetId(), addr, reachable);
4076 vAddrOk.push_back(addr);
4079 peer->m_addr_processed += num_proc;
4080 peer->m_addr_rate_limited += num_rate_limit;
4081 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
4082 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
4084 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
4085 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
4096 std::vector<CInv> vInv;
4100 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
4104 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
4108 const auto current_time{GetTime<std::chrono::microseconds>()};
4111 for (
CInv& inv : vInv) {
4112 if (interruptMsgProc)
return;
4117 if (peer->m_wtxid_relay) {
4124 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
4127 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4135 best_block = &inv.
hash;
4138 if (reject_tx_invs) {
4144 AddKnownTx(*peer, inv.
hash);
4147 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
4155 if (best_block !=
nullptr) {
4167 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4168 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
4170 m_chainman.m_best_header->nHeight, best_block->ToString(),
4173 if (!state.fSyncStarted) {
4174 peer->m_inv_triggered_getheaders_before_sync =
true;
4178 m_last_block_inv_triggering_headers_sync = *best_block;
4187 std::vector<CInv> vInv;
4191 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
4197 if (vInv.size() > 0) {
4202 const auto pushed_tx_opt{m_tx_for_private_broadcast.
GetTxForNode(pfrom.
GetId())};
4203 if (!pushed_tx_opt) {
4204 LogInfo(
"[privatebroadcast] Disconnecting: got GETDATA without sending an INV, peer=%d%s",
4214 if (vInv.size() == 1 && vInv[0].IsMsgTx() && vInv[0].hash == pushed_tx->GetHash().ToUint256()) {
4218 peer->m_ping_queued =
true;
4219 MaybeSendPing(pfrom, *peer, GetTime<std::chrono::microseconds>());
4221 LogInfo(
"[privatebroadcast] Disconnecting: got an unexpected GETDATA message, peer=%d%s",
4229 LOCK(peer->m_getdata_requests_mutex);
4230 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
4231 ProcessGetData(pfrom, *peer, interruptMsgProc);
4240 vRecv >> locator >> hashStop;
4256 std::shared_ptr<const CBlock> a_recent_block;
4258 LOCK(m_most_recent_block_mutex);
4259 a_recent_block = m_most_recent_block;
4262 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4277 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4292 if (--nLimit <= 0) {
4296 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4308 for (
size_t i = 1; i < req.
indexes.size(); ++i) {
4312 std::shared_ptr<const CBlock> recent_block;
4314 LOCK(m_most_recent_block_mutex);
4315 if (m_most_recent_block_hash == req.
blockhash)
4316 recent_block = m_most_recent_block;
4320 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4339 if (!block_pos.IsNull()) {
4346 SendBlockTransactions(pfrom, *peer, block, req);
4359 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4367 vRecv >> locator >> hashStop;
4385 if (m_chainman.
ActiveTip() ==
nullptr ||
4387 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4394 CNodeState *nodestate =
State(pfrom.
GetId());
4404 if (!BlockRequestAllowed(pindex)) {
4405 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4418 std::vector<CBlock> vHeaders;
4419 int nLimit = m_opts.max_headers_result;
4421 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4424 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4439 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4445 if (RejectIncomingTxs(pfrom)) {
4459 const Txid& txid = ptx->GetHash();
4460 const Wtxid& wtxid = ptx->GetWitnessHash();
4463 AddKnownTx(*peer, hash);
4465 if (
const auto num_broadcasted{m_tx_for_private_broadcast.
Remove(ptx)}) {
4466 LogInfo(
"[privatebroadcast] Received our privately broadcast transaction (txid=%s) from the "
4467 "network from peer=%d%s; stopping private broadcast attempts",
4478 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4479 if (!should_validate) {
4484 if (!m_mempool.
exists(txid)) {
4485 LogInfo(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4488 LogInfo(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4490 InitiateTxBroadcastToAll(txid, wtxid);
4494 if (package_to_validate) {
4497 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4498 ProcessPackageResult(package_to_validate.value(), package_result);
4504 Assume(!package_to_validate.has_value());
4514 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4517 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4518 ProcessPackageResult(package_to_validate.value(), package_result);
4534 vRecv >> cmpctblock;
4536 bool received_new_header =
false;
4546 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4556 received_new_header =
true;
4564 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4571 if (received_new_header) {
4572 LogBlockHeader(*pindex, pfrom,
true);
4575 bool fProcessBLOCKTXN =
false;
4579 bool fRevertToHeaderProcessing =
false;
4583 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4584 bool fBlockReconstructed =
false;
4590 CNodeState *nodestate =
State(pfrom.
GetId());
4595 nodestate->m_last_block_announcement =
GetTime();
4601 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4602 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4603 bool requested_block_from_this_peer{
false};
4606 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4608 while (range_flight.first != range_flight.second) {
4609 if (range_flight.first->second.first == pfrom.
GetId()) {
4610 requested_block_from_this_peer =
true;
4613 range_flight.first++;
4618 if (requested_block_from_this_peer) {
4621 std::vector<CInv> vInv(1);
4622 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4629 if (!already_in_flight && !CanDirectFetch()) {
4637 requested_block_from_this_peer) {
4638 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4639 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4640 if (!(*queuedBlockIt)->partialBlock)
4653 Misbehaving(*peer,
"invalid compact block");
4656 if (first_in_flight) {
4658 std::vector<CInv> vInv(1);
4659 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4669 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4674 fProcessBLOCKTXN =
true;
4675 }
else if (first_in_flight) {
4682 IsBlockRequestedFromOutbound(blockhash) ||
4701 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4706 std::vector<CTransactionRef> dummy;
4708 status = tempBlock.FillBlock(*pblock, dummy,
4711 fBlockReconstructed =
true;
4715 if (requested_block_from_this_peer) {
4718 std::vector<CInv> vInv(1);
4719 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4724 fRevertToHeaderProcessing =
true;
4729 if (fProcessBLOCKTXN) {
4732 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4735 if (fRevertToHeaderProcessing) {
4741 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4744 if (fBlockReconstructed) {
4749 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4767 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4784 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4795 std::vector<CBlockHeader> headers;
4799 if (nCount > m_opts.max_headers_result) {
4800 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4803 headers.resize(nCount);
4804 for (
unsigned int n = 0; n < nCount; n++) {
4805 vRecv >> headers[n];
4809 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4813 if (m_headers_presync_should_signal.exchange(
false)) {
4814 HeadersPresyncStats stats;
4816 LOCK(m_headers_presync_mutex);
4817 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4818 if (it != m_headers_presync_stats.end()) stats = it->second;
4836 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4847 Misbehaving(*peer,
"mutated block");
4852 bool forceProcessing =
false;
4853 const uint256 hash(pblock->GetHash());
4854 bool min_pow_checked =
false;
4859 forceProcessing = IsBlockRequested(hash);
4860 RemoveBlockRequest(hash, pfrom.
GetId());
4864 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4868 min_pow_checked =
true;
4871 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4888 Assume(SetupAddressRelay(pfrom, *peer));
4892 if (peer->m_getaddr_recvd) {
4896 peer->m_getaddr_recvd =
true;
4898 peer->m_addrs_to_send.clear();
4899 std::vector<CAddress> vAddr;
4905 for (
const CAddress &addr : vAddr) {
4906 PushAddress(*peer, addr);
4934 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4935 LOCK(tx_relay->m_tx_inventory_mutex);
4936 tx_relay->m_send_mempool =
true;
4962 const auto ping_end = time_received;
4965 bool bPingFinished =
false;
4966 std::string sProblem;
4968 if (nAvail >=
sizeof(
nonce)) {
4972 if (peer->m_ping_nonce_sent != 0) {
4973 if (
nonce == peer->m_ping_nonce_sent) {
4975 bPingFinished =
true;
4976 const auto ping_time = ping_end - peer->m_ping_start.load();
4977 if (ping_time.count() >= 0) {
4982 LogInfo(
"[privatebroadcast] Got a PONG (the transaction will probably reach the network), marking for disconnect, peer=%d%s",
4988 sProblem =
"Timing mishap";
4992 sProblem =
"Nonce mismatch";
4995 bPingFinished =
true;
4996 sProblem =
"Nonce zero";
5000 sProblem =
"Unsolicited pong without ping";
5004 bPingFinished =
true;
5005 sProblem =
"Short payload";
5008 if (!(sProblem.empty())) {
5012 peer->m_ping_nonce_sent,
5016 if (bPingFinished) {
5017 peer->m_ping_nonce_sent = 0;
5034 Misbehaving(*peer,
"too-large bloom filter");
5035 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5037 LOCK(tx_relay->m_bloom_filter_mutex);
5038 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
5039 tx_relay->m_relay_txs =
true;
5053 std::vector<unsigned char> vData;
5061 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5062 LOCK(tx_relay->m_bloom_filter_mutex);
5063 if (tx_relay->m_bloom_filter) {
5064 tx_relay->m_bloom_filter->insert(vData);
5070 Misbehaving(*peer,
"bad filteradd message");
5081 auto tx_relay = peer->GetTxRelay();
5082 if (!tx_relay)
return;
5085 LOCK(tx_relay->m_bloom_filter_mutex);
5086 tx_relay->m_bloom_filter =
nullptr;
5087 tx_relay->m_relay_txs =
true;
5096 vRecv >> newFeeFilter;
5098 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5099 tx_relay->m_fee_filter_received = newFeeFilter;
5107 ProcessGetCFilters(pfrom, *peer, vRecv);
5112 ProcessGetCFHeaders(pfrom, *peer, vRecv);
5117 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
5122 std::vector<CInv> vInv;
5124 std::vector<GenTxid> tx_invs;
5126 for (
CInv &inv : vInv) {
5132 LOCK(m_tx_download_mutex);
5133 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
5142bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5145 LOCK(peer.m_misbehavior_mutex);
5148 if (!peer.m_should_discourage)
return false;
5150 peer.m_should_discourage =
false;
5155 LogWarning(
"Not punishing noban peer %d!", peer.m_id);
5161 LogWarning(
"Not punishing manually connected peer %d!", peer.m_id);
5181bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
5186 PeerRef peer = GetPeerRef(pfrom->
GetId());
5187 if (peer ==
nullptr)
return false;
5191 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
5194 LOCK(peer->m_getdata_requests_mutex);
5195 if (!peer->m_getdata_requests.empty()) {
5196 ProcessGetData(*pfrom, *peer, interruptMsgProc);
5200 const bool processed_orphan = ProcessOrphanTx(*peer);
5205 if (processed_orphan)
return true;
5210 LOCK(peer->m_getdata_requests_mutex);
5211 if (!peer->m_getdata_requests.empty())
return true;
5224 bool fMoreWork = poll_result->second;
5235 if (m_opts.capture_messages) {
5240 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5241 if (interruptMsgProc)
return false;
5243 LOCK(peer->m_getdata_requests_mutex);
5244 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5251 LOCK(m_tx_download_mutex);
5252 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
5253 }
catch (
const std::exception& e) {
5262void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5275 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5277 if (state.m_chain_sync.m_timeout != 0
s) {
5278 state.m_chain_sync.m_timeout = 0
s;
5279 state.m_chain_sync.m_work_header =
nullptr;
5280 state.m_chain_sync.m_sent_getheaders =
false;
5282 }
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)) {
5290 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5291 state.m_chain_sync.m_sent_getheaders =
false;
5292 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5296 if (state.m_chain_sync.m_sent_getheaders) {
5298 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5301 assert(state.m_chain_sync.m_work_header);
5306 MaybeSendGetHeaders(pto,
5307 GetLocator(state.m_chain_sync.m_work_header->pprev),
5309 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());
5310 state.m_chain_sync.m_sent_getheaders =
true;
5322void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5331 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5335 if (pnode->
GetId() > youngest_peer.first) {
5336 next_youngest_peer = youngest_peer;
5337 youngest_peer.first = pnode->GetId();
5338 youngest_peer.second = pnode->m_last_block_time;
5341 NodeId to_disconnect = youngest_peer.first;
5342 if (youngest_peer.second > next_youngest_peer.second) {
5345 to_disconnect = next_youngest_peer.first;
5354 CNodeState *node_state =
State(pnode->
GetId());
5355 if (node_state ==
nullptr ||
5358 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5362 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5378 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5381 AssertLockHeld(::cs_main);
5385 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5386 CNodeState *state = State(pnode->GetId());
5387 if (state == nullptr) return;
5389 if (state->m_chain_sync.m_protect) return;
5392 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5393 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5394 worst_peer = pnode->GetId();
5395 oldest_block_announcement = state->m_last_block_announcement;
5398 if (worst_peer != -1) {
5409 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5413 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5430void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5434 auto now{GetTime<std::chrono::seconds>()};
5436 EvictExtraOutboundPeers(now);
5438 if (now > m_stale_tip_check_time) {
5442 LogInfo(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5451 if (!m_initial_sync_finished && CanDirectFetch()) {
5453 m_initial_sync_finished =
true;
5457void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5460 peer.m_ping_nonce_sent &&
5470 bool pingSend =
false;
5472 if (peer.m_ping_queued) {
5477 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5486 }
while (
nonce == 0);
5487 peer.m_ping_queued =
false;
5488 peer.m_ping_start = now;
5490 peer.m_ping_nonce_sent =
nonce;
5494 peer.m_ping_nonce_sent = 0;
5500void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5503 if (!peer.m_addr_relay_enabled)
return;
5505 LOCK(peer.m_addr_send_times_mutex);
5508 peer.m_next_local_addr_send < current_time) {
5515 if (peer.m_next_local_addr_send != 0us) {
5516 peer.m_addr_known->reset();
5519 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5520 if (peer.m_next_local_addr_send == 0us) {
5524 std::vector<CAddress> self_announcement {local_addr};
5525 if (peer.m_wants_addrv2) {
5532 PushAddress(peer, local_addr);
5539 if (current_time <= peer.m_next_addr_send)
return;
5552 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5553 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5556 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5557 peer.m_addrs_to_send.end());
5560 if (peer.m_addrs_to_send.empty())
return;
5562 if (peer.m_wants_addrv2) {
5567 peer.m_addrs_to_send.clear();
5570 if (peer.m_addrs_to_send.capacity() > 40) {
5571 peer.m_addrs_to_send.shrink_to_fit();
5575void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5583 CNodeState &state = *
State(
node.GetId());
5584 if (state.pindexBestKnownBlock !=
nullptr &&
5591 peer.m_sent_sendheaders =
true;
5596void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5598 if (m_opts.ignore_incoming_txs)
return;
5614 if (peer.m_fee_filter_sent == MAX_FILTER) {
5617 peer.m_next_send_feefilter = 0us;
5620 if (current_time > peer.m_next_send_feefilter) {
5621 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5624 if (filterToSend != peer.m_fee_filter_sent) {
5626 peer.m_fee_filter_sent = filterToSend;
5633 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5639class CompareInvMempoolOrder
5643 explicit CompareInvMempoolOrder(
CTxMemPool* mempool) : m_mempool{mempool} {}
5645 bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
5654bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5664bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5669 if (
node.IsBlockOnlyConn())
return false;
5671 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5675 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5681bool PeerManagerImpl::SendMessages(
CNode* pto)
5686 PeerRef peer = GetPeerRef(pto->
GetId());
5687 if (!peer)
return false;
5692 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5695 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5696 PushNodeVersion(*pto, *peer);
5697 peer->m_outbound_version_message_sent =
true;
5704 const auto current_time{GetTime<std::chrono::microseconds>()};
5711 LogInfo(
"[privatebroadcast] Disconnecting: did not complete the transaction send within %d seconds, peer=%d%s",
5724 MaybeSendPing(*pto, *peer, current_time);
5729 MaybeSendAddr(*pto, *peer, current_time);
5731 MaybeSendSendHeaders(*pto, *peer);
5739 if (m_chainman.m_best_header ==
nullptr) {
5746 bool sync_blocks_and_headers_from_peer =
false;
5747 if (state.fPreferredDownload) {
5748 sync_blocks_and_headers_from_peer =
true;
5759 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5760 sync_blocks_and_headers_from_peer =
true;
5766 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5767 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5775 if (pindexStart->
pprev)
5776 pindexStart = pindexStart->
pprev;
5777 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5780 state.fSyncStarted =
true;
5804 LOCK(peer->m_block_inv_mutex);
5805 std::vector<CBlock> vHeaders;
5806 bool fRevertToInv = ((!peer->m_prefers_headers &&
5807 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5810 ProcessBlockAvailability(pto->
GetId());
5812 if (!fRevertToInv) {
5813 bool fFoundStartingHeader =
false;
5817 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5822 fRevertToInv =
true;
5825 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5837 fRevertToInv =
true;
5840 pBestIndex = pindex;
5841 if (fFoundStartingHeader) {
5844 }
else if (PeerHasHeader(&state, pindex)) {
5846 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5849 fFoundStartingHeader =
true;
5854 fRevertToInv =
true;
5859 if (!fRevertToInv && !vHeaders.empty()) {
5860 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5864 vHeaders.front().GetHash().ToString(), pto->
GetId());
5866 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5868 LOCK(m_most_recent_block_mutex);
5869 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5873 if (cached_cmpctblock_msg.has_value()) {
5874 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5882 state.pindexBestHeaderSent = pBestIndex;
5883 }
else if (peer->m_prefers_headers) {
5884 if (vHeaders.size() > 1) {
5887 vHeaders.front().GetHash().ToString(),
5888 vHeaders.back().GetHash().ToString(), pto->
GetId());
5891 vHeaders.front().GetHash().ToString(), pto->
GetId());
5894 state.pindexBestHeaderSent = pBestIndex;
5896 fRevertToInv =
true;
5902 if (!peer->m_blocks_for_headers_relay.empty()) {
5903 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5916 if (!PeerHasHeader(&state, pindex)) {
5917 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5923 peer->m_blocks_for_headers_relay.clear();
5929 std::vector<CInv> vInv;
5931 LOCK(peer->m_block_inv_mutex);
5935 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5942 peer->m_blocks_for_inv_relay.clear();
5945 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5946 LOCK(tx_relay->m_tx_inventory_mutex);
5949 if (tx_relay->m_next_inv_send_time < current_time) {
5950 fSendTrickle =
true;
5960 LOCK(tx_relay->m_bloom_filter_mutex);
5961 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5965 if (fSendTrickle && tx_relay->m_send_mempool) {
5966 auto vtxinfo = m_mempool.
infoAll();
5967 tx_relay->m_send_mempool =
false;
5968 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5970 LOCK(tx_relay->m_bloom_filter_mutex);
5972 for (
const auto& txinfo : vtxinfo) {
5973 const Txid& txid{txinfo.tx->GetHash()};
5974 const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
5975 const auto inv = peer->m_wtxid_relay ?
5978 tx_relay->m_tx_inventory_to_send.erase(wtxid);
5981 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5984 if (tx_relay->m_bloom_filter) {
5985 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5987 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5988 vInv.push_back(inv);
5999 std::vector<std::set<Wtxid>::iterator> vInvTx;
6000 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
6001 for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
6002 vInvTx.push_back(it);
6004 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
6007 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool);
6008 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6011 unsigned int nRelayedTransactions = 0;
6012 LOCK(tx_relay->m_bloom_filter_mutex);
6015 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
6017 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
6018 std::set<Wtxid>::iterator it = vInvTx.back();
6022 tx_relay->m_tx_inventory_to_send.erase(it);
6024 auto txinfo = m_mempool.
info(wtxid);
6031 const auto inv = peer->m_wtxid_relay ?
6033 CInv{
MSG_TX, txinfo.tx->GetHash().ToUint256()};
6035 if (tx_relay->m_tx_inventory_known_filter.contains(inv.
hash)) {
6039 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
6042 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
6044 vInv.push_back(inv);
6045 nRelayedTransactions++;
6050 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
6055 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
6062 auto stalling_timeout = m_block_stalling_timeout.load();
6063 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
6072 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
6082 if (state.vBlocksInFlight.size() > 0) {
6083 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
6084 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
6092 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
6094 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
6095 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
6112 state.fSyncStarted =
false;
6114 peer->m_headers_sync_timeout = 0us;
6120 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
6126 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
6131 std::vector<CInv> vGetData;
6133 std::vector<const CBlockIndex*> vToDownload;
6135 auto get_inflight_budget = [&state]() {
6142 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
6143 auto historical_blocks{m_chainman.GetHistoricalBlockRange()};
6144 if (historical_blocks && !IsLimitedPeer(*peer)) {
6148 TryDownloadingHistoricalBlocks(
6150 get_inflight_budget(),
6151 vToDownload, from_tip, historical_blocks->second);
6154 uint32_t nFetchFlags = GetFetchFlags(*peer);
6156 BlockRequested(pto->
GetId(), *pindex);
6160 if (state.vBlocksInFlight.empty() && staller != -1) {
6161 if (
State(staller)->m_stalling_since == 0us) {
6162 State(staller)->m_stalling_since = current_time;
6172 LOCK(m_tx_download_mutex);
6173 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
6182 if (!vGetData.empty())
6185 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.
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
@ BLOCK_VALID_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous.
@ BLOCK_HAVE_DATA
full block available in blk*.dat
arith_uint256 GetBlockProof(const CBlockIndex &block)
Compute how much work a block index entry corresponds to.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< CTransactionRef > txn
std::vector< uint16_t > indexes
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
static constexpr SerParams V1_NETWORK
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V2_NETWORK
size_t BlockTxCount() const
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
unsigned int nTx
Number of transactions in this block.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
An in-memory indexed chain of blocks.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const HeadersSyncParams & HeadersSync() const
const Consensus::Params & GetConsensus() const
void NumToOpenAdd(size_t n)
Increment the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
size_t NumToOpenSub(size_t n)
Decrement the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
void ForEachNode(const NodeFn &func)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::microseconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetTryNewOutboundPeer() const
class CConnman::PrivateBroadcast m_private_broadcast
std::vector< CAddress > GetAddresses(CNode &requestor, size_t max_addresses, size_t max_pct)
Return addresses from the per-requestor cache.
void SetTryNewOutboundPeer(bool flag)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
bool DisconnectNode(std::string_view node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return randomly selected addresses.
bool CheckIncomingNonce(uint64_t nonce)
bool GetUseAddrmanOutgoing() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, Txid > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
const std::string m_addr_name
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
std::atomic< bool > m_bip152_highbandwidth_from
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
const uint64_t m_network_key
Network key used to prevent fingerprinting our node across networks.
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
bool IsPrivateBroadcastConn() const
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
General SipHash-2-4 implementation.
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
bool CompareMiningScoreWithTopology(const Wtxid &hasha, const Wtxid &hashb) const
TxMempoolInfo info_for_relay(const T &id, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
CFeeRate GetMinFee(size_t sizelimit) const
CTransactionRef get(const Txid &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
TxMempoolInfo info(const T &id) const
bool exists(const Txid &txid) const
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
std::set< Txid > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
unsigned long size() const
void RemoveUnbroadcastTx(const Txid &txid, bool unchecked=false)
Removes a transaction from the unbroadcast set.
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void BlockChecked(const std::shared_ptr< const CBlock > &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void ActiveTipChange(const CBlockIndex &new_tip, bool is_ibd)
Notifies listeners any time the block chain tip changes, synchronously.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected Provides the block that was disconnected.
virtual void BlockConnected(const kernel::ChainstateRole &role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
void ClearBlockIndexCandidates() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex * FindForkInGlobalIndex(const CBlockLocator &locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Find the last common block of this chain and a locator.
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Chainstate & ActiveChainstate() const
Alternatives to CurrentChainstate() used by older code to query latest chainstate information without...
SnapshotCompletionResult MaybeValidateSnapshot(Chainstate &validated_cs, Chainstate &unvalidated_cs) EXCLUSIVE_LOCKS_REQUIRED(Chainstate & CurrentChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Try to validate an assumeutxo snapshot by using a validated historical chainstate targeted at the sna...
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool ProcessNewBlockHeaders(std::span< const CBlockHeader > headers, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const arith_uint256 & MinimumChainWork() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
void ReportHeadersPresync(int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Double ended buffer combining vector and stream-like interfaces.
void ignore(size_t num_ignore)
uint64_t rand64() noexcept
Generate a random 64-bit integer.
const uint256 & ToUint256() const LIFETIMEBOUND
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing, bool segwit_active)
bool IsTxAvailable(size_t index) const
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< Wtxid, CTransactionRef > > &extra_txn)
virtual util::Expected< void, std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
virtual std::vector< node::TxOrphanage::OrphanInfo > GetOrphanTransactions()=0
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, DataStream &vRecv, 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 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.
Store a list of transactions to be broadcast privately.
void NodeConfirmedReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Mark that the node has confirmed reception of the transaction we sent it by responding with PONG to o...
bool HavePendingTransactions() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if there are transactions that need to be broadcast.
bool DidNodeConfirmReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if the node has confirmed reception of the transaction.
std::optional< size_t > Remove(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Forget a transaction.
std::optional< CTransactionRef > PickTxForSend(const NodeId &will_send_to_nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Pick the transaction with the fewest send attempts, and confirmations, and oldest send/confirm times.
std::optional< CTransactionRef > GetTxForNode(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transaction that was picked for sending to a given node by PickTxForSend().
bool Add(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a transaction to the storage.
std::vector< CTransactionRef > GetStale() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transactions that have not been broadcast recently.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
std::string GetDebugMessage() const
std::string ToString() const
256-bit unsigned big integer.
constexpr bool IsNull() const
std::string ToString() const
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool LoadingBlocks() const
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t > > block_part=std::nullopt) const
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
bool IsPruneMode() const
Whether running in -prune mode.
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
Manages warning messages within a node.
std::string ToString() const
const uint256 & ToUint256() const LIFETIMEBOUND
The util::Expected class provides a standard way for low-level functions to return either error value...
The util::Unexpected class represents an unexpected value stored in util::Expected.
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
@ BLOCK_HEADER_LOW_WORK
the block header may be on a too-little-work chain
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ BLOCK_RESULT_UNSET
initial value. Block has not yet been rejected
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_NO_MEMPOOL
this node does not have a mempool so can't validate the transaction
@ TX_RESULT_UNSET
initial value. Tx has not yet been rejected
static size_t RecursiveDynamicUsage(const CScript &script)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
is a home for simple enum and struct type definitions that can be used internally by functions in the...
#define LogDebug(category,...)
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
TRACEPOINT_SEMAPHORE(net, inbound_message)
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr size_t NUM_PRIVATE_BROADCAST_PER_TX
For private broadcast, send a transaction to this many 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 PRIVATE_BROADCAST_MAX_CONNECTION_LIFETIME
Private broadcast connections must complete within this time.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" message type for wtxid-based relay starts with this version
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" message type and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
std::chrono::seconds time_offset
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
@ DIFFERENT_WITNESS
Valid, transaction was already in the mempool.
@ INVALID
Fully validated, valid.
const std::list< CTransactionRef > m_replaced_transactions
Mempool transactions replaced by the tx.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
Validation result for package mempool acceptance.
PackageValidationState m_state
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
std::chrono::seconds median_outbound_time_offset
Information about chainstate that notifications are sent from.
bool historical
Whether this is a historical chainstate downloading old blocks to validate an assumeutxo snapshot,...
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
std::vector< NodeId > m_senders
std::string ToString() const
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define ACQUIRED_BEFORE(...)
#define TRACEPOINT(context,...)
consteval auto _(util::TranslatedLiteral str)
ReconciliationRegisterResult
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
constexpr int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
bool HasValidProofOfWork(std::span< const CBlockHeader > headers, const Consensus::Params &consensusParams)
Check that 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...