176 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
210 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
213 const bool m_is_inbound;
216 Mutex m_misbehavior_mutex;
218 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
221 Mutex m_block_inv_mutex;
225 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
229 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
240 std::atomic<int> m_starting_height{-1};
243 std::atomic<uint64_t> m_ping_nonce_sent{0};
245 std::atomic<std::chrono::microseconds> m_ping_start{0us};
247 std::atomic<bool> m_ping_queued{
false};
250 std::atomic<bool> m_wtxid_relay{
false};
262 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
264 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
275 std::set<uint256> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
279 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
282 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
288 std::atomic<CAmount> m_fee_filter_received{0};
294 LOCK(m_tx_relay_mutex);
296 m_tx_relay = std::make_unique<Peer::TxRelay>();
297 return m_tx_relay.get();
302 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
331 std::atomic_bool m_addr_relay_enabled{
false};
335 mutable Mutex m_addr_send_times_mutex;
337 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
339 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
342 std::atomic_bool m_wants_addrv2{
false};
351 std::atomic<uint64_t> m_addr_rate_limited{0};
353 std::atomic<uint64_t> m_addr_processed{0};
359 Mutex m_getdata_requests_mutex;
361 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
367 Mutex m_headers_sync_mutex;
370 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
373 std::atomic<bool> m_sent_sendheaders{
false};
383 std::atomic<std::chrono::seconds> m_time_offset{0
s};
387 , m_our_services{our_services}
388 , m_is_inbound{is_inbound}
392 mutable Mutex m_tx_relay_mutex;
395 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
398 using PeerRef = std::shared_ptr<Peer>;
410 uint256 hashLastUnknownBlock{};
416 bool fSyncStarted{
false};
418 std::chrono::microseconds m_stalling_since{0us};
419 std::list<QueuedBlock> vBlocksInFlight;
421 std::chrono::microseconds m_downloading_since{0us};
423 bool fPreferredDownload{
false};
425 bool m_requested_hb_cmpctblocks{
false};
427 bool m_provides_cmpctblocks{
false};
453 struct ChainSyncTimeoutState {
455 std::chrono::seconds m_timeout{0
s};
459 bool m_sent_getheaders{
false};
461 bool m_protect{
false};
464 ChainSyncTimeoutState m_chain_sync;
467 int64_t m_last_block_announcement{0};
478 void ActiveTipChange(
const CBlockIndex& new_tip,
bool)
override 480 void BlockConnected(
ChainstateRole role,
const std::shared_ptr<const CBlock>& pblock,
const CBlockIndex* pindexConnected)
override 482 void BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
override 484 void UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
override 488 void NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
override 494 bool HasAllDesirableServiceFlags(
ServiceFlags services)
const override;
495 bool ProcessMessages(
CNode* pfrom, std::atomic<bool>& interrupt)
override 496 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
497 bool SendMessages(
CNode* pto)
override 501 void StartScheduledTasks(
CScheduler& scheduler)
override;
502 void CheckForStaleTipAndEvictPeers()
override;
503 std::optional<std::string> FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
override 506 std::vector<TxOrphanage::OrphanTxBase> GetOrphanTransactions() override
EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);
510 void SetBestBlock(
int height,
std::chrono::seconds time)
override 512 m_best_height = height;
513 m_best_block_time = time;
516 void ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
517 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override 518 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex);
519 void UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
override;
542 void Misbehaving(Peer& peer,
const std::string& message);
553 bool via_compact_block,
const std::string& message =
"")
568 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
582 bool first_time_failure)
607 bool ProcessOrphanTx(Peer& peer)
617 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
619 bool via_compact_block)
631 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
650 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
664 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
679 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
681 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
688 template <
typename... Args>
689 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const 695 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
701 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
744 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
747 std::atomic<int> m_best_height{-1};
749 std::atomic<std::chrono::seconds> m_best_block_time{0
s};
757 const Options m_opts;
759 bool RejectIncomingTxs(
const CNode& peer)
const;
767 mutable Mutex m_peer_mutex;
774 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
784 uint32_t GetFetchFlags(
const Peer& peer)
const;
786 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
803 std::atomic<int> m_wtxid_relay_peers{0};
820 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
825 Mutex m_most_recent_block_mutex;
826 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
827 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
829 std::unique_ptr<const std::map<uint256, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
833 Mutex m_headers_presync_mutex;
841 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
843 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
847 std::atomic_bool m_headers_presync_should_signal{
false};
917 std::atomic<
std::chrono::seconds> m_last_tip_update{0
s};
923 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
928 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
953 std::vector<CTransactionRef> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
955 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
967 int64_t ApproximateBestBlockDepth() const;
977 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
995 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
997 const
uint256& stop_hash, uint32_t max_height_diff,
1046 const CNodeState* PeerManagerImpl::
State(
NodeId pnode)
const 1048 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1049 if (it == m_node_states.end())
1056 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1064 static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1069 void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1071 assert(peer.m_addr_known);
1072 peer.m_addr_known->insert(addr.
GetKey());
1075 void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1080 assert(peer.m_addr_known);
1081 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1083 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1085 peer.m_addrs_to_send.push_back(addr);
1090 static void AddKnownTx(Peer& peer,
const uint256& hash)
1092 auto tx_relay = peer.GetTxRelay();
1093 if (!tx_relay)
return;
1095 LOCK(tx_relay->m_tx_inventory_mutex);
1096 tx_relay->m_tx_inventory_known_filter.insert(hash);
1100 static bool CanServeBlocks(
const Peer& peer)
1107 static bool IsLimitedPeer(
const Peer& peer)
1114 static bool CanServeWitnesses(
const Peer& peer)
1119 std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1120 std::chrono::seconds average_interval)
1122 if (m_next_inv_to_inbounds.load() < now) {
1126 m_next_inv_to_inbounds = now + m_rng.rand_exp_duration(average_interval);
1128 return m_next_inv_to_inbounds;
1131 bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1133 return mapBlocksInFlight.count(hash);
1136 bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1138 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1139 auto [nodeid, block_it] = range.first->second;
1140 PeerRef peer{GetPeerRef(nodeid)};
1141 if (peer && !peer->m_is_inbound)
return true;
1147 void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1149 auto range = mapBlocksInFlight.equal_range(hash);
1150 if (range.first == range.second) {
1158 while (range.first != range.second) {
1159 auto [node_id, list_it] = range.first->second;
1161 if (from_peer && *from_peer != node_id) {
1168 if (state.vBlocksInFlight.begin() == list_it) {
1170 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1172 state.vBlocksInFlight.erase(list_it);
1174 if (state.vBlocksInFlight.empty()) {
1176 m_peers_downloading_from--;
1178 state.m_stalling_since = 0us;
1180 range.first = mapBlocksInFlight.erase(range.first);
1184 bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1188 CNodeState *state =
State(nodeid);
1189 assert(state !=
nullptr);
1194 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1195 if (range.first->second.first == nodeid) {
1197 *pit = &range.first->second.second;
1204 RemoveBlockRequest(hash, nodeid);
1206 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1208 if (state->vBlocksInFlight.size() == 1) {
1210 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1211 m_peers_downloading_from++;
1213 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1215 *pit = &itInFlight->second.second;
1220 void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1227 if (m_opts.ignore_incoming_txs)
return;
1229 CNodeState* nodestate =
State(nodeid);
1230 PeerRef peer{GetPeerRef(nodeid)};
1231 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1236 int num_outbound_hb_peers = 0;
1237 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1238 if (*it == nodeid) {
1239 lNodesAnnouncingHeaderAndIDs.erase(it);
1240 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1243 PeerRef peer_ref{GetPeerRef(*it)};
1244 if (peer_ref && !peer_ref->m_is_inbound) ++num_outbound_hb_peers;
1246 if (peer && peer->m_is_inbound) {
1249 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1250 PeerRef remove_peer{GetPeerRef(lNodesAnnouncingHeaderAndIDs.front())};
1251 if (remove_peer && !remove_peer->m_is_inbound) {
1254 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1260 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1263 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1266 pnodeStop->m_bip152_highbandwidth_to =
false;
1269 lNodesAnnouncingHeaderAndIDs.pop_front();
1274 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1279 bool PeerManagerImpl::TipMayBeStale()
1283 if (m_last_tip_update.load() == 0
s) {
1284 m_last_tip_update = GetTime<std::chrono::seconds>();
1286 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1289 int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const 1294 bool PeerManagerImpl::CanDirectFetch()
1301 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1303 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1308 void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1309 CNodeState *state =
State(nodeid);
1310 assert(state !=
nullptr);
1312 if (!state->hashLastUnknownBlock.IsNull()) {
1315 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1316 state->pindexBestKnownBlock = pindex;
1318 state->hashLastUnknownBlock.SetNull();
1323 void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1324 CNodeState *state =
State(nodeid);
1325 assert(state !=
nullptr);
1327 ProcessBlockAvailability(nodeid);
1332 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1333 state->pindexBestKnownBlock = pindex;
1337 state->hashLastUnknownBlock = hash;
1342 void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1347 vBlocks.reserve(vBlocks.size() +
count);
1348 CNodeState *state =
State(peer.m_id);
1349 assert(state !=
nullptr);
1352 ProcessBlockAvailability(peer.m_id);
1354 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1362 const CBlockIndex* snap_base{m_chainman.GetSnapshotBaseBlock()};
1363 if (snap_base && state->pindexBestKnownBlock->GetAncestor(snap_base->nHeight) != snap_base) {
1364 LogDebug(
BCLog::NET,
"Not downloading blocks from peer=%d, which doesn't have the snapshot block in its best chain.\n", peer.m_id);
1371 if (state->pindexLastCommonBlock ==
nullptr ||
1372 (snap_base && state->pindexLastCommonBlock->nHeight < snap_base->nHeight)) {
1373 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1378 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1379 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1382 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1388 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1391 void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1396 if (vBlocks.size() >=
count) {
1400 vBlocks.reserve(
count);
1403 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1420 void 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)
1422 std::vector<const CBlockIndex*> vToFetch;
1423 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1424 bool is_limited_peer = IsLimitedPeer(peer);
1426 while (pindexWalk->
nHeight < nMaxHeight) {
1430 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1431 vToFetch.resize(nToFetch);
1432 pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->
nHeight + nToFetch);
1433 vToFetch[nToFetch - 1] = pindexWalk;
1434 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1435 vToFetch[i - 1] = vToFetch[i]->
pprev;
1455 state->pindexLastCommonBlock = pindex;
1462 if (waitingfor == -1) {
1464 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1470 if (pindex->
nHeight > nWindowEnd) {
1472 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1474 if (nodeStaller) *nodeStaller = waitingfor;
1484 vBlocks.push_back(pindex);
1485 if (vBlocks.size() ==
count) {
1494 void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1496 uint64_t my_services{peer.m_our_services};
1497 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1499 const int nNodeStartingHeight{m_best_height};
1506 const bool tx_relay{!RejectIncomingTxs(pnode)};
1513 LogDebug(
BCLog::NET,
"send version message: version %d, blocks=%d, them=%s, txrelay=%d, peer=%d\n",
PROTOCOL_VERSION, nNodeStartingHeight, addr_you.
ToStringAddrPort(), tx_relay, nodeid);
1519 void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1523 if (state) state->m_last_block_announcement = time_in_seconds;
1531 m_node_states.try_emplace(m_node_states.end(), nodeid);
1533 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty(nodeid));
1539 PeerRef peer = std::make_shared<Peer>(nodeid, our_services,
node.IsInboundConn());
1542 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1546 void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1550 for (
const auto& txid : unbroadcast_txids) {
1553 if (tx !=
nullptr) {
1554 RelayTransaction(txid, tx->GetWitnessHash());
1563 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1566 void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1577 PeerRef peer = RemovePeer(nodeid);
1579 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1580 assert(m_wtxid_relay_peers >= 0);
1582 CNodeState *state =
State(nodeid);
1583 assert(state !=
nullptr);
1585 if (state->fSyncStarted)
1588 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1589 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1590 while (range.first != range.second) {
1591 auto [node_id, list_it] = range.first->second;
1592 if (node_id != nodeid) {
1595 range.first = mapBlocksInFlight.erase(range.first);
1600 LOCK(m_tx_download_mutex);
1601 m_txdownloadman.DisconnectedPeer(nodeid);
1603 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1604 m_num_preferred_download_peers -= state->fPreferredDownload;
1605 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1606 assert(m_peers_downloading_from >= 0);
1607 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1608 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1610 m_node_states.erase(nodeid);
1612 if (m_node_states.empty()) {
1614 assert(mapBlocksInFlight.empty());
1615 assert(m_num_preferred_download_peers == 0);
1616 assert(m_peers_downloading_from == 0);
1617 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1618 assert(m_wtxid_relay_peers == 0);
1619 WITH_LOCK(m_tx_download_mutex, m_txdownloadman.CheckIsEmpty());
1622 if (
node.fSuccessfullyConnected &&
1623 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1630 LOCK(m_headers_presync_mutex);
1631 m_headers_presync_stats.erase(nodeid);
1636 bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const 1639 return !(GetDesirableServiceFlags(services) & (~services));
1653 PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const 1656 auto it = m_peer_map.find(
id);
1657 return it != m_peer_map.end() ? it->second :
nullptr;
1660 PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1664 auto it = m_peer_map.find(
id);
1665 if (it != m_peer_map.end()) {
1666 ret = std::move(it->second);
1667 m_peer_map.erase(it);
1676 const CNodeState* state =
State(nodeid);
1677 if (state ==
nullptr)
1679 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1680 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1681 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1687 PeerRef peer = GetPeerRef(nodeid);
1688 if (peer ==
nullptr)
return false;
1697 auto ping_wait{0us};
1698 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1699 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1702 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1715 LOCK(peer->m_headers_sync_mutex);
1716 if (peer->m_headers_sync) {
1725 std::vector<TxOrphanage::OrphanTxBase> PeerManagerImpl::GetOrphanTransactions()
1727 LOCK(m_tx_download_mutex);
1728 return m_txdownloadman.GetOrphanTransactions();
1735 .ignores_incoming_txs = m_opts.ignore_incoming_txs,
1739 void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1741 if (m_opts.max_extra_txs <= 0)
1743 if (!vExtraTxnForCompact.size())
1744 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1745 vExtraTxnForCompact[vExtraTxnForCompactIt] = tx;
1746 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1749 void PeerManagerImpl::Misbehaving(Peer& peer,
const std::string& message)
1751 LOCK(peer.m_misbehavior_mutex);
1753 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1754 peer.m_should_discourage =
true;
1763 bool via_compact_block,
const std::string& message)
1765 PeerRef peer{GetPeerRef(nodeid)};
1776 if (!via_compact_block) {
1777 if (peer) Misbehaving(*peer, message);
1785 if (peer && !via_compact_block && !peer->m_is_inbound) {
1786 if (peer) Misbehaving(*peer, message);
1794 if (peer) Misbehaving(*peer, message);
1798 if (peer) Misbehaving(*peer, message);
1803 if (message !=
"") {
1810 PeerRef peer{GetPeerRef(nodeid)};
1816 if (peer) Misbehaving(*peer,
"");
1834 bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1843 std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1848 PeerRef peer = GetPeerRef(peer_id);
1849 if (peer ==
nullptr)
return "Peer does not exist";
1852 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1857 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1860 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1872 if (!success)
return "Peer not fully connected";
1876 return std::nullopt;
1883 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
1889 : m_rng{opts.deterministic_rng},
1891 m_chainparams(chainman.GetParams()),
1895 m_chainman(chainman),
1898 m_warnings{warnings},
1903 if (opts.reconcile_txs) {
1908 void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1919 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1922 void PeerManagerImpl::ActiveTipChange(
const CBlockIndex& new_tip,
bool is_ibd)
1930 LOCK(m_tx_download_mutex);
1934 m_txdownloadman.ActiveTipChange();
1944 void PeerManagerImpl::BlockConnected(
1946 const std::shared_ptr<const CBlock>& pblock,
1951 m_last_tip_update = GetTime<std::chrono::seconds>();
1954 auto stalling_timeout = m_block_stalling_timeout.load();
1958 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1968 LOCK(m_tx_download_mutex);
1969 m_txdownloadman.BlockConnected(pblock);
1972 void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1974 LOCK(m_tx_download_mutex);
1975 m_txdownloadman.BlockDisconnected();
1982 void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1988 if (pindex->
nHeight <= m_highest_fast_announce)
1990 m_highest_fast_announce = pindex->
nHeight;
1994 uint256 hashBlock(pblock->GetHash());
1995 const std::shared_future<CSerializedNetMsg> lazy_ser{
1999 auto most_recent_block_txs = std::make_unique<std::map<uint256, CTransactionRef>>();
2000 for (
const auto& tx : pblock->vtx) {
2001 most_recent_block_txs->emplace(tx->GetHash(), tx);
2002 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2005 LOCK(m_most_recent_block_mutex);
2006 m_most_recent_block_hash = hashBlock;
2007 m_most_recent_block = pblock;
2008 m_most_recent_compact_block = pcmpctblock;
2009 m_most_recent_block_txs = std::move(most_recent_block_txs);
2017 ProcessBlockAvailability(pnode->
GetId());
2021 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2023 LogDebug(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2024 hashBlock.ToString(), pnode->
GetId());
2027 PushMessage(*pnode, ser_cmpctblock.Copy());
2028 state.pindexBestHeaderSent = pindex;
2037 void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2039 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2042 if (fInitialDownload)
return;
2045 std::vector<uint256> vHashes;
2047 while (pindexToAnnounce != pindexFork) {
2049 pindexToAnnounce = pindexToAnnounce->
pprev;
2059 for (
auto& it : m_peer_map) {
2060 Peer& peer = *it.second;
2061 LOCK(peer.m_block_inv_mutex);
2062 for (
const uint256& hash : vHashes | std::views::reverse) {
2063 peer.m_blocks_for_headers_relay.push_back(hash);
2080 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2085 it != mapBlockSource.end() &&
2086 State(it->second.first)) {
2087 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2097 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2098 if (it != mapBlockSource.end()) {
2099 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2102 if (it != mapBlockSource.end())
2103 mapBlockSource.erase(it);
2111 bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2116 void PeerManagerImpl::SendPings()
2119 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2122 void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2125 for(
auto& it : m_peer_map) {
2126 Peer& peer = *it.second;
2127 auto tx_relay = peer.GetTxRelay();
2128 if (!tx_relay)
continue;
2130 LOCK(tx_relay->m_tx_inventory_mutex);
2136 if (tx_relay->m_next_inv_send_time == 0
s)
continue;
2138 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2139 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2140 tx_relay->m_tx_inventory_to_send.insert(hash);
2145 void PeerManagerImpl::RelayAddress(
NodeId originator,
2161 const auto current_time{GetTime<std::chrono::seconds>()};
2169 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2171 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2172 assert(nRelayNodes <= best.size());
2176 for (
auto& [
id, peer] : m_peer_map) {
2177 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2179 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2180 if (hashKey > best[i].first) {
2181 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2182 best[i] = std::make_pair(hashKey, peer.get());
2189 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2190 PushAddress(*best[i].second, addr);
2194 void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2196 std::shared_ptr<const CBlock> a_recent_block;
2197 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2199 LOCK(m_most_recent_block_mutex);
2200 a_recent_block = m_most_recent_block;
2201 a_recent_compact_block = m_most_recent_compact_block;
2204 bool need_activate_chain =
false;
2216 need_activate_chain =
true;
2220 if (need_activate_chain) {
2222 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2229 bool can_direct_fetch{
false};
2237 if (!BlockRequestAllowed(pindex)) {
2238 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2265 can_direct_fetch = CanDirectFetch();
2269 std::shared_ptr<const CBlock> pblock;
2270 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2271 pblock = a_recent_block;
2275 std::vector<uint8_t> block_data;
2289 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2299 pblock = pblockRead;
2307 bool sendMerkleBlock =
false;
2309 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2310 LOCK(tx_relay->m_bloom_filter_mutex);
2311 if (tx_relay->m_bloom_filter) {
2312 sendMerkleBlock =
true;
2313 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2316 if (sendMerkleBlock) {
2324 typedef std::pair<unsigned int, uint256> PairType;
2336 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2349 LOCK(peer.m_block_inv_mutex);
2351 if (inv.
hash == peer.m_continuation_block) {
2355 std::vector<CInv> vInv;
2356 vInv.emplace_back(
MSG_BLOCK, tip->GetBlockHash());
2358 peer.m_continuation_block.SetNull();
2366 auto txinfo = m_mempool.
info_for_relay(gtxid, tx_relay.m_last_inv_sequence);
2368 return std::move(txinfo.tx);
2373 LOCK(m_most_recent_block_mutex);
2374 if (m_most_recent_block_txs !=
nullptr) {
2375 auto it = m_most_recent_block_txs->find(gtxid.
GetHash());
2376 if (it != m_most_recent_block_txs->end())
return it->second;
2383 void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2387 auto tx_relay = peer.GetTxRelay();
2389 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2390 std::vector<CInv> vNotFound;
2395 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2396 if (interruptMsgProc)
return;
2401 const CInv &inv = *it++;
2403 if (tx_relay ==
nullptr) {
2413 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2416 vNotFound.push_back(inv);
2422 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2423 const CInv &inv = *it++;
2425 ProcessGetBlockData(pfrom, peer, inv);
2431 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2433 if (!vNotFound.empty()) {
2452 uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const 2454 uint32_t nFetchFlags = 0;
2455 if (CanServeWitnesses(peer)) {
2464 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2466 Misbehaving(peer,
"getblocktxn with out-of-bounds tx indices");
2475 bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2479 Misbehaving(peer,
"header with invalid proof of work");
2484 if (!CheckHeadersAreContinuous(headers)) {
2485 Misbehaving(peer,
"non-continuous headers sequence");
2510 void PeerManagerImpl::HandleUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2511 const std::vector<CBlockHeader>& headers)
2515 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2516 LogDebug(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d)\n",
2518 headers[0].hashPrevBlock.ToString(),
2519 best_header->nHeight,
2529 bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const 2533 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2536 hashLastBlock = header.GetHash();
2541 bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2543 if (peer.m_headers_sync) {
2544 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result);
2546 if (
result.success) peer.m_last_getheaders_timestamp = {};
2547 if (
result.request_more) {
2548 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2550 Assume(!locator.vHave.empty());
2553 if (!locator.vHave.empty()) {
2556 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2559 locator.vHave.front().ToString(), pfrom.
GetId());
2564 peer.m_headers_sync.reset(
nullptr);
2569 LOCK(m_headers_presync_mutex);
2570 m_headers_presync_stats.erase(pfrom.
GetId());
2573 HeadersPresyncStats stats;
2574 stats.first = peer.m_headers_sync->GetPresyncWork();
2576 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2577 peer.m_headers_sync->GetPresyncTime()};
2581 LOCK(m_headers_presync_mutex);
2582 m_headers_presync_stats[pfrom.
GetId()] = stats;
2583 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2584 bool best_updated =
false;
2585 if (best_it == m_headers_presync_stats.end()) {
2589 const HeadersPresyncStats* stat_best{
nullptr};
2590 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2591 if (!stat_best || stat > *stat_best) {
2596 m_headers_presync_bestpeer = peer_best;
2597 best_updated = (peer_best == pfrom.
GetId());
2598 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2600 m_headers_presync_bestpeer = pfrom.
GetId();
2601 best_updated =
true;
2603 if (best_updated && stats.second.has_value()) {
2605 m_headers_presync_should_signal =
true;
2612 headers.swap(
result.pow_validated_headers);
2623 bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2630 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2634 if (total_work < minimum_chain_work) {
2638 if (headers.size() == m_opts.max_headers_result) {
2648 LOCK(peer.m_headers_sync_mutex);
2650 chain_start_header, minimum_chain_work));
2655 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2669 bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2671 if (header ==
nullptr) {
2673 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2681 bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2689 peer.m_last_getheaders_timestamp = current_time;
2700 void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2703 CNodeState *nodestate =
State(pfrom.
GetId());
2706 std::vector<const CBlockIndex*> vToFetch;
2714 vToFetch.push_back(pindexWalk);
2716 pindexWalk = pindexWalk->
pprev;
2727 std::vector<CInv> vGetData;
2729 for (
const CBlockIndex* pindex : vToFetch | std::views::reverse) {
2734 uint32_t nFetchFlags = GetFetchFlags(peer);
2736 BlockRequested(pfrom.
GetId(), *pindex);
2740 if (vGetData.size() > 1) {
2745 if (vGetData.size() > 0) {
2746 if (!m_opts.ignore_incoming_txs &&
2747 nodestate->m_provides_cmpctblocks &&
2748 vGetData.size() == 1 &&
2749 mapBlocksInFlight.size() == 1 &&
2765 void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2766 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2769 CNodeState *nodestate =
State(pfrom.
GetId());
2778 nodestate->m_last_block_announcement =
GetTime();
2786 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2808 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) {
2810 nodestate->m_chain_sync.m_protect =
true;
2811 ++m_outbound_peers_with_protect_from_disconnect;
2816 void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2817 std::vector<CBlockHeader>&& headers,
2818 bool via_compact_block)
2820 size_t nCount = headers.size();
2827 LOCK(peer.m_headers_sync_mutex);
2828 if (peer.m_headers_sync) {
2829 peer.m_headers_sync.reset(
nullptr);
2830 LOCK(m_headers_presync_mutex);
2831 m_headers_presync_stats.erase(pfrom.
GetId());
2835 peer.m_last_getheaders_timestamp = {};
2843 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2858 bool already_validated_work =
false;
2861 bool have_headers_sync =
false;
2863 LOCK(peer.m_headers_sync_mutex);
2865 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2877 if (headers.empty()) {
2881 have_headers_sync = !!peer.m_headers_sync;
2886 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2888 if (!headers_connect_blockindex) {
2892 HandleUnconnectingHeaders(pfrom, peer, headers);
2899 peer.m_last_getheaders_timestamp = {};
2909 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2910 already_validated_work =
true;
2918 already_validated_work =
true;
2924 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2925 chain_start_header, headers)) {
2937 bool received_new_header{last_received_header ==
nullptr};
2943 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2950 if (nCount == m_opts.max_headers_result && !have_headers_sync) {
2952 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2954 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2958 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);
2961 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
2967 bool first_time_failure)
2973 PeerRef peer{GetPeerRef(nodeid)};
2976 ptx->GetHash().ToString(),
2977 ptx->GetWitnessHash().ToString(),
2981 const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
2984 AddToCompactExtraTransactions(ptx);
2986 for (
const Txid& parent_txid : unique_parents) {
2987 if (peer) AddKnownTx(*peer, parent_txid);
2990 MaybePunishNodeForTx(nodeid, state);
2992 return package_to_validate;
2995 void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3001 m_txdownloadman.MempoolAcceptedTx(tx);
3005 tx->GetHash().ToString(),
3006 tx->GetWitnessHash().ToString(),
3009 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3012 AddToCompactExtraTransactions(removedTx);
3022 const auto&
package = package_to_validate.m_txns;
3023 const auto& senders = package_to_validate.
m_senders;
3026 m_txdownloadman.MempoolRejectedPackage(package);
3029 if (!
Assume(package.size() == 2))
return;
3033 auto package_iter = package.rbegin();
3034 auto senders_iter = senders.rbegin();
3035 while (package_iter != package.rend()) {
3036 const auto& tx = *package_iter;
3037 const NodeId nodeid = *senders_iter;
3038 const auto it_result{package_result.
m_tx_results.find(tx->GetWitnessHash())};
3042 const auto& tx_result = it_result->second;
3043 switch (tx_result.m_result_type) {
3046 ProcessValidTx(nodeid, tx, tx_result.m_replaced_transactions);
3056 ProcessInvalidTx(nodeid, tx, tx_result.m_state,
false);
3072 bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3079 while (
CTransactionRef porphanTx = m_txdownloadman.GetTxToReconsider(peer.m_id)) {
3082 const Txid& orphanHash = porphanTx->GetHash();
3083 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3087 ProcessValidTx(peer.m_id, porphanTx,
result.m_replaced_transactions);
3100 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3109 bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3111 const uint256& stop_hash, uint32_t max_height_diff,
3115 const bool supported_filter_type =
3118 if (!supported_filter_type) {
3120 static_cast<uint8_t>(filter_type),
node.DisconnectMsg(
fLogIPs));
3121 node.fDisconnect =
true;
3130 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3133 node.fDisconnect =
true;
3138 uint32_t stop_height = stop_index->
nHeight;
3139 if (start_height > stop_height) {
3141 "start height %d and stop height %d, %s\n",
3142 start_height, stop_height,
node.DisconnectMsg(
fLogIPs));
3143 node.fDisconnect =
true;
3146 if (stop_height - start_height >= max_height_diff) {
3148 stop_height - start_height + 1, max_height_diff,
node.DisconnectMsg(
fLogIPs));
3149 node.fDisconnect =
true;
3154 if (!filter_index) {
3164 uint8_t filter_type_ser;
3165 uint32_t start_height;
3168 vRecv >> filter_type_ser >> start_height >> stop_hash;
3174 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3179 std::vector<BlockFilter> filters;
3181 LogDebug(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3186 for (
const auto& filter : filters) {
3193 uint8_t filter_type_ser;
3194 uint32_t start_height;
3197 vRecv >> filter_type_ser >> start_height >> stop_hash;
3203 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3209 if (start_height > 0) {
3211 stop_index->
GetAncestor(static_cast<int>(start_height - 1));
3213 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3219 std::vector<uint256> filter_hashes;
3221 LogDebug(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3235 uint8_t filter_type_ser;
3238 vRecv >> filter_type_ser >> stop_hash;
3244 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3245 std::numeric_limits<uint32_t>::max(),
3246 stop_index, filter_index)) {
3254 for (
int i = headers.size() - 1; i >= 0; i--) {
3259 LogDebug(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3271 void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked)
3273 bool new_block{
false};
3274 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3276 node.m_last_block_time = GetTime<std::chrono::seconds>();
3281 RemoveBlockRequest(block->GetHash(), std::nullopt);
3284 mapBlockSource.erase(block->GetHash());
3288 void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3290 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3291 bool fBlockRead{
false};
3295 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3296 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3297 bool requested_block_from_this_peer{
false};
3300 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3302 while (range_flight.first != range_flight.second) {
3303 auto [node_id, block_it] = range_flight.first->second;
3304 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3305 requested_block_from_this_peer =
true;
3308 range_flight.first++;
3311 if (!requested_block_from_this_peer) {
3320 Misbehaving(peer,
"invalid compact block/non-matching block transactions");
3323 if (first_in_flight) {
3325 std::vector<CInv> invs;
3330 LogDebug(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3359 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3369 ProcessBlock(pfrom, pblock,
true,
true);
3374 void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3375 const std::chrono::microseconds time_received,
3376 const std::atomic<bool>& interruptMsgProc)
3382 PeerRef peer = GetPeerRef(pfrom.
GetId());
3383 if (peer ==
nullptr)
return;
3393 uint64_t nNonce = 1;
3396 std::string cleanSubVer;
3397 int starting_height = -1;
3400 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3415 LogDebug(
BCLog::NET,
"peer does not offer the expected services (%08x offered, %08x expected), %s\n",
3417 GetDesirableServiceFlags(nServices),
3430 if (!vRecv.
empty()) {
3438 if (!vRecv.
empty()) {
3439 std::string strSubVer;
3443 if (!vRecv.
empty()) {
3444 vRecv >> starting_height;
3464 PushNodeVersion(pfrom, *peer);
3477 if (greatest_common_version >= 70016) {
3486 peer->m_their_services = nServices;
3490 pfrom.cleanSubVer = cleanSubVer;
3492 peer->m_starting_height = starting_height;
3502 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3503 auto*
const tx_relay = peer->SetTxRelay();
3505 LOCK(tx_relay->m_bloom_filter_mutex);
3506 tx_relay->m_relay_txs = fRelay;
3518 const auto* tx_relay = peer->GetTxRelay();
3519 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3521 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3534 m_num_preferred_download_peers += state->fPreferredDownload;
3540 bool send_getaddr{
false};
3542 send_getaddr = SetupAddressRelay(pfrom, *peer);
3552 peer->m_getaddr_sent =
true;
3577 LogDebug(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3582 peer->m_time_offset =
NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
3586 m_outbound_time_offsets.Add(peer->m_time_offset);
3587 m_outbound_time_offsets.WarnIfOutOfSync();
3591 if (greatest_common_version <= 70012) {
3592 constexpr
auto finalAlert{
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"_hex};
3593 MakeAndPushMessage(pfrom,
"alert", finalAlert);
3620 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3623 pfrom.
nVersion.load(), peer->m_starting_height,
3625 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3637 if (m_txreconciliation) {
3638 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3642 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3646 if (
auto tx_relay = peer->GetTxRelay()) {
3655 tx_relay->m_tx_inventory_mutex,
3656 return tx_relay->m_tx_inventory_to_send.empty() &&
3657 tx_relay->m_next_inv_send_time == 0
s));
3662 const CNodeState* state =
State(pfrom.
GetId());
3666 .m_wtxid_relay = peer->m_wtxid_relay,
3675 peer->m_prefers_headers =
true;
3680 bool sendcmpct_hb{
false};
3681 uint64_t sendcmpct_version{0};
3682 vRecv >> sendcmpct_hb >> sendcmpct_version;
3688 CNodeState* nodestate =
State(pfrom.
GetId());
3689 nodestate->m_provides_cmpctblocks =
true;
3690 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3707 if (!peer->m_wtxid_relay) {
3708 peer->m_wtxid_relay =
true;
3709 m_wtxid_relay_peers++;
3728 peer->m_wants_addrv2 =
true;
3736 if (!m_txreconciliation) {
3737 LogDebug(
BCLog::NET,
"sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.
GetId());
3748 if (RejectIncomingTxs(pfrom)) {
3757 const auto* tx_relay = peer->GetTxRelay();
3758 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3764 uint32_t peer_txreconcl_version;
3765 uint64_t remote_salt;
3766 vRecv >> peer_txreconcl_version >> remote_salt;
3769 peer_txreconcl_version, remote_salt);
3794 const auto ser_params{
3802 std::vector<CAddress> vAddr;
3804 vRecv >> ser_params(vAddr);
3806 if (!SetupAddressRelay(pfrom, *peer)) {
3813 Misbehaving(*peer,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3818 std::vector<CAddress> vAddrOk;
3819 const auto current_a_time{Now<NodeSeconds>()};
3822 const auto current_time{GetTime<std::chrono::microseconds>()};
3825 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3829 peer->m_addr_token_timestamp = current_time;
3832 uint64_t num_proc = 0;
3833 uint64_t num_rate_limit = 0;
3834 std::shuffle(vAddr.begin(), vAddr.end(), m_rng);
3837 if (interruptMsgProc)
3841 if (peer->m_addr_token_bucket < 1.0) {
3847 peer->m_addr_token_bucket -= 1.0;
3856 addr.
nTime = current_a_time - 5 * 24h;
3858 AddAddressKnown(*peer, addr);
3865 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3867 RelayAddress(pfrom.
GetId(), addr, reachable);
3871 vAddrOk.push_back(addr);
3874 peer->m_addr_processed += num_proc;
3875 peer->m_addr_rate_limited += num_rate_limit;
3876 LogDebug(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3877 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3879 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3880 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3891 std::vector<CInv> vInv;
3895 Misbehaving(*peer,
strprintf(
"inv message size = %u", vInv.size()));
3899 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3903 const auto current_time{GetTime<std::chrono::microseconds>()};
3906 for (
CInv& inv : vInv) {
3907 if (interruptMsgProc)
return;
3912 if (peer->m_wtxid_relay) {
3919 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3922 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3930 best_block = &inv.
hash;
3933 if (reject_tx_invs) {
3939 AddKnownTx(*peer, inv.
hash);
3942 const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.
GetId(), gtxid, current_time)};
3950 if (best_block !=
nullptr) {
3962 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
3963 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
3965 m_chainman.m_best_header->nHeight, best_block->ToString(),
3968 if (!state.fSyncStarted) {
3969 peer->m_inv_triggered_getheaders_before_sync =
true;
3973 m_last_block_inv_triggering_headers_sync = *best_block;
3982 std::vector<CInv> vInv;
3986 Misbehaving(*peer,
strprintf(
"getdata message size = %u", vInv.size()));
3992 if (vInv.size() > 0) {
3997 LOCK(peer->m_getdata_requests_mutex);
3998 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
3999 ProcessGetData(pfrom, *peer, interruptMsgProc);
4008 vRecv >> locator >> hashStop;
4024 std::shared_ptr<const CBlock> a_recent_block;
4026 LOCK(m_most_recent_block_mutex);
4027 a_recent_block = m_most_recent_block;
4030 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4044 LogDebug(
BCLog::NET,
"getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->
nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), nLimit, pfrom.
GetId());
4060 if (--nLimit <= 0) {
4064 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4075 std::shared_ptr<const CBlock> recent_block;
4077 LOCK(m_most_recent_block_mutex);
4078 if (m_most_recent_block_hash == req.blockhash)
4079 recent_block = m_most_recent_block;
4083 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4102 if (!block_pos.IsNull()) {
4109 SendBlockTransactions(pfrom, *peer, block, req);
4122 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4130 vRecv >> locator >> hashStop;
4152 if (m_chainman.
ActiveTip() ==
nullptr ||
4154 LogDebug(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4161 CNodeState *nodestate =
State(pfrom.
GetId());
4171 if (!BlockRequestAllowed(pindex)) {
4172 LogDebug(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4185 std::vector<CBlock> vHeaders;
4186 int nLimit = m_opts.max_headers_result;
4187 LogDebug(
BCLog::NET,
"getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), pfrom.
GetId());
4190 vHeaders.emplace_back(pindex->GetBlockHeader());
4191 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4206 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4212 if (RejectIncomingTxs(pfrom)) {
4227 const uint256& txid = ptx->GetHash();
4228 const uint256& wtxid = ptx->GetWitnessHash();
4230 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4231 AddKnownTx(*peer, hash);
4235 const auto& [should_validate, package_to_validate] = m_txdownloadman.ReceivedTx(pfrom.
GetId(), ptx);
4236 if (!should_validate) {
4242 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4245 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4251 if (package_to_validate) {
4254 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4255 ProcessPackageResult(package_to_validate.value(), package_result);
4261 Assume(!package_to_validate.has_value());
4267 ProcessValidTx(pfrom.
GetId(), ptx,
result.m_replaced_transactions);
4271 if (
auto package_to_validate{ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true)}) {
4274 package_result.
m_state.
IsValid() ?
"package accepted" :
"package rejected");
4275 ProcessPackageResult(package_to_validate.value(), package_result);
4291 vRecv >> cmpctblock;
4293 bool received_new_header =
false;
4303 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4313 received_new_header =
true;
4321 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4326 if (received_new_header) {
4327 LogInfo(
"Saw new cmpctblock header hash=%s peer=%d\n",
4328 blockhash.ToString(), pfrom.
GetId());
4331 bool fProcessBLOCKTXN =
false;
4335 bool fRevertToHeaderProcessing =
false;
4339 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4340 bool fBlockReconstructed =
false;
4348 CNodeState *nodestate =
State(pfrom.
GetId());
4353 nodestate->m_last_block_announcement =
GetTime();
4359 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4360 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4361 bool requested_block_from_this_peer{
false};
4364 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4366 while (range_flight.first != range_flight.second) {
4367 if (range_flight.first->second.first == pfrom.
GetId()) {
4368 requested_block_from_this_peer =
true;
4371 range_flight.first++;
4376 if (requested_block_from_this_peer) {
4379 std::vector<CInv> vInv(1);
4380 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4387 if (!already_in_flight && !CanDirectFetch()) {
4395 requested_block_from_this_peer) {
4396 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4397 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4398 if (!(*queuedBlockIt)->partialBlock)
4411 Misbehaving(*peer,
"invalid compact block");
4414 if (first_in_flight) {
4416 std::vector<CInv> vInv(1);
4417 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4427 for (
size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {
4432 fProcessBLOCKTXN =
true;
4433 }
else if (first_in_flight) {
4440 IsBlockRequestedFromOutbound(blockhash) ||
4459 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4464 std::vector<CTransactionRef> dummy;
4465 status = tempBlock.FillBlock(*pblock, dummy);
4467 fBlockReconstructed =
true;
4471 if (requested_block_from_this_peer) {
4474 std::vector<CInv> vInv(1);
4475 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4480 fRevertToHeaderProcessing =
true;
4485 if (fProcessBLOCKTXN) {
4488 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4491 if (fRevertToHeaderProcessing) {
4497 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.header},
true);
4500 if (fBlockReconstructed) {
4505 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4516 ProcessBlock(pfrom, pblock,
true,
true);
4523 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4540 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4551 std::vector<CBlockHeader> headers;
4555 if (nCount > m_opts.max_headers_result) {
4556 Misbehaving(*peer,
strprintf(
"headers message size = %u", nCount));
4559 headers.resize(nCount);
4560 for (
unsigned int n = 0; n < nCount; n++) {
4561 vRecv >> headers[n];
4565 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4569 if (m_headers_presync_should_signal.exchange(
false)) {
4570 HeadersPresyncStats stats;
4572 LOCK(m_headers_presync_mutex);
4573 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4574 if (it != m_headers_presync_stats.end()) stats = it->second;
4592 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4603 Misbehaving(*peer,
"mutated block");
4608 bool forceProcessing =
false;
4609 const uint256 hash(pblock->GetHash());
4610 bool min_pow_checked =
false;
4615 forceProcessing = IsBlockRequested(hash);
4616 RemoveBlockRequest(hash, pfrom.
GetId());
4620 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4624 min_pow_checked =
true;
4627 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4644 Assume(SetupAddressRelay(pfrom, *peer));
4648 if (peer->m_getaddr_recvd) {
4652 peer->m_getaddr_recvd =
true;
4654 peer->m_addrs_to_send.clear();
4655 std::vector<CAddress> vAddr;
4661 for (
const CAddress &addr : vAddr) {
4662 PushAddress(*peer, addr);
4690 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4691 LOCK(tx_relay->m_tx_inventory_mutex);
4692 tx_relay->m_send_mempool =
true;
4718 const auto ping_end = time_received;
4721 bool bPingFinished =
false;
4722 std::string sProblem;
4724 if (nAvail >=
sizeof(
nonce)) {
4728 if (peer->m_ping_nonce_sent != 0) {
4729 if (
nonce == peer->m_ping_nonce_sent) {
4731 bPingFinished =
true;
4732 const auto ping_time = ping_end - peer->m_ping_start.load();
4733 if (ping_time.count() >= 0) {
4738 sProblem =
"Timing mishap";
4742 sProblem =
"Nonce mismatch";
4745 bPingFinished =
true;
4746 sProblem =
"Nonce zero";
4750 sProblem =
"Unsolicited pong without ping";
4754 bPingFinished =
true;
4755 sProblem =
"Short payload";
4758 if (!(sProblem.empty())) {
4762 peer->m_ping_nonce_sent,
4766 if (bPingFinished) {
4767 peer->m_ping_nonce_sent = 0;
4781 if (!filter.IsWithinSizeConstraints())
4784 Misbehaving(*peer,
"too-large bloom filter");
4785 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4787 LOCK(tx_relay->m_bloom_filter_mutex);
4788 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4789 tx_relay->m_relay_txs =
true;
4803 std::vector<unsigned char> vData;
4811 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4812 LOCK(tx_relay->m_bloom_filter_mutex);
4813 if (tx_relay->m_bloom_filter) {
4814 tx_relay->m_bloom_filter->insert(vData);
4820 Misbehaving(*peer,
"bad filteradd message");
4831 auto tx_relay = peer->GetTxRelay();
4832 if (!tx_relay)
return;
4835 LOCK(tx_relay->m_bloom_filter_mutex);
4836 tx_relay->m_bloom_filter =
nullptr;
4837 tx_relay->m_relay_txs =
true;
4846 vRecv >> newFeeFilter;
4848 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4849 tx_relay->m_fee_filter_received = newFeeFilter;
4857 ProcessGetCFilters(pfrom, *peer, vRecv);
4862 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4867 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4872 std::vector<CInv> vInv;
4874 std::vector<uint256> tx_invs;
4876 for (
CInv &inv : vInv) {
4878 tx_invs.emplace_back(inv.
hash);
4882 LOCK(m_tx_download_mutex);
4883 m_txdownloadman.ReceivedNotFound(pfrom.
GetId(), tx_invs);
4892 bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4895 LOCK(peer.m_misbehavior_mutex);
4898 if (!peer.m_should_discourage)
return false;
4900 peer.m_should_discourage =
false;
4905 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
4911 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
4931 bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4936 PeerRef peer = GetPeerRef(pfrom->
GetId());
4937 if (peer ==
nullptr)
return false;
4941 if (!pfrom->
IsInboundConn() && !peer->m_outbound_version_message_sent)
return false;
4944 LOCK(peer->m_getdata_requests_mutex);
4945 if (!peer->m_getdata_requests.empty()) {
4946 ProcessGetData(*pfrom, *peer, interruptMsgProc);
4950 const bool processed_orphan = ProcessOrphanTx(*peer);
4955 if (processed_orphan)
return true;
4960 LOCK(peer->m_getdata_requests_mutex);
4961 if (!peer->m_getdata_requests.empty())
return true;
4974 bool fMoreWork = poll_result->second;
4985 if (m_opts.capture_messages) {
4990 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
4991 if (interruptMsgProc)
return false;
4993 LOCK(peer->m_getdata_requests_mutex);
4994 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5001 LOCK(m_tx_download_mutex);
5002 if (m_txdownloadman.HaveMoreWork(peer->m_id)) fMoreWork =
true;
5003 }
catch (
const std::exception& e) {
5012 void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5025 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5027 if (state.m_chain_sync.m_timeout != 0
s) {
5028 state.m_chain_sync.m_timeout = 0
s;
5029 state.m_chain_sync.m_work_header =
nullptr;
5030 state.m_chain_sync.m_sent_getheaders =
false;
5032 }
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)) {
5040 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5041 state.m_chain_sync.m_sent_getheaders =
false;
5042 }
else if (state.m_chain_sync.m_timeout > 0
s && time_in_seconds > state.m_chain_sync.m_timeout) {
5046 if (state.m_chain_sync.m_sent_getheaders) {
5048 LogInfo(
"Outbound peer has old chain, best known block = %s, %s\n", state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", pto.
DisconnectMsg(
fLogIPs));
5051 assert(state.m_chain_sync.m_work_header);
5056 MaybeSendGetHeaders(pto,
5057 GetLocator(state.m_chain_sync.m_work_header->pprev),
5059 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());
5060 state.m_chain_sync.m_sent_getheaders =
true;
5072 void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5081 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5085 if (pnode->
GetId() > youngest_peer.first) {
5086 next_youngest_peer = youngest_peer;
5087 youngest_peer.first = pnode->
GetId();
5091 NodeId to_disconnect = youngest_peer.first;
5092 if (youngest_peer.second > next_youngest_peer.second) {
5095 to_disconnect = next_youngest_peer.first;
5104 CNodeState *node_state =
State(pnode->
GetId());
5105 if (node_state ==
nullptr ||
5108 LogDebug(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5112 LogDebug(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5128 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5137 if (state ==
nullptr)
return;
5139 if (state->m_chain_sync.m_protect)
return;
5143 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->
GetId() > worst_peer)) {
5144 worst_peer = pnode->
GetId();
5145 oldest_block_announcement = state->m_last_block_announcement;
5148 if (worst_peer != -1) {
5159 LogDebug(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5163 LogDebug(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5180 void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5184 auto now{GetTime<std::chrono::seconds>()};
5186 EvictExtraOutboundPeers(now);
5188 if (now > m_stale_tip_check_time) {
5192 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5201 if (!m_initial_sync_finished && CanDirectFetch()) {
5203 m_initial_sync_finished =
true;
5207 void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5210 peer.m_ping_nonce_sent &&
5220 bool pingSend =
false;
5222 if (peer.m_ping_queued) {
5227 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5236 }
while (
nonce == 0);
5237 peer.m_ping_queued =
false;
5238 peer.m_ping_start = now;
5240 peer.m_ping_nonce_sent =
nonce;
5244 peer.m_ping_nonce_sent = 0;
5250 void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5253 if (!peer.m_addr_relay_enabled)
return;
5255 LOCK(peer.m_addr_send_times_mutex);
5258 peer.m_next_local_addr_send < current_time) {
5265 if (peer.m_next_local_addr_send != 0us) {
5266 peer.m_addr_known->reset();
5269 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5270 PushAddress(peer, local_addr);
5276 if (current_time <= peer.m_next_addr_send)
return;
5289 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5290 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5293 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5294 peer.m_addrs_to_send.end());
5297 if (peer.m_addrs_to_send.empty())
return;
5299 if (peer.m_wants_addrv2) {
5304 peer.m_addrs_to_send.clear();
5307 if (peer.m_addrs_to_send.capacity() > 40) {
5308 peer.m_addrs_to_send.shrink_to_fit();
5312 void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5320 CNodeState &state = *
State(
node.GetId());
5321 if (state.pindexBestKnownBlock !=
nullptr &&
5328 peer.m_sent_sendheaders =
true;
5333 void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5335 if (m_opts.ignore_incoming_txs)
return;
5351 if (peer.m_fee_filter_sent == MAX_FILTER) {
5354 peer.m_next_send_feefilter = 0us;
5357 if (current_time > peer.m_next_send_feefilter) {
5358 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5361 if (filterToSend != peer.m_fee_filter_sent) {
5363 peer.m_fee_filter_sent = filterToSend;
5370 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5376 class CompareInvMempoolOrder
5381 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5384 m_wtxid_relay = use_wtxid;
5387 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5391 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5396 bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const 5406 bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5411 if (
node.IsBlockOnlyConn())
return false;
5413 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5417 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5423 bool PeerManagerImpl::SendMessages(
CNode* pto)
5428 PeerRef peer = GetPeerRef(pto->
GetId());
5429 if (!peer)
return false;
5434 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5437 if (!pto->
IsInboundConn() && !peer->m_outbound_version_message_sent) {
5438 PushNodeVersion(*pto, *peer);
5439 peer->m_outbound_version_message_sent =
true;
5446 const auto current_time{GetTime<std::chrono::microseconds>()};
5454 MaybeSendPing(*pto, *peer, current_time);
5459 MaybeSendAddr(*pto, *peer, current_time);
5461 MaybeSendSendHeaders(*pto, *peer);
5469 if (m_chainman.m_best_header ==
nullptr) {
5476 bool sync_blocks_and_headers_from_peer =
false;
5477 if (state.fPreferredDownload) {
5478 sync_blocks_and_headers_from_peer =
true;
5489 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5490 sync_blocks_and_headers_from_peer =
true;
5496 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5497 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5505 if (pindexStart->
pprev)
5506 pindexStart = pindexStart->
pprev;
5507 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5510 state.fSyncStarted =
true;
5534 LOCK(peer->m_block_inv_mutex);
5535 std::vector<CBlock> vHeaders;
5536 bool fRevertToInv = ((!peer->m_prefers_headers &&
5537 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5540 ProcessBlockAvailability(pto->
GetId());
5542 if (!fRevertToInv) {
5543 bool fFoundStartingHeader =
false;
5547 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5552 fRevertToInv =
true;
5555 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5567 fRevertToInv =
true;
5570 pBestIndex = pindex;
5571 if (fFoundStartingHeader) {
5574 }
else if (PeerHasHeader(&state, pindex)) {
5576 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5579 fFoundStartingHeader =
true;
5584 fRevertToInv =
true;
5589 if (!fRevertToInv && !vHeaders.empty()) {
5590 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5594 vHeaders.front().GetHash().ToString(), pto->
GetId());
5596 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5598 LOCK(m_most_recent_block_mutex);
5599 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5603 if (cached_cmpctblock_msg.has_value()) {
5604 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5612 state.pindexBestHeaderSent = pBestIndex;
5613 }
else if (peer->m_prefers_headers) {
5614 if (vHeaders.size() > 1) {
5617 vHeaders.front().GetHash().ToString(),
5618 vHeaders.back().GetHash().ToString(), pto->
GetId());
5621 vHeaders.front().GetHash().ToString(), pto->
GetId());
5624 state.pindexBestHeaderSent = pBestIndex;
5626 fRevertToInv =
true;
5632 if (!peer->m_blocks_for_headers_relay.empty()) {
5633 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5646 if (!PeerHasHeader(&state, pindex)) {
5647 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5653 peer->m_blocks_for_headers_relay.clear();
5659 std::vector<CInv> vInv;
5661 LOCK(peer->m_block_inv_mutex);
5665 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5672 peer->m_blocks_for_inv_relay.clear();
5675 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5676 LOCK(tx_relay->m_tx_inventory_mutex);
5679 if (tx_relay->m_next_inv_send_time < current_time) {
5680 fSendTrickle =
true;
5690 LOCK(tx_relay->m_bloom_filter_mutex);
5691 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5695 if (fSendTrickle && tx_relay->m_send_mempool) {
5696 auto vtxinfo = m_mempool.
infoAll();
5697 tx_relay->m_send_mempool =
false;
5698 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5700 LOCK(tx_relay->m_bloom_filter_mutex);
5702 for (
const auto& txinfo : vtxinfo) {
5705 peer->m_wtxid_relay ?
5706 txinfo.tx->GetWitnessHash().ToUint256() :
5707 txinfo.tx->GetHash().ToUint256(),
5709 tx_relay->m_tx_inventory_to_send.erase(inv.
hash);
5712 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5715 if (tx_relay->m_bloom_filter) {
5716 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5718 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5719 vInv.push_back(inv);
5730 std::vector<std::set<uint256>::iterator> vInvTx;
5731 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5732 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5733 vInvTx.push_back(it);
5735 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5738 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
5739 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5742 unsigned int nRelayedTransactions = 0;
5743 LOCK(tx_relay->m_bloom_filter_mutex);
5746 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5748 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5749 std::set<uint256>::iterator it = vInvTx.back();
5754 tx_relay->m_tx_inventory_to_send.erase(it);
5756 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
5765 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5768 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5770 vInv.push_back(inv);
5771 nRelayedTransactions++;
5776 tx_relay->m_tx_inventory_known_filter.insert(hash);
5781 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5788 auto stalling_timeout = m_block_stalling_timeout.load();
5789 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5798 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5808 if (state.vBlocksInFlight.size() > 0) {
5809 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5810 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5818 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5820 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5821 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5838 state.fSyncStarted =
false;
5840 peer->m_headers_sync_timeout = 0us;
5846 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5852 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5857 std::vector<CInv> vGetData;
5859 std::vector<const CBlockIndex*> vToDownload;
5861 auto get_inflight_budget = [&state]() {
5867 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5872 TryDownloadingHistoricalBlocks(
5874 get_inflight_budget(),
5875 vToDownload, from_tip,
5876 Assert(m_chainman.GetSnapshotBaseBlock()));
5879 uint32_t nFetchFlags = GetFetchFlags(*peer);
5881 BlockRequested(pto->
GetId(), *pindex);
5885 if (state.vBlocksInFlight.empty() && staller != -1) {
5886 if (
State(staller)->m_stalling_since == 0us) {
5887 State(staller)->m_stalling_since = current_time;
5897 LOCK(m_tx_download_mutex);
5898 for (
const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->
GetId(), current_time)) {
5907 if (!vGetData.empty())
5910 MaybeSendFeefilter(*pto, *peer, current_time);
std::shared_ptr< const CTransaction > CTransactionRef
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
enum ReadStatus_t ReadStatus
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
constexpr const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
std::atomic_bool fPauseSend
invalid by consensus rules
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
std::chrono::time_point< NodeClock > time_point
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 unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
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.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
ServiceFlags
nServices flags
bool ReadRawBlock(std::vector< uint8_t > &block, const FlatFilePos &pos) const
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...
bool IsPruneMode() const
Whether running in -prune mode.
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.
int64_t GetBlockTime() const
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
std::vector< TxMempoolInfo > infoAll() const
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
uint64_t m_addr_rate_limited
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...
Valid, transaction was already in the mempool.
std::string ToString() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
bool exists(const GenTxid >xid) const
ReconciliationRegisterResult
We don't have the previous block the checked one is built on.
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
std::vector< uint16_t > indexes
bool IsOutboundOrBlockRelayConn() const
static const int WTXID_RELAY_VERSION
"wtxidrelay" command for wtxid-based relay starts with this version
bool IsMsgFilteredBlk() const
An in-memory indexed chain of blocks.
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
Manages warning messages within a node.
size_t DynamicMemoryUsage() const
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
transaction was not validated because package failed
invalid proof of work or time too old
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
constexpr const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
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 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...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
transaction was missing some of its inputs
bool IsMsgCmpctBlk() const
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return all or many randomly selected addresses, optionally by network.
bool IsFeelerConn() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
bool MoneyRange(const CAmount &nValue)
CBlockHeader GetBlockHeader() const
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
int Height() const
Return the maximal height in the chain.
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
static constexpr SerParams V2_NETWORK
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
unsigned long size() const
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid...
void SetCommonVersion(int greatest_common_version)
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
constexpr const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
bool ReadBlock(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set. ...
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
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...
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
violated mempool's fee/size/descendant/RBF/etc limits
the block header may be on a too-little-work chain
inputs (covered by txid) failed policy rules
void SetTryNewOutboundPeer(bool flag)
void ignore(size_t num_ignore)
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message...
uint64_t GetLocalNonce() const
bool SeenLocal(const CService &addr)
vote for a local address
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
transaction spends a coinbase too early, or violates locktime/sequence locks
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
bool MultipleManualOrFullOutboundConns(Network net) const EXCLUSIVE_LOCKS_REQUIRED(m_nodes_mutex)
State
The various states a (txhash,peer) pair can be in.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
initial value. Tx has not yet been rejected
bool GetTryNewOutboundPeer() const
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
enum Network GetNetwork() const
std::string ToStringAddrPort() const
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
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...
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
Stochastic address manager.
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
Transaction validation functions.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version ...
Functions to serialize / deserialize common bitcoin types.
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 DisconnectNode(const std::string &node)
std::function< void(const CAddress &addr, const std::string &msg_type, Span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
int GetExtraBlockRelayCount() const
int64_t CAmount
Amount in satoshis (Can be negative)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
uint256 GetBlockHash() const
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
std::chrono::seconds median_outbound_time_offset
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
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).
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
initial value. Block has not yet been rejected
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends...
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
CAmount m_fee_filter_received
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
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.
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
uint64_t m_addr_processed
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
const bool m_preferred
Whether this peer is preferred for transaction download.
constexpr const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
std::vector< CTransactionRef > txn
this block was cached as being invalid and we didn't store the reason why
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
Validation result for package mempool acceptance.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
void StartExtraBlockRelayPeers()
Double ended buffer combining vector and stream-like interfaces.
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter...
std::string ToString() const
the block failed to meet one of our checkpoints
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
A combination of a network address (CNetAddr) and a (TCP) port.
Transport protocol agnostic message container.
int64_t nPowTargetSpacing
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...
constexpr int64_t count_microseconds(std::chrono::microseconds t)
static constexpr SerParams V1
bool IsProxy(const CNetAddr &addr)
bool LoadingBlocks() const
bool IsManualConn() const
int GetExtraFullOutboundCount() const
A CService with information about it as peer.
std::string ToString() const
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
std::vector< unsigned char > GetKey() const
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
static const int PROTOCOL_VERSION
network protocol versioning
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks...
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
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 ExpectServicesFromConn() const
bool GetNetworkActive() const
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) ...
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
std::string ToString() const
constexpr const char * BLOCK
The block message transmits a single serialized block.
std::atomic< bool > m_bip152_highbandwidth_to
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
std::vector< uint256 > vHave
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
TRACEPOINT_SEMAPHORE(net, inbound_message)
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
Parameters that influence chain consensus.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::atomic_bool fDisconnect
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
CFeeRate GetMinFee(size_t sizelimit) const
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...
constexpr bool IsNull() const
bool IsMsgWitnessBlk() const
fails some policy, but might be acceptable if submitted in a (different) package
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
Validation result for a transaction evaluated by MemPoolAccept (single or package).
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define Assume(val)
Assume is the identity function.
256-bit unsigned big integer.
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB...
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< CTransactionRef > &extra_txn)
std::chrono::seconds PowTargetSpacing() const
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::microseconds m_ping_wait
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
bool CheckIncomingNonce(uint64_t nonce)
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
bool IsBlockOnlyConn() const
Transaction is missing a witness.
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids"...
PackageValidationState m_state
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
ServiceFlags their_services
invalid by consensus rules (excluding any below reasons)
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static time_point now() noexcept
Return current system time or mocked time, if set.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
const arith_uint256 & MinimumChainWork() const
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::vector< CTransactionRef > vtx
std::chrono::seconds time_offset
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 * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
the block's data didn't match the data committed to by the PoW
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
#define LogDebug(category,...)
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
#define LOCKS_EXCLUDED(...)
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
std::set< uint256 > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
uint32_t GetMappedAS(const CNetAddr &addr) const
std::vector< std::pair< unsigned int, uint256 > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
The block chain is a tree shaped structure starting with the genesis block at the root...
const CChainParams & Params()
Return the currently selected parameters.
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch? Larger windows tolerate larger download speed differences between peer, but increase the potential degree of disordering of blocks on disk (which make reindexing and pruning harder).
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
#define TRACEPOINT(context,...)
bool IsTxAvailable(size_t index) const
A block this one builds on is invalid.
TxMempoolInfo info(const GenTxid >xid) const
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
#define ACQUIRED_BEFORE(...)
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network) ...
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.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
#define LIMITED_STRING(obj, n)
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span
Like the Span constructor, but for (const) unsigned char member types only.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
#define AssertLockNotHeld(cs)
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
std::vector< NodeId > m_senders
std::atomic< int > nVersion
const CBlockIndex * GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The tip of the background sync chain.
std::string ConnectionTypeAsString() const
static size_t RecursiveDynamicUsage(const CScript &script)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
std::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
this node does not have a mempool so can't validate the transaction
CTransactionRef get(const uint256 &hash) const
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
block timestamp was > 2 hours in the future (or our clock is bad)
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
std::atomic< bool > m_bip152_highbandwidth_from
constexpr const char * TX
The tx message transmits a single transaction.
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
bool IsAddrFetchConn() const
arith_uint256 GetBlockProof(const CBlockIndex &block)
A Span is an object that can refer to a contiguous sequence of objects.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
The basic transaction that is broadcasted on the network and contained in blocks. ...
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
Information about a peer.
const Consensus::Params & GetConsensus() const
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict...
std::vector< int > vHeightInFlight
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...
void ForEachNode(const NodeFn &func)
Simple class for background tasks that should be run periodically or once "after a while"...
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
full block available in blk*.dat
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.
static constexpr SerParams V1_NETWORK
int64_t GetTime()
DEPRECATED, see GetTime.
int GetCommonVersion() const
const std::string m_addr_name
uint64_t rand64() noexcept
Generate a random 64-bit integer.
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
bool HasPermission(NetPermissionFlags permission) const
std::string ToString() const
bool IsInboundConn() const
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay...
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.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
otherwise didn't meet our local policy rules
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
A generic txid reference (txid or wtxid).
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
bool GetUseAddrmanOutgoing() const
constexpr const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
bool m_addr_relay_enabled
unsigned int nTx
Number of transactions in this block.
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
static GenTxid Txid(const uint256 &hash)
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
std::string ToString(const T &t)
Locale-independent version of std::to_string.
const uint256 & GetHash() const LIFETIMEBOUND
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
bool IsFullOutboundConn() const
#define Assert(val)
Identity function.
const Txid & GetHash() const LIFETIMEBOUND
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...
static constexpr TransactionSerParams TX_WITH_WITNESS
static constexpr TransactionSerParams TX_NO_WITNESS
ReachableNets g_reachable_nets
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.