186 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
220 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
223 Mutex m_misbehavior_mutex;
225 int m_misbehavior_score
GUARDED_BY(m_misbehavior_mutex){0};
227 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
230 Mutex m_block_inv_mutex;
234 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
238 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
246 std::atomic<int> m_starting_height{-1};
249 std::atomic<uint64_t> m_ping_nonce_sent{0};
251 std::atomic<std::chrono::microseconds> m_ping_start{0us};
253 std::atomic<bool> m_ping_queued{
false};
256 std::atomic<bool> m_wtxid_relay{
false};
268 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
270 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
281 std::set<uint256> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
285 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
288 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
294 std::atomic<CAmount> m_fee_filter_received{0};
300 LOCK(m_tx_relay_mutex);
302 m_tx_relay = std::make_unique<Peer::TxRelay>();
303 return m_tx_relay.get();
308 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
337 std::atomic_bool m_addr_relay_enabled{
false};
341 mutable Mutex m_addr_send_times_mutex;
343 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
345 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
348 std::atomic_bool m_wants_addrv2{
false};
357 std::atomic<uint64_t> m_addr_rate_limited{0};
359 std::atomic<uint64_t> m_addr_processed{0};
365 Mutex m_getdata_requests_mutex;
367 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
373 Mutex m_headers_sync_mutex;
376 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
379 std::atomic<bool> m_sent_sendheaders{
false};
392 , m_our_services{our_services}
396 mutable Mutex m_tx_relay_mutex;
399 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
402 using PeerRef = std::shared_ptr<Peer>;
414 uint256 hashLastUnknownBlock{};
420 bool fSyncStarted{
false};
422 std::chrono::microseconds m_stalling_since{0us};
423 std::list<QueuedBlock> vBlocksInFlight;
425 std::chrono::microseconds m_downloading_since{0us};
427 bool fPreferredDownload{
false};
429 bool m_requested_hb_cmpctblocks{
false};
431 bool m_provides_cmpctblocks{
false};
457 struct ChainSyncTimeoutState {
459 std::chrono::seconds m_timeout{0s};
463 bool m_sent_getheaders{
false};
465 bool m_protect{
false};
468 ChainSyncTimeoutState m_chain_sync;
471 int64_t m_last_block_announcement{0};
474 const bool m_is_inbound;
476 CNodeState(
bool is_inbound) : m_is_inbound(is_inbound) {}
502 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex);
504 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, g_msgproc_mutex);
515 void SetBestHeight(
int height)
override { m_best_height = height; };
518 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override 519 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex);
544 void Misbehaving(Peer& peer,
int howmuch,
const std::string& message);
557 bool via_compact_block,
const std::string& message =
"")
574 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
587 bool ProcessOrphanTx(Peer& peer)
597 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
599 bool via_compact_block)
611 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
630 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
644 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
659 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
661 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
669 void AddTxAnnouncement(const
CNode&
node, const
GenTxid& gtxid,
std::chrono::microseconds current_time)
673 void PushNodeVersion(
CNode& pnode, const Peer& peer);
679 void MaybeSendPing(
CNode& node_to, Peer& peer,
std::chrono::microseconds now);
714 std::atomic<
int> m_best_height{-1};
719 const Options m_opts;
721 bool RejectIncomingTxs(
const CNode& peer)
const;
729 mutable Mutex m_peer_mutex;
736 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
746 uint32_t GetFetchFlags(
const Peer& peer)
const;
748 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
765 std::atomic<int> m_wtxid_relay_peers{0};
776 bool AlreadyHaveTx(
const GenTxid& gtxid)
831 Mutex m_recent_confirmed_transactions_mutex;
840 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
841 std::chrono::seconds average_interval);
845 Mutex m_most_recent_block_mutex;
846 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
847 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
849 std::unique_ptr<const std::map<uint256, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
853 Mutex m_headers_presync_mutex;
861 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
863 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
867 std::atomic_bool m_headers_presync_should_signal{
false};
937 std::atomic<
std::chrono::seconds> m_last_tip_update{0s};
943 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
948 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
976 std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
978 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
994 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1012 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1014 const
uint256& stop_hash, uint32_t max_height_diff,
1065 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1066 if (it == m_node_states.end())
1073 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1081 static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1086 void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1088 assert(peer.m_addr_known);
1089 peer.m_addr_known->insert(addr.
GetKey());
1092 void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1097 assert(peer.m_addr_known);
1098 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1100 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1102 peer.m_addrs_to_send.push_back(addr);
1107 static void AddKnownTx(Peer& peer,
const uint256& hash)
1109 auto tx_relay = peer.GetTxRelay();
1110 if (!tx_relay)
return;
1112 LOCK(tx_relay->m_tx_inventory_mutex);
1113 tx_relay->m_tx_inventory_known_filter.insert(hash);
1117 static bool CanServeBlocks(
const Peer& peer)
1124 static bool IsLimitedPeer(
const Peer& peer)
1131 static bool CanServeWitnesses(
const Peer& peer)
1136 std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1137 std::chrono::seconds average_interval)
1139 if (m_next_inv_to_inbounds.load() < now) {
1145 return m_next_inv_to_inbounds;
1148 bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1150 return mapBlocksInFlight.count(hash);
1153 bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1155 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1156 auto [nodeid, block_it] = range.first->second;
1158 if (!nodestate.m_is_inbound)
return true;
1164 void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1166 auto range = mapBlocksInFlight.equal_range(hash);
1167 if (range.first == range.second) {
1175 while (range.first != range.second) {
1176 auto [node_id, list_it] = range.first->second;
1178 if (from_peer && *from_peer != node_id) {
1185 if (state.vBlocksInFlight.begin() == list_it) {
1187 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1189 state.vBlocksInFlight.erase(list_it);
1191 if (state.vBlocksInFlight.empty()) {
1193 m_peers_downloading_from--;
1195 state.m_stalling_since = 0us;
1197 range.first = mapBlocksInFlight.erase(range.first);
1201 bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1205 CNodeState *state =
State(nodeid);
1206 assert(state !=
nullptr);
1211 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1212 if (range.first->second.first == nodeid) {
1214 *pit = &range.first->second.second;
1221 RemoveBlockRequest(hash, nodeid);
1223 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1225 if (state->vBlocksInFlight.size() == 1) {
1227 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1228 m_peers_downloading_from++;
1230 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1232 *pit = &itInFlight->second.second;
1237 void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1244 if (m_opts.ignore_incoming_txs)
return;
1246 CNodeState* nodestate =
State(nodeid);
1247 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1252 int num_outbound_hb_peers = 0;
1253 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1254 if (*it == nodeid) {
1255 lNodesAnnouncingHeaderAndIDs.erase(it);
1256 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1259 CNodeState *state =
State(*it);
1260 if (state !=
nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
1262 if (nodestate->m_is_inbound) {
1265 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1266 CNodeState *remove_node =
State(lNodesAnnouncingHeaderAndIDs.front());
1267 if (remove_node !=
nullptr && !remove_node->m_is_inbound) {
1270 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1276 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1279 m_connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1282 pnodeStop->m_bip152_highbandwidth_to =
false;
1285 lNodesAnnouncingHeaderAndIDs.pop_front();
1290 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1295 bool PeerManagerImpl::TipMayBeStale()
1299 if (m_last_tip_update.load() == 0s) {
1300 m_last_tip_update = GetTime<std::chrono::seconds>();
1302 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1305 bool PeerManagerImpl::CanDirectFetch()
1307 return m_chainman.ActiveChain().Tip()->Time() >
GetAdjustedTime() - m_chainparams.GetConsensus().PowTargetSpacing() * 20;
1312 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1314 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1319 void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1320 CNodeState *state =
State(nodeid);
1321 assert(state !=
nullptr);
1323 if (!state->hashLastUnknownBlock.IsNull()) {
1324 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock);
1326 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1327 state->pindexBestKnownBlock = pindex;
1329 state->hashLastUnknownBlock.SetNull();
1334 void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1335 CNodeState *state =
State(nodeid);
1336 assert(state !=
nullptr);
1338 ProcessBlockAvailability(nodeid);
1340 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
1343 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1344 state->pindexBestKnownBlock = pindex;
1348 state->hashLastUnknownBlock = hash;
1353 void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1358 vBlocks.reserve(vBlocks.size() +
count);
1359 CNodeState *state =
State(peer.m_id);
1360 assert(state !=
nullptr);
1363 ProcessBlockAvailability(peer.m_id);
1365 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.ActiveChain().Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.MinimumChainWork()) {
1370 if (state->pindexLastCommonBlock ==
nullptr) {
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);
1425 while (pindexWalk->
nHeight < nMaxHeight) {
1429 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1430 vToFetch.resize(nToFetch);
1431 pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->
nHeight + nToFetch);
1432 vToFetch[nToFetch - 1] = pindexWalk;
1433 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1434 vToFetch[i - 1] = vToFetch[i]->
pprev;
1452 state->pindexLastCommonBlock = pindex;
1453 }
else if (!IsBlockRequested(pindex->
GetBlockHash())) {
1455 if (pindex->
nHeight > nWindowEnd) {
1457 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1459 if (nodeStaller) *nodeStaller = waitingfor;
1463 vBlocks.push_back(pindex);
1464 if (vBlocks.size() ==
count) {
1467 }
else if (waitingfor == -1) {
1469 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1477 void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1479 uint64_t my_services{peer.m_our_services};
1480 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1482 const int nNodeStartingHeight{m_best_height};
1489 const bool tx_relay{!RejectIncomingTxs(pnode)};
1496 LogPrint(
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);
1502 void PeerManagerImpl::AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
1510 const CNodeState* state =
State(nodeid);
1520 const bool preferred = state->fPreferredDownload;
1526 m_txrequest.ReceivedInv(nodeid, gtxid, preferred, current_time + delay);
1529 void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1533 if (state) state->m_last_block_announcement = time_in_seconds;
1541 m_node_states.emplace_hint(m_node_states.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(
node.IsInboundConn()));
1542 assert(m_txrequest.Count(nodeid) == 0);
1544 PeerRef peer = std::make_shared<Peer>(nodeid, our_services);
1547 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1549 if (!
node.IsInboundConn()) {
1550 PushNodeVersion(
node, *peer);
1554 void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1556 std::set<uint256> unbroadcast_txids = m_mempool.GetUnbroadcastTxs();
1558 for (
const auto& txid : unbroadcast_txids) {
1561 if (tx !=
nullptr) {
1564 m_mempool.RemoveUnbroadcastTx(txid,
true);
1570 const std::chrono::milliseconds delta = 10min +
GetRandMillis(5min);
1571 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1574 void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1586 PeerRef peer = RemovePeer(nodeid);
1588 misbehavior =
WITH_LOCK(peer->m_misbehavior_mutex,
return peer->m_misbehavior_score);
1589 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1590 assert(m_wtxid_relay_peers >= 0);
1592 CNodeState *state =
State(nodeid);
1593 assert(state !=
nullptr);
1595 if (state->fSyncStarted)
1598 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1599 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1600 while (range.first != range.second) {
1601 auto [node_id, list_it] = range.first->second;
1602 if (node_id != nodeid) {
1605 range.first = mapBlocksInFlight.erase(range.first);
1610 m_txrequest.DisconnectedPeer(nodeid);
1611 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1612 m_num_preferred_download_peers -= state->fPreferredDownload;
1613 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1614 assert(m_peers_downloading_from >= 0);
1615 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1616 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1618 m_node_states.erase(nodeid);
1620 if (m_node_states.empty()) {
1622 assert(mapBlocksInFlight.empty());
1623 assert(m_num_preferred_download_peers == 0);
1624 assert(m_peers_downloading_from == 0);
1625 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1626 assert(m_wtxid_relay_peers == 0);
1627 assert(m_txrequest.Size() == 0);
1631 if (
node.fSuccessfullyConnected && misbehavior == 0 &&
1632 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1636 m_addrman.Connected(
node.addr);
1639 LOCK(m_headers_presync_mutex);
1640 m_headers_presync_stats.erase(nodeid);
1645 PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const 1648 auto it = m_peer_map.find(
id);
1649 return it != m_peer_map.end() ? it->second :
nullptr;
1652 PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1656 auto it = m_peer_map.find(
id);
1657 if (it != m_peer_map.end()) {
1658 ret = std::move(it->second);
1659 m_peer_map.erase(it);
1668 const CNodeState* state =
State(nodeid);
1669 if (state ==
nullptr)
1671 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1672 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1673 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1679 PeerRef peer = GetPeerRef(nodeid);
1680 if (peer ==
nullptr)
return false;
1689 auto ping_wait{0us};
1690 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1691 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1694 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1707 LOCK(peer->m_headers_sync_mutex);
1708 if (peer->m_headers_sync) {
1716 void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1718 if (m_opts.max_extra_txs <= 0)
1720 if (!vExtraTxnForCompact.size())
1721 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1722 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1723 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1726 void PeerManagerImpl::Misbehaving(Peer& peer,
int howmuch,
const std::string& message)
1730 LOCK(peer.m_misbehavior_mutex);
1731 const int score_before{peer.m_misbehavior_score};
1732 peer.m_misbehavior_score += howmuch;
1733 const int score_now{peer.m_misbehavior_score};
1735 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1736 std::string warning;
1739 warning =
" DISCOURAGE THRESHOLD EXCEEDED";
1740 peer.m_should_discourage =
true;
1744 peer.m_id, score_before, score_now, warning, message_prefixed);
1748 bool via_compact_block,
const std::string& message)
1750 PeerRef peer{GetPeerRef(nodeid)};
1761 if (!via_compact_block) {
1762 if (peer) Misbehaving(*peer, 100, message);
1769 CNodeState *node_state =
State(nodeid);
1770 if (node_state ==
nullptr) {
1776 if (!via_compact_block && !node_state->m_is_inbound) {
1777 if (peer) Misbehaving(*peer, 100, message);
1785 if (peer) Misbehaving(*peer, 100, message);
1790 if (peer) Misbehaving(*peer, 10, message);
1796 if (message !=
"") {
1804 PeerRef peer{GetPeerRef(nodeid)};
1810 if (peer) Misbehaving(*peer, 100,
"");
1828 bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1831 if (m_chainman.ActiveChain().Contains(pindex))
return true;
1837 std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1839 if (m_chainman.m_blockman.LoadingBlocks())
return "Loading blocks ...";
1842 PeerRef peer = GetPeerRef(peer_id);
1843 if (peer ==
nullptr)
return "Peer does not exist";
1846 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1851 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1854 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1861 bool success = m_connman.ForNode(peer_id, [
this, &invs](
CNode*
node) {
1867 if (!success)
return "Peer not fully connected";
1871 return std::nullopt;
1878 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, opts);
1884 : m_rng{opts.deterministic_rng},
1886 m_chainparams(chainman.GetParams()),
1890 m_chainman(chainman),
1896 if (opts.reconcile_txs) {
1901 void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1911 const std::chrono::milliseconds delta = 10min +
GetRandMillis(5min);
1912 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1921 void PeerManagerImpl::BlockConnected(
1923 const std::shared_ptr<const CBlock>& pblock,
1928 m_last_tip_update = GetTime<std::chrono::seconds>();
1931 auto stalling_timeout = m_block_stalling_timeout.load();
1935 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1948 LOCK(m_recent_confirmed_transactions_mutex);
1949 for (
const auto& ptx : pblock->vtx) {
1950 m_recent_confirmed_transactions.insert(ptx->GetHash());
1951 if (ptx->GetHash() != ptx->GetWitnessHash()) {
1952 m_recent_confirmed_transactions.insert(ptx->GetWitnessHash());
1958 for (
const auto& ptx : pblock->vtx) {
1959 m_txrequest.ForgetTxHash(ptx->GetHash());
1960 m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
1965 void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1975 LOCK(m_recent_confirmed_transactions_mutex);
1976 m_recent_confirmed_transactions.reset();
1983 void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1985 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock);
1990 if (pindex->
nHeight <= m_highest_fast_announce)
1992 m_highest_fast_announce = pindex->
nHeight;
1996 uint256 hashBlock(pblock->GetHash());
1997 const std::shared_future<CSerializedNetMsg> lazy_ser{
2001 auto most_recent_block_txs = std::make_unique<std::map<uint256, CTransactionRef>>();
2002 for (
const auto& tx : pblock->vtx) {
2003 most_recent_block_txs->emplace(tx->GetHash(), tx);
2004 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2007 LOCK(m_most_recent_block_mutex);
2008 m_most_recent_block_hash = hashBlock;
2009 m_most_recent_block = pblock;
2010 m_most_recent_compact_block = pcmpctblock;
2011 m_most_recent_block_txs = std::move(most_recent_block_txs);
2019 ProcessBlockAvailability(pnode->
GetId());
2023 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2025 LogPrint(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2026 hashBlock.ToString(), pnode->
GetId());
2029 m_connman.PushMessage(pnode, ser_cmpctblock.Copy());
2030 state.pindexBestHeaderSent = pindex;
2039 void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2041 SetBestHeight(pindexNew->
nHeight);
2045 if (fInitialDownload)
return;
2048 std::vector<uint256> vHashes;
2050 while (pindexToAnnounce != pindexFork) {
2052 pindexToAnnounce = pindexToAnnounce->
pprev;
2062 for (
auto& it : m_peer_map) {
2063 Peer& peer = *it.second;
2064 LOCK(peer.m_block_inv_mutex);
2066 peer.m_blocks_for_headers_relay.push_back(hash);
2071 m_connman.WakeMessageHandler();
2083 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2088 it != mapBlockSource.end() &&
2089 State(it->second.first)) {
2090 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2099 !m_chainman.IsInitialBlockDownload() &&
2100 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2101 if (it != mapBlockSource.end()) {
2102 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2105 if (it != mapBlockSource.end())
2106 mapBlockSource.erase(it);
2115 bool PeerManagerImpl::AlreadyHaveTx(
const GenTxid& gtxid)
2117 if (m_chainman.ActiveChain().Tip()->GetBlockHash() != hashRecentRejectsChainTip) {
2122 hashRecentRejectsChainTip = m_chainman.ActiveChain().Tip()->GetBlockHash();
2123 m_recent_rejects.reset();
2128 if (m_orphanage.
HaveTx(gtxid))
return true;
2131 LOCK(m_recent_confirmed_transactions_mutex);
2132 if (m_recent_confirmed_transactions.contains(hash))
return true;
2135 return m_recent_rejects.contains(hash) || m_mempool.exists(gtxid);
2138 bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2140 return m_chainman.m_blockman.LookupBlockIndex(block_hash) !=
nullptr;
2143 void PeerManagerImpl::SendPings()
2146 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2149 void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2152 for(
auto& it : m_peer_map) {
2153 Peer& peer = *it.second;
2154 auto tx_relay = peer.GetTxRelay();
2155 if (!tx_relay)
continue;
2157 LOCK(tx_relay->m_tx_inventory_mutex);
2163 if (tx_relay->m_next_inv_send_time == 0s)
continue;
2165 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2166 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2167 tx_relay->m_tx_inventory_to_send.insert(hash);
2172 void PeerManagerImpl::RelayAddress(
NodeId originator,
2188 const auto current_time{GetTime<std::chrono::seconds>()};
2196 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2198 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2199 assert(nRelayNodes <= best.size());
2203 for (
auto& [
id, peer] : m_peer_map) {
2204 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2206 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2207 if (hashKey > best[i].first) {
2208 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2209 best[i] = std::make_pair(hashKey, peer.get());
2216 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2217 PushAddress(*best[i].second, addr);
2221 void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2223 std::shared_ptr<const CBlock> a_recent_block;
2224 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2226 LOCK(m_most_recent_block_mutex);
2227 a_recent_block = m_most_recent_block;
2228 a_recent_compact_block = m_most_recent_compact_block;
2231 bool need_activate_chain =
false;
2234 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.
hash);
2243 need_activate_chain =
true;
2247 if (need_activate_chain) {
2249 if (!m_chainman.ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2255 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.
hash);
2259 if (!BlockRequestAllowed(pindex)) {
2260 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2265 if (m_connman.OutboundTargetReached(
true) &&
2277 LogPrint(
BCLog::NET,
"Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.
GetId());
2287 std::shared_ptr<const CBlock> pblock;
2288 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2289 pblock = a_recent_block;
2293 std::vector<uint8_t> block_data;
2294 if (!m_chainman.m_blockman.ReadRawBlockFromDisk(block_data, pindex->
GetBlockPos())) {
2295 assert(!
"cannot load block from disk");
2301 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2302 if (!m_chainman.m_blockman.ReadBlockFromDisk(*pblockRead, *pindex)) {
2303 assert(!
"cannot load block from disk");
2305 pblock = pblockRead;
2313 bool sendMerkleBlock =
false;
2315 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2316 LOCK(tx_relay->m_bloom_filter_mutex);
2317 if (tx_relay->m_bloom_filter) {
2318 sendMerkleBlock =
true;
2319 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2322 if (sendMerkleBlock) {
2330 typedef std::pair<unsigned int, uint256> PairType;
2342 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2355 LOCK(peer.m_block_inv_mutex);
2357 if (inv.
hash == peer.m_continuation_block) {
2361 std::vector<CInv> vInv;
2362 vInv.emplace_back(
MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash());
2364 peer.m_continuation_block.SetNull();
2372 auto txinfo = m_mempool.info_for_relay(gtxid, tx_relay.m_last_inv_sequence);
2374 return std::move(txinfo.tx);
2379 LOCK(m_most_recent_block_mutex);
2380 if (m_most_recent_block_txs !=
nullptr) {
2381 auto it = m_most_recent_block_txs->find(gtxid.
GetHash());
2382 if (it != m_most_recent_block_txs->end())
return it->second;
2389 void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2393 auto tx_relay = peer.GetTxRelay();
2395 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2396 std::vector<CInv> vNotFound;
2402 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2403 if (interruptMsgProc)
return;
2408 const CInv &inv = *it++;
2410 if (tx_relay ==
nullptr) {
2420 m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags,
NetMsgType::TX, *tx));
2421 m_mempool.RemoveUnbroadcastTx(tx->GetHash());
2423 vNotFound.push_back(inv);
2429 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2430 const CInv &inv = *it++;
2432 ProcessGetBlockData(pfrom, peer, inv);
2438 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2440 if (!vNotFound.empty()) {
2459 uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const 2461 uint32_t nFetchFlags = 0;
2462 if (CanServeWitnesses(peer)) {
2471 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2473 Misbehaving(peer, 100,
"getblocktxn with out-of-bounds tx indices");
2483 bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2487 Misbehaving(peer, 100,
"header with invalid proof of work");
2492 if (!CheckHeadersAreContinuous(headers)) {
2493 Misbehaving(peer, 20,
"non-continuous headers sequence");
2503 if (m_chainman.ActiveChain().Tip() !=
nullptr) {
2504 const CBlockIndex *tip = m_chainman.ActiveChain().Tip();
2509 return std::max(near_chaintip_work, m_chainman.MinimumChainWork());
2524 void PeerManagerImpl::HandleFewUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2525 const std::vector<CBlockHeader>& headers)
2527 peer.m_num_unconnecting_headers_msgs++;
2530 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2531 LogPrint(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, m_num_unconnecting_headers_msgs=%d)\n",
2533 headers[0].hashPrevBlock.ToString(),
2534 best_header->nHeight,
2535 pfrom.
GetId(), peer.m_num_unconnecting_headers_msgs);
2546 Misbehaving(peer, 20,
strprintf(
"%d non-connecting headers", peer.m_num_unconnecting_headers_msgs));
2550 bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const 2554 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2557 hashLastBlock = header.GetHash();
2562 bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2564 if (peer.m_headers_sync) {
2565 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() ==
MAX_HEADERS_RESULTS);
2566 if (result.request_more) {
2567 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2569 Assume(!locator.vHave.empty());
2570 if (!locator.vHave.empty()) {
2577 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2578 if (sent_getheaders) {
2580 locator.vHave.front().ToString(), pfrom.
GetId());
2582 LogPrint(
BCLog::NET,
"error sending next getheaders (from %s) to continue sync with peer=%d\n",
2583 locator.vHave.front().ToString(), pfrom.
GetId());
2589 peer.m_headers_sync.reset(
nullptr);
2594 LOCK(m_headers_presync_mutex);
2595 m_headers_presync_stats.erase(pfrom.
GetId());
2598 HeadersPresyncStats stats;
2599 stats.first = peer.m_headers_sync->GetPresyncWork();
2601 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2602 peer.m_headers_sync->GetPresyncTime()};
2606 LOCK(m_headers_presync_mutex);
2607 m_headers_presync_stats[pfrom.
GetId()] = stats;
2608 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2609 bool best_updated =
false;
2610 if (best_it == m_headers_presync_stats.end()) {
2614 const HeadersPresyncStats* stat_best{
nullptr};
2615 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2616 if (!stat_best || stat > *stat_best) {
2621 m_headers_presync_bestpeer = peer_best;
2622 best_updated = (peer_best == pfrom.
GetId());
2623 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2625 m_headers_presync_bestpeer = pfrom.
GetId();
2626 best_updated =
true;
2628 if (best_updated && stats.second.has_value()) {
2630 m_headers_presync_should_signal =
true;
2634 if (result.success) {
2637 headers.swap(result.pow_validated_headers);
2640 return result.success;
2648 bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2655 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2659 if (total_work < minimum_chain_work) {
2673 LOCK(peer.m_headers_sync_mutex);
2674 peer.m_headers_sync.reset(
new HeadersSyncState(peer.m_id, m_chainparams.GetConsensus(),
2675 chain_start_header, minimum_chain_work));
2680 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2694 bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2696 if (header ==
nullptr) {
2698 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2700 }
else if (m_chainman.ActiveChain().Contains(header)) {
2706 bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2716 peer.m_last_getheaders_timestamp = current_time;
2727 void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2732 CNodeState *nodestate =
State(pfrom.
GetId());
2735 std::vector<const CBlockIndex*> vToFetch;
2743 vToFetch.push_back(pindexWalk);
2745 pindexWalk = pindexWalk->
pprev;
2751 if (!m_chainman.ActiveChain().Contains(pindexWalk)) {
2756 std::vector<CInv> vGetData;
2763 uint32_t nFetchFlags = GetFetchFlags(peer);
2765 BlockRequested(pfrom.
GetId(), *pindex);
2769 if (vGetData.size() > 1) {
2774 if (vGetData.size() > 0) {
2775 if (!m_opts.ignore_incoming_txs &&
2776 nodestate->m_provides_cmpctblocks &&
2777 vGetData.size() == 1 &&
2778 mapBlocksInFlight.size() == 1 &&
2794 void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2795 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2797 if (peer.m_num_unconnecting_headers_msgs > 0) {
2798 LogPrint(
BCLog::NET,
"peer=%d: resetting m_num_unconnecting_headers_msgs (%d -> 0)\n", pfrom.
GetId(), peer.m_num_unconnecting_headers_msgs);
2800 peer.m_num_unconnecting_headers_msgs = 0;
2803 CNodeState *nodestate =
State(pfrom.
GetId());
2811 if (received_new_header && last_header.
nChainWork > m_chainman.ActiveChain().Tip()->nChainWork) {
2812 nodestate->m_last_block_announcement =
GetTime();
2817 if (m_chainman.IsInitialBlockDownload() && !may_have_more_headers) {
2820 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.MinimumChainWork()) {
2830 LogPrintf(
"Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.
GetId());
2842 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) {
2844 nodestate->m_chain_sync.m_protect =
true;
2845 ++m_outbound_peers_with_protect_from_disconnect;
2850 void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2851 std::vector<CBlockHeader>&& headers,
2852 bool via_compact_block)
2854 size_t nCount = headers.size();
2861 LOCK(peer.m_headers_sync_mutex);
2862 if (peer.m_headers_sync) {
2863 peer.m_headers_sync.reset(
nullptr);
2864 LOCK(m_headers_presync_mutex);
2865 m_headers_presync_stats.erase(pfrom.
GetId());
2874 if (!CheckHeadersPoW(headers, m_chainparams.GetConsensus(), peer)) {
2889 bool already_validated_work =
false;
2892 bool have_headers_sync =
false;
2894 LOCK(peer.m_headers_sync_mutex);
2896 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2908 if (headers.empty()) {
2912 have_headers_sync = !!peer.m_headers_sync;
2916 const CBlockIndex *chain_start_header{
WITH_LOCK(::
cs_main,
return m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock))};
2917 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2919 if (!headers_connect_blockindex) {
2924 HandleFewUnconnectingHeaders(pfrom, peer, headers);
2926 Misbehaving(peer, 10,
"invalid header received");
2938 last_received_header = m_chainman.m_blockman.LookupBlockIndex(headers.back().GetHash());
2939 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2940 already_validated_work =
true;
2948 already_validated_work =
true;
2954 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2955 chain_start_header, headers)) {
2967 bool received_new_header{last_received_header ==
nullptr};
2971 if (!m_chainman.ProcessNewBlockHeaders(headers,
true, state, &pindexLast)) {
2973 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2982 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2984 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2988 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount ==
MAX_HEADERS_RESULTS);
2991 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
2996 bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3006 const uint256& orphanHash = porphanTx->GetHash();
3007 const uint256& orphan_wtxid = porphanTx->GetWitnessHash();
3015 m_mempool.size(), m_mempool.DynamicMemoryUsage() / 1000);
3016 RelayTransaction(orphanHash, porphanTx->GetWitnessHash());
3018 m_orphanage.
EraseTx(orphanHash);
3020 AddToCompactExtraTransactions(removedTx);
3036 MaybePunishNodeForTx(peer.m_id, state);
3055 m_recent_rejects.insert(porphanTx->GetWitnessHash());
3067 m_recent_rejects.insert(porphanTx->GetHash());
3070 m_orphanage.
EraseTx(orphanHash);
3078 bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3080 const uint256& stop_hash, uint32_t max_height_diff,
3084 const bool supported_filter_type =
3087 if (!supported_filter_type) {
3089 node.GetId(),
static_cast<uint8_t
>(filter_type));
3090 node.fDisconnect =
true;
3096 stop_index = m_chainman.m_blockman.LookupBlockIndex(stop_hash);
3099 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3102 node.fDisconnect =
true;
3107 uint32_t stop_height = stop_index->
nHeight;
3108 if (start_height > stop_height) {
3110 "start height %d and stop height %d\n",
3111 node.GetId(), start_height, stop_height);
3112 node.fDisconnect =
true;
3115 if (stop_height - start_height >= max_height_diff) {
3117 node.GetId(), stop_height - start_height + 1, max_height_diff);
3118 node.fDisconnect =
true;
3123 if (!filter_index) {
3133 uint8_t filter_type_ser;
3134 uint32_t start_height;
3137 vRecv >> filter_type_ser >> start_height >> stop_hash;
3143 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3148 std::vector<BlockFilter> filters;
3150 LogPrint(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3155 for (
const auto& filter : filters) {
3158 m_connman.PushMessage(&
node, std::move(
msg));
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,
3180 if (start_height > 0) {
3182 stop_index->
GetAncestor(static_cast<int>(start_height - 1));
3184 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3190 std::vector<uint256> filter_hashes;
3192 LogPrint(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3203 m_connman.PushMessage(&
node, std::move(
msg));
3208 uint8_t filter_type_ser;
3211 vRecv >> filter_type_ser >> stop_hash;
3217 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3218 std::numeric_limits<uint32_t>::max(),
3219 stop_index, filter_index)) {
3227 for (
int i = headers.size() - 1; i >= 0; i--) {
3232 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3243 m_connman.PushMessage(&
node, std::move(
msg));
3246 void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked)
3248 bool new_block{
false};
3249 m_chainman.ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3251 node.m_last_block_time = GetTime<std::chrono::seconds>();
3256 RemoveBlockRequest(block->GetHash(), std::nullopt);
3259 mapBlockSource.erase(block->GetHash());
3263 void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3265 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3266 bool fBlockRead{
false};
3271 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3272 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3273 bool requested_block_from_this_peer{
false};
3276 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3278 while (range_flight.first != range_flight.second) {
3279 auto [node_id, block_it] = range_flight.first->second;
3280 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3281 requested_block_from_this_peer =
true;
3284 range_flight.first++;
3287 if (!requested_block_from_this_peer) {
3296 Misbehaving(peer, 100,
"invalid compact block/non-matching block transactions");
3299 if (first_in_flight) {
3301 std::vector<CInv> invs;
3306 LogPrint(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3335 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3345 ProcessBlock(pfrom, pblock,
true,
true);
3350 void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
CDataStream& vRecv,
3351 const std::chrono::microseconds time_received,
3352 const std::atomic<bool>& interruptMsgProc)
3358 PeerRef peer = GetPeerRef(pfrom.
GetId());
3359 if (peer ==
nullptr)
return;
3369 uint64_t nNonce = 1;
3372 std::string cleanSubVer;
3373 int starting_height = -1;
3376 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3384 m_addrman.SetServices(pfrom.
addr, nServices);
3400 if (!vRecv.
empty()) {
3408 if (!vRecv.
empty()) {
3409 std::string strSubVer;
3413 if (!vRecv.
empty()) {
3414 vRecv >> starting_height;
3419 if (pfrom.
IsInboundConn() && !m_connman.CheckIncomingNonce(nNonce))
3434 PushNodeVersion(pfrom, *peer);
3449 if (greatest_common_version >= 70016) {
3458 peer->m_their_services = nServices;
3462 pfrom.cleanSubVer = cleanSubVer;
3464 peer->m_starting_height = starting_height;
3474 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3475 auto*
const tx_relay = peer->SetTxRelay();
3477 LOCK(tx_relay->m_bloom_filter_mutex);
3478 tx_relay->m_relay_txs = fRelay;
3490 const auto* tx_relay = peer->GetTxRelay();
3491 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3493 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3506 m_num_preferred_download_peers += state->fPreferredDownload;
3512 bool send_getaddr{
false};
3514 send_getaddr = SetupAddressRelay(pfrom, *peer);
3524 peer->m_getaddr_sent =
true;
3545 m_addrman.Good(pfrom.
addr);
3548 std::string remoteAddr;
3552 const auto mapped_as{m_connman.GetMappedAS(pfrom.
addr)};
3553 LogPrint(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3556 remoteAddr, (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3558 int64_t nTimeOffset = nTime -
GetTime();
3567 if (greatest_common_version <= 70012) {
3568 const auto finalAlert{
ParseHex(
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50")};
3569 m_connman.PushMessage(&pfrom,
CNetMsgMaker(greatest_common_version).Make(
"alert",
Span{finalAlert}));
3598 const auto mapped_as{m_connman.GetMappedAS(pfrom.
addr)};
3599 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3602 pfrom.
nVersion.load(), peer->m_starting_height,
3604 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3616 if (m_txreconciliation) {
3617 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3621 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3625 if (
auto tx_relay = peer->GetTxRelay()) {
3634 tx_relay->m_tx_inventory_mutex,
3635 return tx_relay->m_tx_inventory_to_send.empty() &&
3636 tx_relay->m_next_inv_send_time == 0s));
3644 peer->m_prefers_headers =
true;
3649 bool sendcmpct_hb{
false};
3650 uint64_t sendcmpct_version{0};
3651 vRecv >> sendcmpct_hb >> sendcmpct_version;
3657 CNodeState* nodestate =
State(pfrom.
GetId());
3658 nodestate->m_provides_cmpctblocks =
true;
3659 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3676 if (!peer->m_wtxid_relay) {
3677 peer->m_wtxid_relay =
true;
3678 m_wtxid_relay_peers++;
3697 peer->m_wants_addrv2 =
true;
3705 if (!m_txreconciliation) {
3717 if (RejectIncomingTxs(pfrom)) {
3726 const auto* tx_relay = peer->GetTxRelay();
3727 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3733 uint32_t peer_txreconcl_version;
3734 uint64_t remote_salt;
3735 vRecv >> peer_txreconcl_version >> remote_salt;
3738 peer_txreconcl_version, remote_salt);
3763 const auto ser_params{
3771 std::vector<CAddress> vAddr;
3775 if (!SetupAddressRelay(pfrom, *peer)) {
3782 Misbehaving(*peer, 20,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3787 std::vector<CAddress> vAddrOk;
3788 const auto current_a_time{Now<NodeSeconds>()};
3791 const auto current_time{GetTime<std::chrono::microseconds>()};
3794 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3798 peer->m_addr_token_timestamp = current_time;
3801 uint64_t num_proc = 0;
3802 uint64_t num_rate_limit = 0;
3803 Shuffle(vAddr.begin(), vAddr.end(), m_rng);
3806 if (interruptMsgProc)
3810 if (peer->m_addr_token_bucket < 1.0) {
3816 peer->m_addr_token_bucket -= 1.0;
3825 addr.
nTime = current_a_time - 5 * 24h;
3827 AddAddressKnown(*peer, addr);
3828 if (m_banman && (m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr))) {
3834 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3836 RelayAddress(pfrom.
GetId(), addr, reachable);
3840 vAddrOk.push_back(addr);
3843 peer->m_addr_processed += num_proc;
3844 peer->m_addr_rate_limited += num_rate_limit;
3845 LogPrint(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3846 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3848 m_addrman.Add(vAddrOk, pfrom.
addr, 2h);
3849 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3860 std::vector<CInv> vInv;
3864 Misbehaving(*peer, 20,
strprintf(
"inv message size = %u", vInv.size()));
3868 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3872 const auto current_time{GetTime<std::chrono::microseconds>()};
3875 for (
CInv& inv : vInv) {
3876 if (interruptMsgProc)
return;
3881 if (peer->m_wtxid_relay) {
3888 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3891 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3892 if (!fAlreadyHave && !m_chainman.m_blockman.LoadingBlocks() && !IsBlockRequested(inv.
hash)) {
3899 best_block = &inv.
hash;
3902 if (reject_tx_invs) {
3908 const bool fAlreadyHave = AlreadyHaveTx(gtxid);
3911 AddKnownTx(*peer, inv.
hash);
3912 if (!fAlreadyHave && !m_chainman.IsInitialBlockDownload()) {
3913 AddTxAnnouncement(pfrom, gtxid, current_time);
3920 if (best_block !=
nullptr) {
3932 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
3933 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
3935 m_chainman.m_best_header->nHeight, best_block->ToString(),
3938 if (!state.fSyncStarted) {
3939 peer->m_inv_triggered_getheaders_before_sync =
true;
3943 m_last_block_inv_triggering_headers_sync = *best_block;
3952 std::vector<CInv> vInv;
3956 Misbehaving(*peer, 20,
strprintf(
"getdata message size = %u", vInv.size()));
3962 if (vInv.size() > 0) {
3967 LOCK(peer->m_getdata_requests_mutex);
3968 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
3969 ProcessGetData(pfrom, *peer, interruptMsgProc);
3978 vRecv >> locator >> hashStop;
3994 std::shared_ptr<const CBlock> a_recent_block;
3996 LOCK(m_most_recent_block_mutex);
3997 a_recent_block = m_most_recent_block;
4000 if (!m_chainman.ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4008 const CBlockIndex* pindex = m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
4012 pindex = m_chainman.ActiveChain().Next(pindex);
4014 LogPrint(
BCLog::NET,
"getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->
nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), nLimit, pfrom.
GetId());
4015 for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex))
4024 const int nPrunedBlocksLikelyToHave =
MIN_BLOCKS_TO_KEEP - 3600 / m_chainparams.GetConsensus().nPowTargetSpacing;
4025 if (m_chainman.m_blockman.IsPruneMode() && (!(pindex->nStatus &
BLOCK_HAVE_DATA) || pindex->
nHeight <= m_chainman.ActiveChain().Tip()->nHeight - nPrunedBlocksLikelyToHave)) {
4030 if (--nLimit <= 0) {
4034 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4045 std::shared_ptr<const CBlock> recent_block;
4047 LOCK(m_most_recent_block_mutex);
4048 if (m_most_recent_block_hash == req.blockhash)
4049 recent_block = m_most_recent_block;
4053 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4060 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(req.blockhash);
4068 const bool ret{m_chainman.m_blockman.ReadBlockFromDisk(block, *pindex)};
4071 SendBlockTransactions(pfrom, *peer, block, req);
4085 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4093 vRecv >> locator >> hashStop;
4101 if (m_chainman.m_blockman.LoadingBlocks()) {
4115 if (m_chainman.ActiveTip() ==
nullptr ||
4117 LogPrint(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4124 CNodeState *nodestate =
State(pfrom.
GetId());
4129 pindex = m_chainman.m_blockman.LookupBlockIndex(hashStop);
4134 if (!BlockRequestAllowed(pindex)) {
4135 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4142 pindex = m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
4144 pindex = m_chainman.ActiveChain().Next(pindex);
4148 std::vector<CBlock> vHeaders;
4150 LogPrint(
BCLog::NET,
"getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), pfrom.
GetId());
4151 for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex))
4153 vHeaders.emplace_back(pindex->GetBlockHeader());
4154 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4169 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.ActiveChain().Tip();
4175 if (RejectIncomingTxs(pfrom)) {
4184 if (m_chainman.IsInitialBlockDownload())
return;
4190 const uint256& txid = ptx->GetHash();
4191 const uint256& wtxid = ptx->GetWitnessHash();
4193 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4194 AddKnownTx(*peer, hash);
4198 m_txrequest.ReceivedResponse(pfrom.
GetId(), txid);
4199 if (tx.
HasWitness()) m_txrequest.ReceivedResponse(pfrom.
GetId(), wtxid);
4219 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4222 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4251 m_txrequest.ForgetTxHash(tx.
GetHash());
4262 m_mempool.size(), m_mempool.DynamicMemoryUsage() / 1000);
4265 AddToCompactExtraTransactions(removedTx);
4270 bool fRejectedParents =
false;
4274 std::vector<uint256> unique_parents;
4275 unique_parents.reserve(tx.
vin.size());
4280 std::sort(unique_parents.begin(), unique_parents.end());
4281 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
4282 for (
const uint256& parent_txid : unique_parents) {
4283 if (m_recent_rejects.contains(parent_txid)) {
4284 fRejectedParents =
true;
4288 if (!fRejectedParents) {
4289 const auto current_time{GetTime<std::chrono::microseconds>()};
4291 for (
const uint256& parent_txid : unique_parents) {
4298 AddKnownTx(*peer, parent_txid);
4299 if (!AlreadyHaveTx(gtxid)) AddTxAnnouncement(pfrom, gtxid, current_time);
4303 AddToCompactExtraTransactions(ptx);
4307 m_txrequest.ForgetTxHash(tx.
GetHash());
4322 m_recent_rejects.insert(tx.
GetHash());
4324 m_txrequest.ForgetTxHash(tx.
GetHash());
4353 m_recent_rejects.insert(tx.
GetHash());
4354 m_txrequest.ForgetTxHash(tx.
GetHash());
4357 AddToCompactExtraTransactions(ptx);
4368 MaybePunishNodeForTx(pfrom.
GetId(), state);
4376 if (m_chainman.m_blockman.LoadingBlocks()) {
4382 vRecv >> cmpctblock;
4384 bool received_new_header =
false;
4390 const CBlockIndex* prev_block = m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock);
4393 if (!m_chainman.IsInitialBlockDownload()) {
4394 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4403 if (!m_chainman.m_blockman.LookupBlockIndex(blockhash)) {
4404 received_new_header =
true;
4410 if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header},
true, state, &pindex)) {
4412 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4417 if (received_new_header) {
4419 blockhash.ToString(), pfrom.
GetId());
4422 bool fProcessBLOCKTXN =
false;
4426 bool fRevertToHeaderProcessing =
false;
4430 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4431 bool fBlockReconstructed =
false;
4439 CNodeState *nodestate =
State(pfrom.
GetId());
4443 if (received_new_header && pindex->
nChainWork > m_chainman.ActiveChain().Tip()->nChainWork) {
4444 nodestate->m_last_block_announcement =
GetTime();
4450 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4451 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4452 bool requested_block_from_this_peer{
false};
4455 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4457 while (range_flight.first != range_flight.second) {
4458 if (range_flight.first->second.first == pfrom.
GetId()) {
4459 requested_block_from_this_peer =
true;
4462 range_flight.first++;
4465 if (pindex->
nChainWork <= m_chainman.ActiveChain().Tip()->nChainWork ||
4467 if (requested_block_from_this_peer) {
4470 std::vector<CInv> vInv(1);
4471 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4478 if (!already_in_flight && !CanDirectFetch()) {
4484 if (pindex->
nHeight <= m_chainman.ActiveChain().Height() + 2) {
4486 requested_block_from_this_peer) {
4487 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4488 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4489 if (!(*queuedBlockIt)->partialBlock)
4502 Misbehaving(*peer, 100,
"invalid compact block");
4505 if (first_in_flight) {
4507 std::vector<CInv> vInv(1);
4508 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4518 for (
size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {
4523 fProcessBLOCKTXN =
true;
4524 }
else if (first_in_flight) {
4531 IsBlockRequestedFromOutbound(blockhash) ||
4550 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4555 std::vector<CTransactionRef> dummy;
4556 status = tempBlock.FillBlock(*pblock, dummy);
4558 fBlockReconstructed =
true;
4562 if (requested_block_from_this_peer) {
4565 std::vector<CInv> vInv(1);
4566 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4571 fRevertToHeaderProcessing =
true;
4576 if (fProcessBLOCKTXN) {
4579 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4582 if (fRevertToHeaderProcessing) {
4588 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.header},
true);
4591 if (fBlockReconstructed) {
4596 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4607 ProcessBlock(pfrom, pblock,
true,
true);
4614 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4623 if (m_chainman.m_blockman.LoadingBlocks()) {
4631 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4637 if (m_chainman.m_blockman.LoadingBlocks()) {
4644 peer->m_last_getheaders_timestamp = {};
4646 std::vector<CBlockHeader> headers;
4651 Misbehaving(*peer, 20,
strprintf(
"headers message size = %u", nCount));
4654 headers.resize(nCount);
4655 for (
unsigned int n = 0; n < nCount; n++) {
4656 vRecv >> headers[n];
4660 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4664 if (m_headers_presync_should_signal.exchange(
false)) {
4665 HeadersPresyncStats stats;
4667 LOCK(m_headers_presync_mutex);
4668 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4669 if (it != m_headers_presync_stats.end()) stats = it->second;
4672 m_chainman.ReportHeadersPresync(stats.first, stats.second->first, stats.second->second);
4682 if (m_chainman.m_blockman.LoadingBlocks()) {
4687 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4692 const CBlockIndex* prev_block{
WITH_LOCK(m_chainman.GetMutex(),
return m_chainman.m_blockman.LookupBlockIndex(pblock->hashPrevBlock))};
4698 Misbehaving(*peer, 100,
"mutated block");
4703 bool forceProcessing =
false;
4704 const uint256 hash(pblock->GetHash());
4705 bool min_pow_checked =
false;
4710 forceProcessing = IsBlockRequested(hash);
4711 RemoveBlockRequest(hash, pfrom.
GetId());
4715 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4719 min_pow_checked =
true;
4722 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4739 Assume(SetupAddressRelay(pfrom, *peer));
4743 if (peer->m_getaddr_recvd) {
4747 peer->m_getaddr_recvd =
true;
4749 peer->m_addrs_to_send.clear();
4750 std::vector<CAddress> vAddr;
4756 for (
const CAddress &addr : vAddr) {
4757 PushAddress(*peer, addr);
4785 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4786 LOCK(tx_relay->m_tx_inventory_mutex);
4787 tx_relay->m_send_mempool =
true;
4813 const auto ping_end = time_received;
4816 bool bPingFinished =
false;
4817 std::string sProblem;
4819 if (nAvail >=
sizeof(
nonce)) {
4823 if (peer->m_ping_nonce_sent != 0) {
4824 if (
nonce == peer->m_ping_nonce_sent) {
4826 bPingFinished =
true;
4827 const auto ping_time = ping_end - peer->m_ping_start.load();
4828 if (ping_time.count() >= 0) {
4833 sProblem =
"Timing mishap";
4837 sProblem =
"Nonce mismatch";
4840 bPingFinished =
true;
4841 sProblem =
"Nonce zero";
4845 sProblem =
"Unsolicited pong without ping";
4849 bPingFinished =
true;
4850 sProblem =
"Short payload";
4853 if (!(sProblem.empty())) {
4857 peer->m_ping_nonce_sent,
4861 if (bPingFinished) {
4862 peer->m_ping_nonce_sent = 0;
4869 LogPrint(
BCLog::NET,
"filterload received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4876 if (!filter.IsWithinSizeConstraints())
4879 Misbehaving(*peer, 100,
"too-large bloom filter");
4880 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4882 LOCK(tx_relay->m_bloom_filter_mutex);
4883 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4884 tx_relay->m_relay_txs =
true;
4894 LogPrint(
BCLog::NET,
"filteradd received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4898 std::vector<unsigned char> vData;
4906 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4907 LOCK(tx_relay->m_bloom_filter_mutex);
4908 if (tx_relay->m_bloom_filter) {
4909 tx_relay->m_bloom_filter->insert(vData);
4915 Misbehaving(*peer, 100,
"bad filteradd message");
4922 LogPrint(
BCLog::NET,
"filterclear received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4926 auto tx_relay = peer->GetTxRelay();
4927 if (!tx_relay)
return;
4930 LOCK(tx_relay->m_bloom_filter_mutex);
4931 tx_relay->m_bloom_filter =
nullptr;
4932 tx_relay->m_relay_txs =
true;
4941 vRecv >> newFeeFilter;
4943 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4944 tx_relay->m_fee_filter_received = newFeeFilter;
4952 ProcessGetCFilters(pfrom, *peer, vRecv);
4957 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4962 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4967 std::vector<CInv> vInv;
4971 for (
CInv &inv : vInv) {
4975 m_txrequest.ReceivedResponse(pfrom.
GetId(), inv.
hash);
4987 bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4990 LOCK(peer.m_misbehavior_mutex);
4993 if (!peer.m_should_discourage)
return false;
4995 peer.m_should_discourage =
false;
5000 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
5006 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
5021 if (m_banman) m_banman->Discourage(pnode.
addr);
5022 m_connman.DisconnectNode(pnode.
addr);
5026 bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
5030 PeerRef peer = GetPeerRef(pfrom->
GetId());
5031 if (peer ==
nullptr)
return false;
5034 LOCK(peer->m_getdata_requests_mutex);
5035 if (!peer->m_getdata_requests.empty()) {
5036 ProcessGetData(*pfrom, *peer, interruptMsgProc);
5040 const bool processed_orphan = ProcessOrphanTx(*peer);
5045 if (processed_orphan)
return true;
5050 LOCK(peer->m_getdata_requests_mutex);
5051 if (!peer->m_getdata_requests.empty())
return true;
5064 bool fMoreWork = poll_result->second;
5066 TRACE6(net, inbound_message,
5075 if (m_opts.capture_messages) {
5082 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5083 if (interruptMsgProc)
return false;
5085 LOCK(peer->m_getdata_requests_mutex);
5086 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5094 }
catch (
const std::exception& e) {
5103 void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5116 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.ActiveChain().Tip()->nChainWork) {
5117 if (state.m_chain_sync.m_timeout != 0s) {
5118 state.m_chain_sync.m_timeout = 0s;
5119 state.m_chain_sync.m_work_header =
nullptr;
5120 state.m_chain_sync.m_sent_getheaders =
false;
5122 }
else if (state.m_chain_sync.m_timeout == 0s || (state.m_chain_sync.m_work_header !=
nullptr && state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= state.m_chain_sync.m_work_header->nChainWork)) {
5128 state.m_chain_sync.m_work_header = m_chainman.ActiveChain().Tip();
5129 state.m_chain_sync.m_sent_getheaders =
false;
5130 }
else if (state.m_chain_sync.m_timeout > 0s && time_in_seconds > state.m_chain_sync.m_timeout) {
5134 if (state.m_chain_sync.m_sent_getheaders) {
5136 LogPrintf(
"Disconnecting outbound peer %d for old chain, best known block = %s\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>");
5139 assert(state.m_chain_sync.m_work_header);
5144 MaybeSendGetHeaders(pto,
5145 GetLocator(state.m_chain_sync.m_work_header->pprev),
5147 LogPrint(
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());
5148 state.m_chain_sync.m_sent_getheaders =
true;
5160 void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5168 if (m_connman.GetExtraBlockRelayCount() > 0) {
5169 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5171 m_connman.ForEachNode([&](
CNode* pnode) {
5173 if (pnode->
GetId() > youngest_peer.first) {
5174 next_youngest_peer = youngest_peer;
5175 youngest_peer.first = pnode->
GetId();
5179 NodeId to_disconnect = youngest_peer.first;
5180 if (youngest_peer.second > next_youngest_peer.second) {
5183 to_disconnect = next_youngest_peer.first;
5192 CNodeState *node_state =
State(pnode->
GetId());
5193 if (node_state ==
nullptr ||
5196 LogPrint(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5200 LogPrint(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5208 if (m_connman.GetExtraFullOutboundCount() > 0) {
5216 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5225 if (state ==
nullptr)
return;
5227 if (state->m_chain_sync.m_protect)
return;
5230 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->
addr.
GetNetwork()))
return;
5231 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->
GetId() > worst_peer)) {
5232 worst_peer = pnode->
GetId();
5233 oldest_block_announcement = state->m_last_block_announcement;
5236 if (worst_peer != -1) {
5247 LogPrint(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5251 LogPrint(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5262 m_connman.SetTryNewOutboundPeer(
false);
5268 void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5272 auto now{GetTime<std::chrono::seconds>()};
5274 EvictExtraOutboundPeers(now);
5276 if (now > m_stale_tip_check_time) {
5279 if (!m_chainman.m_blockman.LoadingBlocks() && m_connman.GetNetworkActive() && m_connman.GetUseAddrmanOutgoing() && TipMayBeStale()) {
5280 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5282 m_connman.SetTryNewOutboundPeer(
true);
5283 }
else if (m_connman.GetTryNewOutboundPeer()) {
5284 m_connman.SetTryNewOutboundPeer(
false);
5289 if (!m_initial_sync_finished && CanDirectFetch()) {
5290 m_connman.StartExtraBlockRelayPeers();
5291 m_initial_sync_finished =
true;
5295 void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5297 if (m_connman.ShouldRunInactivityChecks(node_to, std::chrono::duration_cast<std::chrono::seconds>(now)) &&
5298 peer.m_ping_nonce_sent &&
5309 bool pingSend =
false;
5311 if (peer.m_ping_queued) {
5316 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5324 nonce = GetRand<uint64_t>();
5325 }
while (
nonce == 0);
5326 peer.m_ping_queued =
false;
5327 peer.m_ping_start = now;
5329 peer.m_ping_nonce_sent =
nonce;
5333 peer.m_ping_nonce_sent = 0;
5339 void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5342 if (!peer.m_addr_relay_enabled)
return;
5344 LOCK(peer.m_addr_send_times_mutex);
5346 if (
fListen && !m_chainman.IsInitialBlockDownload() &&
5347 peer.m_next_local_addr_send < current_time) {
5354 if (peer.m_next_local_addr_send != 0us) {
5355 peer.m_addr_known->reset();
5358 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5359 PushAddress(peer, local_addr);
5365 if (current_time <= peer.m_next_addr_send)
return;
5378 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5379 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5382 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5383 peer.m_addrs_to_send.end());
5386 if (peer.m_addrs_to_send.empty())
return;
5388 const char* msg_type;
5390 if (peer.m_wants_addrv2) {
5398 peer.m_addrs_to_send.clear();
5401 if (peer.m_addrs_to_send.capacity() > 40) {
5402 peer.m_addrs_to_send.shrink_to_fit();
5406 void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5414 CNodeState &state = *
State(
node.GetId());
5415 if (state.pindexBestKnownBlock !=
nullptr &&
5416 state.pindexBestKnownBlock->nChainWork > m_chainman.MinimumChainWork()) {
5422 peer.m_sent_sendheaders =
true;
5427 void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5429 if (m_opts.ignore_incoming_txs)
return;
5437 CAmount currentFilter = m_mempool.GetMinFee().GetFeePerK();
5439 if (m_chainman.IsInitialBlockDownload()) {
5445 if (peer.m_fee_filter_sent == MAX_FILTER) {
5448 peer.m_next_send_feefilter = 0us;
5451 if (current_time > peer.m_next_send_feefilter) {
5452 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5454 filterToSend = std::max(filterToSend, m_mempool.m_min_relay_feerate.GetFeePerK());
5455 if (filterToSend != peer.m_fee_filter_sent) {
5457 peer.m_fee_filter_sent = filterToSend;
5464 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5470 class CompareInvMempoolOrder
5475 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5478 m_wtxid_relay = use_wtxid;
5481 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5485 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5490 bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const 5500 bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5505 if (
node.IsBlockOnlyConn())
return false;
5507 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5511 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5517 bool PeerManagerImpl::SendMessages(
CNode* pto)
5521 PeerRef peer = GetPeerRef(pto->
GetId());
5522 if (!peer)
return false;
5527 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5536 const auto current_time{GetTime<std::chrono::microseconds>()};
5544 MaybeSendPing(*pto, *peer, current_time);
5549 MaybeSendAddr(*pto, *peer, current_time);
5551 MaybeSendSendHeaders(*pto, *peer);
5559 if (m_chainman.m_best_header ==
nullptr) {
5560 m_chainman.m_best_header = m_chainman.ActiveChain().Tip();
5566 bool sync_blocks_and_headers_from_peer =
false;
5567 if (state.fPreferredDownload) {
5568 sync_blocks_and_headers_from_peer =
true;
5579 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5580 sync_blocks_and_headers_from_peer =
true;
5584 if (!state.fSyncStarted && CanServeBlocks(*peer) && !m_chainman.m_blockman.LoadingBlocks()) {
5586 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
GetAdjustedTime() - 24h) {
5587 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5595 if (pindexStart->
pprev)
5596 pindexStart = pindexStart->
pprev;
5597 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5600 state.fSyncStarted =
true;
5624 LOCK(peer->m_block_inv_mutex);
5625 std::vector<CBlock> vHeaders;
5626 bool fRevertToInv = ((!peer->m_prefers_headers &&
5627 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5630 ProcessBlockAvailability(pto->
GetId());
5632 if (!fRevertToInv) {
5633 bool fFoundStartingHeader =
false;
5637 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5638 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
5640 if (m_chainman.ActiveChain()[pindex->
nHeight] != pindex) {
5642 fRevertToInv =
true;
5645 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5657 fRevertToInv =
true;
5660 pBestIndex = pindex;
5661 if (fFoundStartingHeader) {
5664 }
else if (PeerHasHeader(&state, pindex)) {
5666 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5669 fFoundStartingHeader =
true;
5674 fRevertToInv =
true;
5679 if (!fRevertToInv && !vHeaders.empty()) {
5680 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5684 vHeaders.front().GetHash().ToString(), pto->
GetId());
5686 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5688 LOCK(m_most_recent_block_mutex);
5689 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5693 if (cached_cmpctblock_msg.has_value()) {
5694 m_connman.PushMessage(pto, std::move(cached_cmpctblock_msg.value()));
5697 const bool ret{m_chainman.m_blockman.ReadBlockFromDisk(block, *pBestIndex)};
5702 state.pindexBestHeaderSent = pBestIndex;
5703 }
else if (peer->m_prefers_headers) {
5704 if (vHeaders.size() > 1) {
5707 vHeaders.front().GetHash().ToString(),
5708 vHeaders.back().GetHash().ToString(), pto->
GetId());
5711 vHeaders.front().GetHash().ToString(), pto->
GetId());
5714 state.pindexBestHeaderSent = pBestIndex;
5716 fRevertToInv =
true;
5722 if (!peer->m_blocks_for_headers_relay.empty()) {
5723 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5724 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hashToAnnounce);
5730 if (m_chainman.ActiveChain()[pindex->
nHeight] != pindex) {
5732 hashToAnnounce.
ToString(), m_chainman.ActiveChain().Tip()->GetBlockHash().ToString());
5736 if (!PeerHasHeader(&state, pindex)) {
5737 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5743 peer->m_blocks_for_headers_relay.clear();
5749 std::vector<CInv> vInv;
5751 LOCK(peer->m_block_inv_mutex);
5755 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5762 peer->m_blocks_for_inv_relay.clear();
5765 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5766 LOCK(tx_relay->m_tx_inventory_mutex);
5769 if (tx_relay->m_next_inv_send_time < current_time) {
5770 fSendTrickle =
true;
5780 LOCK(tx_relay->m_bloom_filter_mutex);
5781 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5785 if (fSendTrickle && tx_relay->m_send_mempool) {
5786 auto vtxinfo = m_mempool.infoAll();
5787 tx_relay->m_send_mempool =
false;
5788 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5790 LOCK(tx_relay->m_bloom_filter_mutex);
5792 for (
const auto& txinfo : vtxinfo) {
5793 const uint256& hash = peer->m_wtxid_relay ? txinfo.tx->GetWitnessHash() : txinfo.tx->GetHash();
5795 tx_relay->m_tx_inventory_to_send.erase(hash);
5797 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5800 if (tx_relay->m_bloom_filter) {
5801 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5803 tx_relay->m_tx_inventory_known_filter.insert(hash);
5804 vInv.push_back(inv);
5815 std::vector<std::set<uint256>::iterator> vInvTx;
5816 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5817 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5818 vInvTx.push_back(it);
5820 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5823 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
5824 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5827 unsigned int nRelayedTransactions = 0;
5828 LOCK(tx_relay->m_bloom_filter_mutex);
5831 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5833 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5834 std::set<uint256>::iterator it = vInvTx.back();
5839 tx_relay->m_tx_inventory_to_send.erase(it);
5841 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
5845 auto txinfo = m_mempool.info(
ToGenTxid(inv));
5850 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5853 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5855 vInv.push_back(inv);
5856 nRelayedTransactions++;
5861 tx_relay->m_tx_inventory_known_filter.insert(hash);
5866 tx_relay->m_last_inv_sequence = m_mempool.GetSequence();
5873 auto stalling_timeout = m_block_stalling_timeout.load();
5874 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5883 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5893 if (state.vBlocksInFlight.size() > 0) {
5894 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5895 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5903 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5906 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5923 state.fSyncStarted =
false;
5925 peer->m_headers_sync_timeout = 0us;
5931 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5937 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5942 std::vector<CInv> vGetData;
5943 if (CanServeBlocks(*peer) && ((sync_blocks_and_headers_from_peer && !IsLimitedPeer(*peer)) || !m_chainman.IsInitialBlockDownload()) && state.vBlocksInFlight.size() <
MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
5944 std::vector<const CBlockIndex*> vToDownload;
5946 auto get_inflight_budget = [&state]() {
5952 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5953 if (m_chainman.BackgroundSyncInProgress() && !IsLimitedPeer(*peer)) {
5954 TryDownloadingHistoricalBlocks(
5956 get_inflight_budget(),
5957 vToDownload, m_chainman.GetBackgroundSyncTip(),
5958 Assert(m_chainman.GetSnapshotBaseBlock()));
5961 uint32_t nFetchFlags = GetFetchFlags(*peer);
5963 BlockRequested(pto->
GetId(), *pindex);
5967 if (state.vBlocksInFlight.empty() && staller != -1) {
5968 if (
State(staller)->m_stalling_since == 0us) {
5969 State(staller)->m_stalling_since = current_time;
5978 std::vector<std::pair<NodeId, GenTxid>> expired;
5979 auto requestable = m_txrequest.GetRequestable(pto->
GetId(), current_time, &expired);
5980 for (
const auto& entry : expired) {
5981 LogPrint(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ?
"wtx" :
"tx",
5982 entry.second.GetHash().ToString(), entry.first);
5984 for (
const GenTxid& gtxid : requestable) {
5985 if (!AlreadyHaveTx(gtxid)) {
5997 m_txrequest.ForgetTxHash(gtxid.
GetHash());
6002 if (!vGetData.empty())
6005 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.
const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
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 ...
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, Options opts)
enum ReadStatus_t ReadStatus
const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected...
static constexpr auto TXID_RELAY_DELAY
How long to delay requesting transactions via txids, if we have wtxid-relaying peers.
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
std::atomic_bool fPauseSend
static const int SERIALIZE_TRANSACTION_NO_WITNESS
A flag that is ORed into the protocol version to designate that a transaction should be (un)serialize...
invalid by consensus rules
bool HaveNumChainTxs() const
Check whether this block's and all previous blocks' transactions have been downloaded (and stored to ...
std::chrono::time_point< NodeClock > time_point
const char * BLOCKTXN
Contains a BlockTransactions.
static GenTxid Wtxid(const uint256 &hash)
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.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
ServiceFlags
nServices flags
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...
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.
#define LogPrint(category,...)
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...
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
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 ...
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
uint64_t m_addr_rate_limited
virtual void UnitTestMisbehaving(NodeId peer_id, int howmuch)=0
std::string ToString() const
ReconciliationRegisterResult
We don't have the previous block the checked one is built on.
Data structure to keep track of, and schedule, transaction downloads from peers.
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
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
bool IsMsgFilteredBlk() const
An in-memory indexed chain of blocks.
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests.cpp.
const std::optional< std::list< CTransactionRef > > m_replaced_transactions
Mempool transactions replaced by the tx.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
reverse_range< T > reverse_iterate(T &x)
invalid proof of work or time too old
const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
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...
constexpr auto GetRandMillis
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
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
bool IsFeelerConn() const
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.
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
const uint256 & GetHash() const
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
int EraseTx(const uint256 &txid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase an orphan by txid.
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid...
void SetCommonVersion(int greatest_common_version)
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
Interface for message handling.
void SetServiceFlagsIBDCache(bool state)
Set the current IBD status in order to figure out the desirable service flags.
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set. ...
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
const TxValidationState m_state
Contains information about why the transaction failed.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version ...
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
static constexpr auto NONPREF_PEER_TX_DELAY
How long to delay requesting transactions from non-preferred peers.
the block header may be on a too-little-work chain
inputs (covered by txid) failed policy rules
void ignore(size_t num_ignore)
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
const ResultType m_result_type
Result type.
uint64_t GetLocalNonce() const
bool SeenLocal(const CService &addr)
vote for a local address
transaction spends a coinbase too early, or violates locktime/sequence locks
const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
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.
const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
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.
initial value. Tx has not yet been rejected
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
enum Network GetNetwork() const
const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
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...
const std::vector< CTxIn > vin
bool HaveTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Does this peer have any work to do?
const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
Stochastic address manager.
NodeClock::time_point GetAdjustedTime()
Transaction validation functions.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
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.
int64_t CAmount
Amount in satoshis (Can be negative)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
uint256 GetBlockHash() const
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
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.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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.
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
CAmount m_fee_filter_received
const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
virtual void InitializeNode(CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state, queue any initial messages)
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
uint64_t m_addr_processed
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
Invalid by a change to consensus rules more recent than SegWit.
Scripts & signatures ok. Implies all parents are either at least VALID_SCRIPTS, or are ASSUMED_VALID...
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.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
std::vector< CTransactionRef > txn
std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval)
Return a timestamp in the future sampled from an exponential distribution (https://en.wikipedia.org/wiki/Exponential_distribution).
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.
An input of a transaction.
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 bool HasAllDesirableServiceFlags(ServiceFlags services)
A shortcut for (services & GetDesirableServiceFlags(services)) == GetDesirableServiceFlags(services)...
const uint256 & GetWitnessHash() const
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message...
const uint256 & GetHash() const
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.
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation
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
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase all orphans announced by a peer (eg, after that peer disconnects)
const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr int64_t count_microseconds(std::chrono::microseconds t)
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static constexpr SerParams V1
bool IsProxy(const CNetAddr &addr)
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
bool IsManualConn() const
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
A CService with information about it as peer.
virtual bool IgnoresIncomingTxs()=0
Whether this node ignores txs received over p2p.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
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.
#define LogPrintLevel(category, level,...)
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
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.
#define LogPrintfCategory(category,...)
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
bool ExpectServicesFromConn() const
static auto WithParams(const Params ¶ms, T &&t)
Return a wrapper around t that (de)serializes it with specified parameter params. ...
static const int DISCOURAGEMENT_THRESHOLD
Threshold for marking a node to be discouraged, e.g.
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter...
std::string ToString() const
std::atomic< bool > m_bip152_highbandwidth_to
std::vector< uint256 > vHave
virtual std::optional< std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
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.
const char * BLOCK
The block message transmits a single serialized block.
std::atomic_bool fDisconnect
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks...
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
size_t Size() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Return how many entries exist in the orphange.
Validation result for a single transaction mempool acceptance.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define Assume(val)
Assume is the identity function.
256-bit unsigned big integer.
void AddChildrenToWorkSet(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add any orphans that list a particular tx as a parent into the from peer's work set.
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, CDataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB...
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::microseconds m_ping_wait
CTransactionRef GetTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Extract a transaction from a peer's work set Returns nullptr if there are no transactions to work on...
const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
bool IsBlockOnlyConn() const
Transaction is missing a witness.
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.
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
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.
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::vector< CTransactionRef > vtx
const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids"...
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
the block's data didn't match the data committed to by the PoW
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
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.
virtual void SendPings()=0
Send ping message to all peers.
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
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.
bool AddTx(const CTransactionRef &tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a new orphan transaction.
void EraseForBlock(const CBlock &block) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase all orphans included in or invalidated by a new block.
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 int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static const int PROTOCOL_VERSION
network protocol versioning
virtual void RelayTransaction(const uint256 &txid, const uint256 &wtxid)=0
Relay transaction to all peers.
bool IsTxAvailable(size_t index) const
A block this one builds on is invalid.
#define TRACE6(context, event, a, b, c, d, e, f)
ServiceFlags GetDesirableServiceFlags(ServiceFlags services)
Gets the set of service flags which are "desirable" for a given peer.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
std::atomic< int64_t > nTimeOffset
const char * GETDATA
The getdata message requests one or more data objects from another node.
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
static constexpr auto OVERLOADED_PEER_TX_DELAY
How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT).
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.
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::atomic< int > nVersion
Invalid by a change to consensus rules more recent than SegWit.
Transaction reconciliation is a way for nodes to efficiently announce transactions.
arith_uint256 CalculateHeadersWork(const std::vector< CBlockHeader > &headers)
Return the sum of the work on a given set of headers.
std::string ConnectionTypeAsString() const
static size_t RecursiveDynamicUsage(const CScript &script)
const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< uint256, CTransactionRef >> &extra_txn)
virtual void BlockConnected(ChainstateRole role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
this node does not have a mempool so can't validate the transaction
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
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
bool IsAddrFetchConn() const
arith_uint256 GetBlockProof(const CBlockIndex &block)
A Span is an object that can refer to a contiguous sequence of objects.
const char * TX
The tx message transmits a single transaction.
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.
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...
Simple class for background tasks that should be run periodically or once "after a while"...
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT
Maximum number of in-flight transaction requests from a peer.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
full block available in blk*.dat
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
static constexpr SerParams V1_NETWORK
int64_t GetTime()
DEPRECATED, see GetTime.
int GetCommonVersion() const
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
bool HaveTx(const GenTxid >xid) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if we already have an orphan transaction (by txid or wtxid)
const std::string m_addr_name
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
static const int WTXID_RELAY_VERSION
"wtxidrelay" command for wtxid-based relay starts with this version
bool HasPermission(NetPermissionFlags permission) 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...
otherwise didn't meet our local policy rules
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).
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
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.
static GenTxid Txid(const uint256 &hash)
void LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Limit the orphanage to the given maximum.
static constexpr auto GETDATA_TX_INTERVAL
How long to wait before downloading a transaction from an additional peer.
const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
bool IsFullOutboundConn() const
#define Assert(val)
Identity function.
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 const int MAX_NUM_UNCONNECTING_HEADERS_MSGS
Maximum number of unconnecting headers announcements before DoS score.
ReachableNets g_reachable_nets
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.