193 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
227 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
230 Mutex m_misbehavior_mutex;
232 int m_misbehavior_score
GUARDED_BY(m_misbehavior_mutex){0};
234 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
237 Mutex m_block_inv_mutex;
241 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
245 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
253 std::atomic<int> m_starting_height{-1};
256 std::atomic<uint64_t> m_ping_nonce_sent{0};
258 std::atomic<std::chrono::microseconds> m_ping_start{0us};
260 std::atomic<bool> m_ping_queued{
false};
263 std::atomic<bool> m_wtxid_relay{
false};
270 std::chrono::microseconds m_next_send_feefilter{0};
280 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
282 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
293 std::set<uint256> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
296 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
298 std::atomic<std::chrono::seconds> m_last_mempool_req{0s};
301 std::chrono::microseconds m_next_inv_send_time{0};
304 std::atomic<CAmount> m_fee_filter_received{0};
310 LOCK(m_tx_relay_mutex);
312 m_tx_relay = std::make_unique<Peer::TxRelay>();
313 return m_tx_relay.get();
318 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
322 std::vector<CAddress> m_addrs_to_send;
332 std::unique_ptr<CRollingBloomFilter> m_addr_known;
347 std::atomic_bool m_addr_relay_enabled{
false};
349 bool m_getaddr_sent{
false};
351 mutable Mutex m_addr_send_times_mutex;
353 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
355 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
358 std::atomic_bool m_wants_addrv2{
false};
360 bool m_getaddr_recvd{
false};
363 double m_addr_token_bucket{1.0};
365 std::chrono::microseconds m_addr_token_timestamp{GetTime<std::chrono::microseconds>()};
367 std::atomic<uint64_t> m_addr_rate_limited{0};
369 std::atomic<uint64_t> m_addr_processed{0};
375 bool m_inv_triggered_getheaders_before_sync{
false};
378 Mutex m_getdata_requests_mutex;
380 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
386 Mutex m_headers_sync_mutex;
389 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
392 std::atomic<bool> m_sent_sendheaders{
false};
396 , m_our_services{our_services}
400 Mutex m_tx_relay_mutex;
405 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
408 using PeerRef = std::shared_ptr<Peer>;
420 uint256 hashLastUnknownBlock{};
426 int nUnconnectingHeaders{0};
428 bool fSyncStarted{
false};
430 std::chrono::microseconds m_headers_sync_timeout{0us};
432 std::chrono::microseconds m_stalling_since{0us};
433 std::list<QueuedBlock> vBlocksInFlight;
435 std::chrono::microseconds m_downloading_since{0us};
436 int nBlocksInFlight{0};
438 bool fPreferredDownload{
false};
440 bool fPreferHeaders{
false};
442 bool m_requested_hb_cmpctblocks{
false};
444 bool m_provides_cmpctblocks{
false};
470 struct ChainSyncTimeoutState {
472 std::chrono::seconds m_timeout{0s};
476 bool m_sent_getheaders{
false};
478 bool m_protect{
false};
481 ChainSyncTimeoutState m_chain_sync;
484 int64_t m_last_block_announcement{0};
487 const bool m_is_inbound;
492 CNodeState(
bool is_inbound) : m_is_inbound(is_inbound) {}
518 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex);
523 void StartScheduledTasks(
CScheduler& scheduler) override;
524 void CheckForStaleTipAndEvictPeers() override;
528 bool IgnoresIncomingTxs()
override {
return m_ignore_incoming_txs; }
531 void SetBestHeight(
int height)
override { m_best_height = height; };
534 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override 535 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex);
560 void Misbehaving(Peer& peer,
int howmuch,
const std::string& message);
573 bool via_compact_block,
const std::string& message =
"")
590 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
601 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
603 bool via_compact_block)
613 void HandleFewUnconnectingHeaders(
CNode& pfrom, Peer& peer, const
std::vector<
CBlockHeader>& headers);
615 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
634 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
649 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
664 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex* pindexLast);
666 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, const
CBlockIndex *pindexLast,
bool received_new_header,
bool may_have_more_headers);
673 void AddTxAnnouncement(const
CNode&
node, const
GenTxid& gtxid,
std::chrono::microseconds current_time)
677 void PushNodeVersion(
CNode& pnode, const Peer& peer);
683 void MaybeSendPing(
CNode& node_to, Peer& peer,
std::chrono::microseconds now);
686 void MaybeSendAddr(
CNode&
node, Peer& peer,
std::chrono::microseconds current_time);
689 void MaybeSendSendHeaders(
CNode&
node, Peer& peer);
701 void MaybeSendFeefilter(
CNode&
node, Peer& peer,
std::chrono::microseconds current_time);
713 std::atomic<
int> m_best_height{-1};
719 const bool m_ignore_incoming_txs;
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};
754 uint256 m_last_block_inv_triggering_headers_sync{};
765 std::atomic<int> m_wtxid_relay_peers{0};
773 bool AlreadyHaveTx(
const GenTxid& gtxid)
828 Mutex m_recent_confirmed_transactions_mutex;
837 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
838 std::chrono::seconds average_interval);
842 Mutex m_most_recent_block_mutex;
843 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
844 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
849 Mutex m_headers_presync_mutex;
857 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
859 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
863 std::atomic_bool m_headers_presync_should_signal{
false};
866 int m_highest_fast_announce{0};
896 std::atomic<
std::chrono::seconds> m_last_tip_update{0s};
901 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
905 void ProcessBlock(
CNode&
node, const
std::shared_ptr<const
CBlock>& block,
bool force_processing,
bool min_pow_checked);
953 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
971 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
973 const
uint256& stop_hash, uint32_t max_height_diff,
1016 bool SetupAddressRelay(const
CNode&
node, Peer& peer);
1021 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1022 if (it == m_node_states.end())
1029 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1037 static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1042 static void AddAddressKnown(Peer& peer,
const CAddress& addr)
1044 assert(peer.m_addr_known);
1045 peer.m_addr_known->insert(addr.
GetKey());
1053 assert(peer.m_addr_known);
1054 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1056 peer.m_addrs_to_send[insecure_rand.
randrange(peer.m_addrs_to_send.size())] = addr;
1058 peer.m_addrs_to_send.push_back(addr);
1063 static void AddKnownTx(Peer& peer,
const uint256& hash)
1065 auto tx_relay = peer.GetTxRelay();
1066 if (!tx_relay)
return;
1068 LOCK(tx_relay->m_tx_inventory_mutex);
1069 tx_relay->m_tx_inventory_known_filter.insert(hash);
1073 static bool CanServeBlocks(
const Peer& peer)
1080 static bool IsLimitedPeer(
const Peer& peer)
1087 static bool CanServeWitnesses(
const Peer& peer)
1092 std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1093 std::chrono::seconds average_interval)
1095 if (m_next_inv_to_inbounds.load() < now) {
1101 return m_next_inv_to_inbounds;
1104 bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1106 return mapBlocksInFlight.find(hash) != mapBlocksInFlight.end();
1109 void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1111 auto it = mapBlocksInFlight.find(hash);
1112 if (it == mapBlocksInFlight.end()) {
1117 auto [node_id, list_it] = it->second;
1119 if (from_peer && node_id != *from_peer) {
1124 CNodeState *state =
State(node_id);
1125 assert(state !=
nullptr);
1127 if (state->vBlocksInFlight.begin() == list_it) {
1129 state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
1131 state->vBlocksInFlight.erase(list_it);
1133 state->nBlocksInFlight--;
1134 if (state->nBlocksInFlight == 0) {
1136 m_peers_downloading_from--;
1138 state->m_stalling_since = 0us;
1139 mapBlocksInFlight.erase(it);
1142 bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1146 CNodeState *state =
State(nodeid);
1147 assert(state !=
nullptr);
1150 std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
1151 if (itInFlight != mapBlocksInFlight.end() && itInFlight->second.first == nodeid) {
1153 *pit = &itInFlight->second.second;
1159 RemoveBlockRequest(hash, std::nullopt);
1161 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1163 state->nBlocksInFlight++;
1164 if (state->nBlocksInFlight == 1) {
1166 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1167 m_peers_downloading_from++;
1169 itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it))).first;
1171 *pit = &itInFlight->second.second;
1176 void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1183 if (m_ignore_incoming_txs)
return;
1185 CNodeState* nodestate =
State(nodeid);
1186 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1191 int num_outbound_hb_peers = 0;
1192 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1193 if (*it == nodeid) {
1194 lNodesAnnouncingHeaderAndIDs.erase(it);
1195 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1198 CNodeState *state =
State(*it);
1199 if (state !=
nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
1201 if (nodestate->m_is_inbound) {
1204 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1205 CNodeState *remove_node =
State(lNodesAnnouncingHeaderAndIDs.front());
1206 if (remove_node !=
nullptr && !remove_node->m_is_inbound) {
1209 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1215 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1218 m_connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1221 pnodeStop->m_bip152_highbandwidth_to =
false;
1224 lNodesAnnouncingHeaderAndIDs.pop_front();
1229 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1234 bool PeerManagerImpl::TipMayBeStale()
1238 if (m_last_tip_update.load() == 0s) {
1239 m_last_tip_update = GetTime<std::chrono::seconds>();
1241 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1244 bool PeerManagerImpl::CanDirectFetch()
1246 return m_chainman.ActiveChain().Tip()->Time() >
GetAdjustedTime() - m_chainparams.GetConsensus().PowTargetSpacing() * 20;
1251 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1253 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1258 void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1259 CNodeState *state =
State(nodeid);
1260 assert(state !=
nullptr);
1262 if (!state->hashLastUnknownBlock.IsNull()) {
1263 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock);
1265 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1266 state->pindexBestKnownBlock = pindex;
1268 state->hashLastUnknownBlock.SetNull();
1273 void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1274 CNodeState *state =
State(nodeid);
1275 assert(state !=
nullptr);
1277 ProcessBlockAvailability(nodeid);
1279 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
1282 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1283 state->pindexBestKnownBlock = pindex;
1287 state->hashLastUnknownBlock = hash;
1291 void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1296 vBlocks.reserve(vBlocks.size() +
count);
1297 CNodeState *state =
State(peer.m_id);
1298 assert(state !=
nullptr);
1301 ProcessBlockAvailability(peer.m_id);
1303 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.ActiveChain().Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork <
nMinimumChainWork) {
1308 if (state->pindexLastCommonBlock ==
nullptr) {
1311 state->pindexLastCommonBlock = m_chainman.ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.ActiveChain().Height())];
1316 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1317 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1320 std::vector<const CBlockIndex*> vToFetch;
1321 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1326 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1328 while (pindexWalk->
nHeight < nMaxHeight) {
1332 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1333 vToFetch.resize(nToFetch);
1334 pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->
nHeight + nToFetch);
1335 vToFetch[nToFetch - 1] = pindexWalk;
1336 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1337 vToFetch[i - 1] = vToFetch[i]->
pprev;
1353 if (pindex->nStatus &
BLOCK_HAVE_DATA || m_chainman.ActiveChain().Contains(pindex)) {
1355 state->pindexLastCommonBlock = pindex;
1356 }
else if (!IsBlockRequested(pindex->
GetBlockHash())) {
1358 if (pindex->
nHeight > nWindowEnd) {
1360 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1362 nodeStaller = waitingfor;
1366 vBlocks.push_back(pindex);
1367 if (vBlocks.size() ==
count) {
1370 }
else if (waitingfor == -1) {
1372 waitingfor = mapBlocksInFlight[pindex->
GetBlockHash()].first;
1380 void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1382 uint64_t my_services{peer.m_our_services};
1383 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1385 const int nNodeStartingHeight{m_best_height};
1394 your_services, addr_you,
1399 LogPrint(
BCLog::NET,
"send version message: version %d, blocks=%d, them=%s, txrelay=%d, peer=%d\n",
PROTOCOL_VERSION, nNodeStartingHeight, addr_you.
ToString(), tx_relay, nodeid);
1405 void PeerManagerImpl::AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
1413 const CNodeState* state =
State(nodeid);
1423 const bool preferred = state->fPreferredDownload;
1429 m_txrequest.ReceivedInv(nodeid, gtxid, preferred, current_time + delay);
1432 void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1436 if (state) state->m_last_block_announcement = time_in_seconds;
1444 m_node_states.emplace_hint(m_node_states.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(
node.IsInboundConn()));
1445 assert(m_txrequest.Count(nodeid) == 0);
1447 PeerRef peer = std::make_shared<Peer>(nodeid, our_services);
1450 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1452 if (!
node.IsInboundConn()) {
1453 PushNodeVersion(
node, *peer);
1457 void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1459 std::set<uint256> unbroadcast_txids = m_mempool.GetUnbroadcastTxs();
1461 for (
const auto& txid : unbroadcast_txids) {
1464 if (tx !=
nullptr) {
1467 m_mempool.RemoveUnbroadcastTx(txid,
true);
1473 const std::chrono::milliseconds delta = 10min +
GetRandMillis(5min);
1474 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1477 void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1489 PeerRef peer = RemovePeer(nodeid);
1491 misbehavior =
WITH_LOCK(peer->m_misbehavior_mutex,
return peer->m_misbehavior_score);
1492 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1493 assert(m_wtxid_relay_peers >= 0);
1495 CNodeState *state =
State(nodeid);
1496 assert(state !=
nullptr);
1498 if (state->fSyncStarted)
1501 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1502 mapBlocksInFlight.erase(entry.pindex->GetBlockHash());
1505 m_txrequest.DisconnectedPeer(nodeid);
1506 m_num_preferred_download_peers -= state->fPreferredDownload;
1507 m_peers_downloading_from -= (state->nBlocksInFlight != 0);
1508 assert(m_peers_downloading_from >= 0);
1509 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1510 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1512 m_node_states.erase(nodeid);
1514 if (m_node_states.empty()) {
1516 assert(mapBlocksInFlight.empty());
1517 assert(m_num_preferred_download_peers == 0);
1518 assert(m_peers_downloading_from == 0);
1519 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1520 assert(m_wtxid_relay_peers == 0);
1521 assert(m_txrequest.Size() == 0);
1525 if (
node.fSuccessfullyConnected && misbehavior == 0 &&
1526 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1530 m_addrman.Connected(
node.addr);
1533 LOCK(m_headers_presync_mutex);
1534 m_headers_presync_stats.erase(nodeid);
1539 PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const 1542 auto it = m_peer_map.find(
id);
1543 return it != m_peer_map.end() ? it->second :
nullptr;
1546 PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1550 auto it = m_peer_map.find(
id);
1551 if (it != m_peer_map.end()) {
1552 ret = std::move(it->second);
1553 m_peer_map.erase(it);
1562 const CNodeState* state =
State(nodeid);
1563 if (state ==
nullptr)
1565 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1566 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1567 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1573 PeerRef peer = GetPeerRef(nodeid);
1574 if (peer ==
nullptr)
return false;
1583 auto ping_wait{0us};
1584 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1585 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1588 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1601 LOCK(peer->m_headers_sync_mutex);
1602 if (peer->m_headers_sync) {
1610 void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1613 if (max_extra_txn <= 0)
1615 if (!vExtraTxnForCompact.size())
1616 vExtraTxnForCompact.resize(max_extra_txn);
1617 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1618 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % max_extra_txn;
1621 void PeerManagerImpl::Misbehaving(Peer& peer,
int howmuch,
const std::string& message)
1625 LOCK(peer.m_misbehavior_mutex);
1626 const int score_before{peer.m_misbehavior_score};
1627 peer.m_misbehavior_score += howmuch;
1628 const int score_now{peer.m_misbehavior_score};
1630 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1631 std::string warning;
1634 warning =
" DISCOURAGE THRESHOLD EXCEEDED";
1635 peer.m_should_discourage =
true;
1639 peer.m_id, score_before, score_now, warning, message_prefixed);
1643 bool via_compact_block,
const std::string& message)
1645 PeerRef peer{GetPeerRef(nodeid)};
1656 if (!via_compact_block) {
1657 if (peer) Misbehaving(*peer, 100, message);
1664 CNodeState *node_state =
State(nodeid);
1665 if (node_state ==
nullptr) {
1671 if (!via_compact_block && !node_state->m_is_inbound) {
1672 if (peer) Misbehaving(*peer, 100, message);
1680 if (peer) Misbehaving(*peer, 100, message);
1685 if (peer) Misbehaving(*peer, 10, message);
1691 if (message !=
"") {
1697 bool PeerManagerImpl::MaybePunishNodeForTx(
NodeId nodeid,
const TxValidationState& state,
const std::string& message)
1699 PeerRef peer{GetPeerRef(nodeid)};
1705 if (peer) Misbehaving(*peer, 100, message);
1720 if (message !=
"") {
1726 bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1729 if (m_chainman.ActiveChain().Contains(pindex))
return true;
1735 std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1738 if (
fReindex)
return "Reindexing...";
1741 PeerRef peer = GetPeerRef(peer_id);
1742 if (peer ==
nullptr)
return "Peer does not exist";
1745 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1752 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1759 bool success = m_connman.ForNode(peer_id, [
this, &invs](
CNode*
node) {
1765 if (!success)
return "Peer not fully connected";
1769 return std::nullopt;
1776 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, ignore_incoming_txs);
1782 : m_chainparams(chainman.GetParams()),
1786 m_chainman(chainman),
1788 m_ignore_incoming_txs(ignore_incoming_txs)
1792 void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1802 const std::chrono::milliseconds delta = 10min +
GetRandMillis(5min);
1803 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1811 void PeerManagerImpl::BlockConnected(
const std::shared_ptr<const CBlock>& pblock,
const CBlockIndex* pindex)
1813 m_orphanage.EraseForBlock(*pblock);
1814 m_last_tip_update = GetTime<std::chrono::seconds>();
1817 LOCK(m_recent_confirmed_transactions_mutex);
1818 for (
const auto& ptx : pblock->vtx) {
1819 m_recent_confirmed_transactions.insert(ptx->GetHash());
1820 if (ptx->GetHash() != ptx->GetWitnessHash()) {
1821 m_recent_confirmed_transactions.insert(ptx->GetWitnessHash());
1827 for (
const auto& ptx : pblock->vtx) {
1828 m_txrequest.ForgetTxHash(ptx->GetHash());
1829 m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
1834 void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1844 LOCK(m_recent_confirmed_transactions_mutex);
1845 m_recent_confirmed_transactions.reset();
1852 void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1854 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock);
1859 if (pindex->
nHeight <= m_highest_fast_announce)
1861 m_highest_fast_announce = pindex->
nHeight;
1865 uint256 hashBlock(pblock->GetHash());
1866 const std::shared_future<CSerializedNetMsg> lazy_ser{
1870 LOCK(m_most_recent_block_mutex);
1871 m_most_recent_block_hash = hashBlock;
1872 m_most_recent_block = pblock;
1873 m_most_recent_compact_block = pcmpctblock;
1881 ProcessBlockAvailability(pnode->
GetId());
1885 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
1887 LogPrint(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
1888 hashBlock.ToString(), pnode->
GetId());
1891 m_connman.PushMessage(pnode, ser_cmpctblock.Copy());
1892 state.pindexBestHeaderSent = pindex;
1901 void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
1903 SetBestHeight(pindexNew->
nHeight);
1907 if (fInitialDownload)
return;
1910 std::vector<uint256> vHashes;
1912 while (pindexToAnnounce != pindexFork) {
1914 pindexToAnnounce = pindexToAnnounce->
pprev;
1924 for (
auto& it : m_peer_map) {
1925 Peer& peer = *it.second;
1926 LOCK(peer.m_block_inv_mutex);
1928 peer.m_blocks_for_headers_relay.push_back(hash);
1933 m_connman.WakeMessageHandler();
1945 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
1950 it != mapBlockSource.end() &&
1951 State(it->second.first)) {
1952 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
1961 !m_chainman.ActiveChainstate().IsInitialBlockDownload() &&
1962 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
1963 if (it != mapBlockSource.end()) {
1964 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
1967 if (it != mapBlockSource.end())
1968 mapBlockSource.erase(it);
1977 bool PeerManagerImpl::AlreadyHaveTx(
const GenTxid& gtxid)
1979 if (m_chainman.ActiveChain().Tip()->GetBlockHash() != hashRecentRejectsChainTip) {
1984 hashRecentRejectsChainTip = m_chainman.ActiveChain().Tip()->GetBlockHash();
1985 m_recent_rejects.reset();
1990 if (m_orphanage.HaveTx(gtxid))
return true;
1993 LOCK(m_recent_confirmed_transactions_mutex);
1994 if (m_recent_confirmed_transactions.contains(hash))
return true;
1997 return m_recent_rejects.contains(hash) || m_mempool.exists(gtxid);
2000 bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2002 return m_chainman.m_blockman.LookupBlockIndex(block_hash) !=
nullptr;
2005 void PeerManagerImpl::SendPings()
2008 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2011 void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2014 for(
auto& it : m_peer_map) {
2015 Peer& peer = *it.second;
2016 auto tx_relay = peer.GetTxRelay();
2017 if (!tx_relay)
continue;
2019 LOCK(tx_relay->m_tx_inventory_mutex);
2025 if (tx_relay->m_next_inv_send_time == 0s)
continue;
2027 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2028 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2029 tx_relay->m_tx_inventory_to_send.insert(hash);
2034 void PeerManagerImpl::RelayAddress(
NodeId originator,
2050 const auto current_time{GetTime<std::chrono::seconds>()};
2059 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2061 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2062 assert(nRelayNodes <= best.size());
2066 for (
auto& [
id, peer] : m_peer_map) {
2067 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2069 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2070 if (hashKey > best[i].first) {
2071 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2072 best[i] = std::make_pair(hashKey, peer.get());
2079 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2080 PushAddress(*best[i].second, addr, insecure_rand);
2084 void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2086 std::shared_ptr<const CBlock> a_recent_block;
2087 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2089 LOCK(m_most_recent_block_mutex);
2090 a_recent_block = m_most_recent_block;
2091 a_recent_compact_block = m_most_recent_compact_block;
2094 bool need_activate_chain =
false;
2097 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.
hash);
2106 need_activate_chain =
true;
2110 if (need_activate_chain) {
2112 if (!m_chainman.ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2118 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.
hash);
2122 if (!BlockRequestAllowed(pindex)) {
2123 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2128 if (m_connman.OutboundTargetReached(
true) &&
2140 LogPrint(
BCLog::NET,
"Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.
GetId());
2150 std::shared_ptr<const CBlock> pblock;
2151 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2152 pblock = a_recent_block;
2156 std::vector<uint8_t> block_data;
2158 assert(!
"cannot load block from disk");
2164 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2166 assert(!
"cannot load block from disk");
2168 pblock = pblockRead;
2176 bool sendMerkleBlock =
false;
2178 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2179 LOCK(tx_relay->m_bloom_filter_mutex);
2180 if (tx_relay->m_bloom_filter) {
2181 sendMerkleBlock =
true;
2182 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2185 if (sendMerkleBlock) {
2193 typedef std::pair<unsigned int, uint256> PairType;
2205 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2218 LOCK(peer.m_block_inv_mutex);
2220 if (inv.
hash == peer.m_continuation_block) {
2224 std::vector<CInv> vInv;
2225 vInv.push_back(
CInv(
MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash()));
2227 peer.m_continuation_block.SetNull();
2232 CTransactionRef PeerManagerImpl::FindTxForGetData(
const CNode& peer,
const GenTxid& gtxid,
const std::chrono::seconds mempool_req,
const std::chrono::seconds now)
2234 auto txinfo = m_mempool.info(gtxid);
2240 return std::move(txinfo.tx);
2249 if (txinfo.tx)
return std::move(txinfo.tx);
2251 auto mi = mapRelay.find(gtxid.
GetHash());
2252 if (mi != mapRelay.end())
return mi->second;
2259 void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2263 auto tx_relay = peer.GetTxRelay();
2265 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2266 std::vector<CInv> vNotFound;
2269 const auto now{GetTime<std::chrono::seconds>()};
2271 const auto mempool_req = tx_relay !=
nullptr ? tx_relay->m_last_mempool_req.load() : std::chrono::seconds::min();
2276 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2277 if (interruptMsgProc)
return;
2282 const CInv &inv = *it++;
2284 if (tx_relay ==
nullptr) {
2294 m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags,
NetMsgType::TX, *tx));
2295 m_mempool.RemoveUnbroadcastTx(tx->GetHash());
2297 std::vector<uint256> parent_ids_to_add;
2300 auto txiter = m_mempool.GetIter(tx->GetHash());
2303 parent_ids_to_add.reserve(parents.size());
2306 parent_ids_to_add.push_back(parent.GetTx().GetHash());
2311 for (
const uint256& parent_txid : parent_ids_to_add) {
2313 if (
WITH_LOCK(tx_relay->m_tx_inventory_mutex,
return !tx_relay->m_tx_inventory_known_filter.contains(parent_txid))) {
2315 State(pfrom.
GetId())->m_recently_announced_invs.insert(parent_txid);
2319 vNotFound.push_back(inv);
2325 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2326 const CInv &inv = *it++;
2328 ProcessGetBlockData(pfrom, peer, inv);
2334 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2336 if (!vNotFound.empty()) {
2355 uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const 2357 uint32_t nFetchFlags = 0;
2358 if (CanServeWitnesses(peer)) {
2367 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2369 Misbehaving(peer, 100,
"getblocktxn with out-of-bounds tx indices");
2379 bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2383 Misbehaving(peer, 100,
"header with invalid proof of work");
2388 if (!CheckHeadersAreContinuous(headers)) {
2389 Misbehaving(peer, 20,
"non-continuous headers sequence");
2399 if (m_chainman.ActiveChain().Tip() !=
nullptr) {
2400 const CBlockIndex *tip = m_chainman.ActiveChain().Tip();
2420 void PeerManagerImpl::HandleFewUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2421 const std::vector<CBlockHeader>& headers)
2426 CNodeState *nodestate =
State(pfrom.
GetId());
2428 nodestate->nUnconnectingHeaders++;
2430 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), peer)) {
2431 LogPrint(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
2433 headers[0].hashPrevBlock.ToString(),
2434 m_chainman.m_best_header->nHeight,
2435 pfrom.
GetId(), nodestate->nUnconnectingHeaders);
2440 UpdateBlockAvailability(pfrom.
GetId(), headers.back().GetHash());
2445 Misbehaving(peer, 20,
strprintf(
"%d non-connecting headers", nodestate->nUnconnectingHeaders));
2449 bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const 2453 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2456 hashLastBlock = header.GetHash();
2461 bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2463 if (peer.m_headers_sync) {
2464 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() ==
MAX_HEADERS_RESULTS);
2465 if (result.request_more) {
2466 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2468 Assume(!locator.vHave.empty());
2469 if (!locator.vHave.empty()) {
2476 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2477 if (sent_getheaders) {
2479 locator.vHave.front().ToString(), pfrom.
GetId());
2481 LogPrint(
BCLog::NET,
"error sending next getheaders (from %s) to continue sync with peer=%d\n",
2482 locator.vHave.front().ToString(), pfrom.
GetId());
2488 peer.m_headers_sync.reset(
nullptr);
2493 LOCK(m_headers_presync_mutex);
2494 m_headers_presync_stats.erase(pfrom.
GetId());
2497 HeadersPresyncStats stats;
2498 stats.first = peer.m_headers_sync->GetPresyncWork();
2500 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2501 peer.m_headers_sync->GetPresyncTime()};
2505 LOCK(m_headers_presync_mutex);
2506 m_headers_presync_stats[pfrom.
GetId()] = stats;
2507 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2508 bool best_updated =
false;
2509 if (best_it == m_headers_presync_stats.end()) {
2513 const HeadersPresyncStats* stat_best{
nullptr};
2514 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2515 if (!stat_best || stat > *stat_best) {
2520 m_headers_presync_bestpeer = peer_best;
2521 best_updated = (peer_best == pfrom.
GetId());
2522 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2524 m_headers_presync_bestpeer = pfrom.
GetId();
2525 best_updated =
true;
2527 if (best_updated && stats.second.has_value()) {
2529 m_headers_presync_should_signal =
true;
2533 if (result.success) {
2536 headers.swap(result.pow_validated_headers);
2539 return result.success;
2547 bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2554 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2558 if (total_work < minimum_chain_work) {
2572 LOCK(peer.m_headers_sync_mutex);
2573 peer.m_headers_sync.reset(
new HeadersSyncState(peer.m_id, m_chainparams.GetConsensus(),
2574 chain_start_header, minimum_chain_work));
2578 if (!IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers)) {
2580 peer.m_headers_sync.reset(
nullptr);
2581 LOCK(m_headers_presync_mutex);
2582 m_headers_presync_stats.erase(peer.m_id);
2597 bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2599 if (header ==
nullptr) {
2601 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2603 }
else if (m_chainman.ActiveChain().Contains(header)) {
2609 bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2619 peer.m_last_getheaders_timestamp = current_time;
2630 void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex* pindexLast)
2635 CNodeState *nodestate =
State(pfrom.
GetId());
2639 std::vector<const CBlockIndex*> vToFetch;
2647 vToFetch.push_back(pindexWalk);
2649 pindexWalk = pindexWalk->
pprev;
2655 if (!m_chainman.ActiveChain().Contains(pindexWalk)) {
2660 std::vector<CInv> vGetData;
2667 uint32_t nFetchFlags = GetFetchFlags(peer);
2669 BlockRequested(pfrom.
GetId(), *pindex);
2673 if (vGetData.size() > 1) {
2677 if (vGetData.size() > 0) {
2678 if (!m_ignore_incoming_txs &&
2679 nodestate->m_provides_cmpctblocks &&
2680 vGetData.size() == 1 &&
2681 mapBlocksInFlight.size() == 1 &&
2697 void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom,
2698 const CBlockIndex *pindexLast,
bool received_new_header,
bool may_have_more_headers)
2701 CNodeState *nodestate =
State(pfrom.
GetId());
2702 if (nodestate->nUnconnectingHeaders > 0) {
2703 LogPrint(
BCLog::NET,
"peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom.
GetId(), nodestate->nUnconnectingHeaders);
2705 nodestate->nUnconnectingHeaders = 0;
2714 if (received_new_header && pindexLast->
nChainWork > m_chainman.ActiveChain().Tip()->nChainWork) {
2715 nodestate->m_last_block_announcement =
GetTime();
2720 if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && !may_have_more_headers) {
2723 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork <
nMinimumChainWork) {
2733 LogPrintf(
"Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.
GetId());
2745 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) {
2747 nodestate->m_chain_sync.m_protect =
true;
2748 ++m_outbound_peers_with_protect_from_disconnect;
2753 void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2754 std::vector<CBlockHeader>&& headers,
2755 bool via_compact_block)
2757 size_t nCount = headers.size();
2764 LOCK(peer.m_headers_sync_mutex);
2765 if (peer.m_headers_sync) {
2766 peer.m_headers_sync.reset(
nullptr);
2767 LOCK(m_headers_presync_mutex);
2768 m_headers_presync_stats.erase(pfrom.
GetId());
2777 if (!CheckHeadersPoW(headers, m_chainparams.GetConsensus(), peer)) {
2792 bool already_validated_work =
false;
2795 bool have_headers_sync =
false;
2797 LOCK(peer.m_headers_sync_mutex);
2799 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2811 if (headers.empty()) {
2815 have_headers_sync = !!peer.m_headers_sync;
2819 const CBlockIndex *chain_start_header{
WITH_LOCK(::
cs_main,
return m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock))};
2820 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2822 if (!headers_connect_blockindex) {
2827 HandleFewUnconnectingHeaders(pfrom, peer, headers);
2829 Misbehaving(peer, 10,
"invalid header received");
2841 last_received_header = m_chainman.m_blockman.LookupBlockIndex(headers.back().GetHash());
2842 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2843 already_validated_work =
true;
2851 already_validated_work =
true;
2857 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2858 chain_start_header, headers)) {
2870 bool received_new_header{last_received_header ==
nullptr};
2874 if (!m_chainman.ProcessNewBlockHeaders(headers,
true, state, &pindexLast)) {
2876 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2885 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
2887 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2891 UpdatePeerStateForReceivedHeaders(pfrom, pindexLast, received_new_header, nCount ==
MAX_HEADERS_RESULTS);
2894 HeadersDirectFetchBlocks(pfrom, peer, pindexLast);
2907 void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
2912 while (!orphan_work_set.empty()) {
2914 orphan_work_set.erase(orphan_work_set.begin());
2916 const auto [porphanTx, from_peer] = m_orphanage.
GetTx(orphanHash);
2917 if (porphanTx ==
nullptr)
continue;
2924 RelayTransaction(orphanHash, porphanTx->GetWitnessHash());
2926 m_orphanage.
EraseTx(orphanHash);
2928 AddToCompactExtraTransactions(removedTx);
2938 MaybePunishNodeForTx(from_peer, state);
2957 m_recent_rejects.insert(porphanTx->GetWitnessHash());
2969 m_recent_rejects.insert(porphanTx->GetHash());
2972 m_orphanage.
EraseTx(orphanHash);
2978 bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
2980 const uint256& stop_hash, uint32_t max_height_diff,
2984 const bool supported_filter_type =
2987 if (!supported_filter_type) {
2989 node.GetId(),
static_cast<uint8_t
>(filter_type));
2990 node.fDisconnect =
true;
2996 stop_index = m_chainman.m_blockman.LookupBlockIndex(stop_hash);
2999 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3002 node.fDisconnect =
true;
3007 uint32_t stop_height = stop_index->
nHeight;
3008 if (start_height > stop_height) {
3010 "start height %d and stop height %d\n",
3011 node.GetId(), start_height, stop_height);
3012 node.fDisconnect =
true;
3015 if (stop_height - start_height >= max_height_diff) {
3017 node.GetId(), stop_height - start_height + 1, max_height_diff);
3018 node.fDisconnect =
true;
3023 if (!filter_index) {
3033 uint8_t filter_type_ser;
3034 uint32_t start_height;
3037 vRecv >> filter_type_ser >> start_height >> stop_hash;
3043 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3048 std::vector<BlockFilter> filters;
3050 LogPrint(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3055 for (
const auto& filter : filters) {
3058 m_connman.PushMessage(&
node, std::move(msg));
3064 uint8_t filter_type_ser;
3065 uint32_t start_height;
3068 vRecv >> filter_type_ser >> start_height >> stop_hash;
3074 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3080 if (start_height > 0) {
3082 stop_index->
GetAncestor(static_cast<int>(start_height - 1));
3084 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3090 std::vector<uint256> filter_hashes;
3092 LogPrint(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3103 m_connman.PushMessage(&
node, std::move(msg));
3108 uint8_t filter_type_ser;
3111 vRecv >> filter_type_ser >> stop_hash;
3117 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3118 std::numeric_limits<uint32_t>::max(),
3119 stop_index, filter_index)) {
3127 for (
int i = headers.size() - 1; i >= 0; i--) {
3132 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3143 m_connman.PushMessage(&
node, std::move(msg));
3146 void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked)
3148 bool new_block{
false};
3149 m_chainman.ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3151 node.m_last_block_time = GetTime<std::chrono::seconds>();
3156 RemoveBlockRequest(block->GetHash(), std::nullopt);
3159 mapBlockSource.erase(block->GetHash());
3163 void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
CDataStream& vRecv,
3164 const std::chrono::microseconds time_received,
3165 const std::atomic<bool>& interruptMsgProc)
3169 PeerRef peer = GetPeerRef(pfrom.
GetId());
3170 if (peer ==
nullptr)
return;
3180 uint64_t nNonce = 1;
3183 std::string cleanSubVer;
3184 int starting_height = -1;
3187 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3195 m_addrman.SetServices(pfrom.
addr, nServices);
3211 if (!vRecv.
empty()) {
3219 if (!vRecv.
empty()) {
3220 std::string strSubVer;
3224 if (!vRecv.
empty()) {
3225 vRecv >> starting_height;
3230 if (pfrom.
IsInboundConn() && !m_connman.CheckIncomingNonce(nNonce))
3245 PushNodeVersion(pfrom, *peer);
3260 if (greatest_common_version >= 70016) {
3271 peer->m_their_services = nServices;
3275 pfrom.cleanSubVer = cleanSubVer;
3277 peer->m_starting_height = starting_height;
3284 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3285 auto*
const tx_relay = peer->SetTxRelay();
3287 LOCK(tx_relay->m_bloom_filter_mutex);
3288 tx_relay->m_relay_txs = fRelay;
3298 m_num_preferred_download_peers += state->fPreferredDownload;
3302 if (!pfrom.
IsInboundConn() && SetupAddressRelay(pfrom, *peer)) {
3314 if (
fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload())
3321 PushAddress(*peer, addr, insecure_rand);
3329 PushAddress(*peer, addr, insecure_rand);
3335 peer->m_getaddr_sent =
true;
3356 m_addrman.Good(pfrom.
addr);
3359 std::string remoteAddr;
3363 LogPrint(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s\n",
3365 peer->m_starting_height, addrMe.ToString(), fRelay, pfrom.
GetId(),
3368 int64_t nTimeOffset = nTime -
GetTime();
3377 if (greatest_common_version <= 70012) {
3378 CDataStream finalAlert(
ParseHex(
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"),
SER_NETWORK,
PROTOCOL_VERSION);
3379 m_connman.PushMessage(&pfrom,
CNetMsgMaker(greatest_common_version).Make(
"alert", finalAlert));
3406 LogPrintf(
"New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n",
3407 pfrom.
nVersion.load(), peer->m_starting_height,
3421 if (
auto tx_relay = peer->GetTxRelay()) {
3430 tx_relay->m_tx_inventory_mutex,
3431 return tx_relay->m_tx_inventory_to_send.empty() &&
3432 tx_relay->m_next_inv_send_time == 0s));
3446 bool sendcmpct_hb{
false};
3447 uint64_t sendcmpct_version{0};
3448 vRecv >> sendcmpct_hb >> sendcmpct_version;
3454 CNodeState* nodestate =
State(pfrom.
GetId());
3455 nodestate->m_provides_cmpctblocks =
true;
3456 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3473 if (!peer->m_wtxid_relay) {
3474 peer->m_wtxid_relay =
true;
3475 m_wtxid_relay_peers++;
3494 peer->m_wants_addrv2 =
true;
3512 std::vector<CAddress> vAddr;
3516 if (!SetupAddressRelay(pfrom, *peer)) {
3523 Misbehaving(*peer, 20,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3528 std::vector<CAddress> vAddrOk;
3529 const auto current_a_time{Now<NodeSeconds>()};
3532 const auto current_time{GetTime<std::chrono::microseconds>()};
3535 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3539 peer->m_addr_token_timestamp = current_time;
3542 uint64_t num_proc = 0;
3543 uint64_t num_rate_limit = 0;
3547 if (interruptMsgProc)
3551 if (peer->m_addr_token_bucket < 1.0) {
3557 peer->m_addr_token_bucket -= 1.0;
3566 addr.
nTime = current_a_time - 5 * 24h;
3568 AddAddressKnown(*peer, addr);
3569 if (m_banman && (m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr))) {
3575 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3577 RelayAddress(pfrom.
GetId(), addr, fReachable);
3581 vAddrOk.push_back(addr);
3583 peer->m_addr_processed += num_proc;
3584 peer->m_addr_rate_limited += num_rate_limit;
3585 LogPrint(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3586 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3588 m_addrman.Add(vAddrOk, pfrom.
addr, 2h);
3589 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3600 std::vector<CInv> vInv;
3604 Misbehaving(*peer, 20,
strprintf(
"inv message size = %u", vInv.size()));
3608 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3612 const auto current_time{GetTime<std::chrono::microseconds>()};
3615 for (
CInv& inv : vInv) {
3616 if (interruptMsgProc)
return;
3621 if (peer->m_wtxid_relay) {
3628 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3631 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3639 best_block = &inv.
hash;
3642 if (reject_tx_invs) {
3648 const bool fAlreadyHave = AlreadyHaveTx(gtxid);
3651 AddKnownTx(*peer, inv.
hash);
3652 if (!fAlreadyHave && !m_chainman.ActiveChainstate().IsInitialBlockDownload()) {
3653 AddTxAnnouncement(pfrom, gtxid, current_time);
3660 if (best_block !=
nullptr) {
3672 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
3673 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
3675 m_chainman.m_best_header->nHeight, best_block->ToString(),
3678 if (!state.fSyncStarted) {
3679 peer->m_inv_triggered_getheaders_before_sync =
true;
3683 m_last_block_inv_triggering_headers_sync = *best_block;
3692 std::vector<CInv> vInv;
3696 Misbehaving(*peer, 20,
strprintf(
"getdata message size = %u", vInv.size()));
3702 if (vInv.size() > 0) {
3707 LOCK(peer->m_getdata_requests_mutex);
3708 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
3709 ProcessGetData(pfrom, *peer, interruptMsgProc);
3718 vRecv >> locator >> hashStop;
3734 std::shared_ptr<const CBlock> a_recent_block;
3736 LOCK(m_most_recent_block_mutex);
3737 a_recent_block = m_most_recent_block;
3740 if (!m_chainman.ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
3748 const CBlockIndex* pindex = m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
3752 pindex = m_chainman.ActiveChain().Next(pindex);
3754 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());
3755 for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex))
3764 const int nPrunedBlocksLikelyToHave =
MIN_BLOCKS_TO_KEEP - 3600 / m_chainparams.GetConsensus().nPowTargetSpacing;
3771 if (--nLimit <= 0) {
3775 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
3786 std::shared_ptr<const CBlock> recent_block;
3788 LOCK(m_most_recent_block_mutex);
3789 if (m_most_recent_block_hash == req.blockhash)
3790 recent_block = m_most_recent_block;
3794 SendBlockTransactions(pfrom, *peer, *recent_block, req);
3801 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(req.blockhash);
3812 SendBlockTransactions(pfrom, *peer, block, req);
3826 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
3834 vRecv >> locator >> hashStop;
3856 if (m_chainman.ActiveTip() ==
nullptr ||
3858 LogPrint(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
3865 CNodeState *nodestate =
State(pfrom.
GetId());
3870 pindex = m_chainman.m_blockman.LookupBlockIndex(hashStop);
3875 if (!BlockRequestAllowed(pindex)) {
3876 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
3883 pindex = m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
3885 pindex = m_chainman.ActiveChain().Next(pindex);
3889 std::vector<CBlock> vHeaders;
3891 LogPrint(
BCLog::NET,
"getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), pfrom.
GetId());
3892 for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex))
3894 vHeaders.push_back(pindex->GetBlockHeader());
3895 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
3910 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.ActiveChain().Tip();
3916 if (RejectIncomingTxs(pfrom)) {
3925 if (m_chainman.ActiveChainstate().IsInitialBlockDownload())
return;
3931 const uint256& txid = ptx->GetHash();
3932 const uint256& wtxid = ptx->GetWitnessHash();
3934 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
3935 AddKnownTx(*peer, hash);
3936 if (peer->m_wtxid_relay && txid != wtxid) {
3942 AddKnownTx(*peer, txid);
3947 m_txrequest.ReceivedResponse(pfrom.
GetId(), txid);
3948 if (tx.
HasWitness()) m_txrequest.ReceivedResponse(pfrom.
GetId(), wtxid);
3983 m_txrequest.ForgetTxHash(tx.
GetHash());
3993 m_mempool.size(), m_mempool.DynamicMemoryUsage() / 1000);
3996 AddToCompactExtraTransactions(removedTx);
4000 ProcessOrphanTx(peer->m_orphan_work_set);
4004 bool fRejectedParents =
false;
4008 std::vector<uint256> unique_parents;
4009 unique_parents.reserve(tx.
vin.size());
4014 std::sort(unique_parents.begin(), unique_parents.end());
4015 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
4016 for (
const uint256& parent_txid : unique_parents) {
4017 if (m_recent_rejects.contains(parent_txid)) {
4018 fRejectedParents =
true;
4022 if (!fRejectedParents) {
4023 const auto current_time{GetTime<std::chrono::microseconds>()};
4025 for (
const uint256& parent_txid : unique_parents) {
4032 AddKnownTx(*peer, parent_txid);
4033 if (!AlreadyHaveTx(gtxid)) AddTxAnnouncement(pfrom, gtxid, current_time);
4037 AddToCompactExtraTransactions(ptx);
4041 m_txrequest.ForgetTxHash(tx.
GetHash());
4055 m_recent_rejects.insert(tx.
GetHash());
4057 m_txrequest.ForgetTxHash(tx.
GetHash());
4086 m_recent_rejects.insert(tx.
GetHash());
4087 m_txrequest.ForgetTxHash(tx.
GetHash());
4090 AddToCompactExtraTransactions(ptx);
4116 MaybePunishNodeForTx(pfrom.
GetId(), state);
4130 vRecv >> cmpctblock;
4132 bool received_new_header =
false;
4137 const CBlockIndex* prev_block = m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock);
4140 if (!m_chainman.ActiveChainstate().IsInitialBlockDownload()) {
4141 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4150 if (!m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.GetHash())) {
4151 received_new_header =
true;
4157 if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header},
true, state, &pindex)) {
4159 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4168 bool fProcessBLOCKTXN =
false;
4173 bool fRevertToHeaderProcessing =
false;
4177 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4178 bool fBlockReconstructed =
false;
4186 CNodeState *nodestate =
State(pfrom.
GetId());
4190 if (received_new_header && pindex->
nChainWork > m_chainman.ActiveChain().Tip()->nChainWork) {
4191 nodestate->m_last_block_announcement =
GetTime();
4194 std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator blockInFlightIt = mapBlocksInFlight.find(pindex->
GetBlockHash());
4195 bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end();
4200 if (pindex->
nChainWork <= m_chainman.ActiveChain().Tip()->nChainWork ||
4202 if (fAlreadyInFlight) {
4205 std::vector<CInv> vInv(1);
4206 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), cmpctblock.header.GetHash());
4213 if (!fAlreadyInFlight && !CanDirectFetch()) {
4219 if (pindex->
nHeight <= m_chainman.ActiveChain().Height() + 2) {
4221 (fAlreadyInFlight && blockInFlightIt->second.first == pfrom.
GetId())) {
4222 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4223 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4224 if (!(*queuedBlockIt)->partialBlock)
4237 Misbehaving(*peer, 100,
"invalid compact block");
4241 std::vector<CInv> vInv(1);
4242 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), cmpctblock.header.GetHash());
4248 for (
size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {
4255 txn.
blockhash = cmpctblock.header.GetHash();
4257 fProcessBLOCKTXN =
true;
4269 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4274 std::vector<CTransactionRef> dummy;
4275 status = tempBlock.FillBlock(*pblock, dummy);
4277 fBlockReconstructed =
true;
4281 if (fAlreadyInFlight) {
4284 std::vector<CInv> vInv(1);
4285 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), cmpctblock.header.GetHash());
4290 fRevertToHeaderProcessing =
true;
4295 if (fProcessBLOCKTXN) {
4296 return ProcessMessage(pfrom,
NetMsgType::BLOCKTXN, blockTxnMsg, time_received, interruptMsgProc);
4299 if (fRevertToHeaderProcessing) {
4305 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.header},
true);
4308 if (fBlockReconstructed) {
4313 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4324 ProcessBlock(pfrom, pblock,
true,
true);
4331 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4348 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4349 bool fBlockRead =
false;
4353 std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator it = mapBlocksInFlight.find(resp.blockhash);
4354 if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock ||
4355 it->second.first != pfrom.
GetId()) {
4363 RemoveBlockRequest(resp.blockhash, pfrom.
GetId());
4364 Misbehaving(*peer, 100,
"invalid compact block/non-matching block transactions");
4368 std::vector<CInv> invs;
4369 invs.push_back(
CInv(
MSG_BLOCK | GetFetchFlags(*peer), resp.blockhash));
4389 RemoveBlockRequest(resp.blockhash, pfrom.
GetId());
4397 mapBlockSource.emplace(resp.blockhash, std::make_pair(pfrom.
GetId(),
false));
4407 ProcessBlock(pfrom, pblock,
true,
true);
4422 peer->m_last_getheaders_timestamp = {};
4424 std::vector<CBlockHeader> headers;
4429 Misbehaving(*peer, 20,
strprintf(
"headers message size = %u", nCount));
4432 headers.resize(nCount);
4433 for (
unsigned int n = 0; n < nCount; n++) {
4434 vRecv >> headers[n];
4438 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4442 if (m_headers_presync_should_signal.exchange(
false)) {
4443 HeadersPresyncStats stats;
4445 LOCK(m_headers_presync_mutex);
4446 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4447 if (it != m_headers_presync_stats.end()) stats = it->second;
4450 m_chainman.ReportHeadersPresync(stats.first, stats.second->first, stats.second->second);
4465 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4470 bool forceProcessing =
false;
4471 const uint256 hash(pblock->GetHash());
4472 bool min_pow_checked =
false;
4477 forceProcessing = IsBlockRequested(hash);
4478 RemoveBlockRequest(hash, pfrom.
GetId());
4482 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4485 const CBlockIndex* prev_block = m_chainman.m_blockman.LookupBlockIndex(pblock->hashPrevBlock);
4487 min_pow_checked =
true;
4490 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4507 Assume(SetupAddressRelay(pfrom, *peer));
4511 if (peer->m_getaddr_recvd) {
4515 peer->m_getaddr_recvd =
true;
4517 peer->m_addrs_to_send.clear();
4518 std::vector<CAddress> vAddr;
4525 for (
const CAddress &addr : vAddr) {
4526 PushAddress(*peer, addr, insecure_rand);
4552 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4553 LOCK(tx_relay->m_tx_inventory_mutex);
4554 tx_relay->m_send_mempool =
true;
4580 const auto ping_end = time_received;
4583 bool bPingFinished =
false;
4584 std::string sProblem;
4586 if (nAvail >=
sizeof(
nonce)) {
4590 if (peer->m_ping_nonce_sent != 0) {
4591 if (
nonce == peer->m_ping_nonce_sent) {
4593 bPingFinished =
true;
4594 const auto ping_time = ping_end - peer->m_ping_start.load();
4595 if (ping_time.count() >= 0) {
4600 sProblem =
"Timing mishap";
4604 sProblem =
"Nonce mismatch";
4607 bPingFinished =
true;
4608 sProblem =
"Nonce zero";
4612 sProblem =
"Unsolicited pong without ping";
4616 bPingFinished =
true;
4617 sProblem =
"Short payload";
4620 if (!(sProblem.empty())) {
4624 peer->m_ping_nonce_sent,
4628 if (bPingFinished) {
4629 peer->m_ping_nonce_sent = 0;
4636 LogPrint(
BCLog::NET,
"filterload received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4643 if (!filter.IsWithinSizeConstraints())
4646 Misbehaving(*peer, 100,
"too-large bloom filter");
4647 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4649 LOCK(tx_relay->m_bloom_filter_mutex);
4650 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4651 tx_relay->m_relay_txs =
true;
4661 LogPrint(
BCLog::NET,
"filteradd received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4665 std::vector<unsigned char> vData;
4673 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4674 LOCK(tx_relay->m_bloom_filter_mutex);
4675 if (tx_relay->m_bloom_filter) {
4676 tx_relay->m_bloom_filter->insert(vData);
4682 Misbehaving(*peer, 100,
"bad filteradd message");
4689 LogPrint(
BCLog::NET,
"filterclear received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4693 auto tx_relay = peer->GetTxRelay();
4694 if (!tx_relay)
return;
4697 LOCK(tx_relay->m_bloom_filter_mutex);
4698 tx_relay->m_bloom_filter =
nullptr;
4699 tx_relay->m_relay_txs =
true;
4708 vRecv >> newFeeFilter;
4710 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4711 tx_relay->m_fee_filter_received = newFeeFilter;
4719 ProcessGetCFilters(pfrom, *peer, vRecv);
4724 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4729 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4734 std::vector<CInv> vInv;
4738 for (
CInv &inv : vInv) {
4742 m_txrequest.ReceivedResponse(pfrom.
GetId(), inv.
hash);
4754 bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4757 LOCK(peer.m_misbehavior_mutex);
4760 if (!peer.m_should_discourage)
return false;
4762 peer.m_should_discourage =
false;
4767 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
4773 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
4788 if (m_banman) m_banman->Discourage(pnode.
addr);
4789 m_connman.DisconnectNode(pnode.
addr);
4793 bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4795 bool fMoreWork =
false;
4797 PeerRef peer = GetPeerRef(pfrom->
GetId());
4798 if (peer ==
nullptr)
return false;
4801 LOCK(peer->m_getdata_requests_mutex);
4802 if (!peer->m_getdata_requests.empty()) {
4803 ProcessGetData(*pfrom, *peer, interruptMsgProc);
4809 if (!peer->m_orphan_work_set.empty()) {
4810 ProcessOrphanTx(peer->m_orphan_work_set);
4820 LOCK(peer->m_getdata_requests_mutex);
4821 if (!peer->m_getdata_requests.empty())
return true;
4826 if (!peer->m_orphan_work_set.empty())
return true;
4832 std::list<CNetMessage> msgs;
4835 if (pfrom->vProcessMsg.empty())
return false;
4837 msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin());
4838 pfrom->nProcessQueueSize -= msgs.front().m_raw_message_size;
4839 pfrom->
fPauseRecv = pfrom->nProcessQueueSize > m_connman.GetReceiveFloodSize();
4840 fMoreWork = !pfrom->vProcessMsg.empty();
4844 TRACE6(net, inbound_message,
4860 ProcessMessage(*pfrom, msg.
m_type, msg.m_recv, msg.m_time, interruptMsgProc);
4861 if (interruptMsgProc)
return false;
4863 LOCK(peer->m_getdata_requests_mutex);
4864 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
4866 }
catch (
const std::exception& e) {
4875 void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
4889 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.ActiveChain().Tip()->nChainWork) {
4890 if (state.m_chain_sync.m_timeout != 0s) {
4891 state.m_chain_sync.m_timeout = 0s;
4892 state.m_chain_sync.m_work_header =
nullptr;
4893 state.m_chain_sync.m_sent_getheaders =
false;
4895 }
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)) {
4901 state.m_chain_sync.m_work_header = m_chainman.ActiveChain().Tip();
4902 state.m_chain_sync.m_sent_getheaders =
false;
4903 }
else if (state.m_chain_sync.m_timeout > 0s && time_in_seconds > state.m_chain_sync.m_timeout) {
4907 if (state.m_chain_sync.m_sent_getheaders) {
4909 LogPrintf(
"Disconnecting outbound peer %d for old chain, best known block = %s\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>");
4912 assert(state.m_chain_sync.m_work_header);
4917 MaybeSendGetHeaders(pto,
4918 GetLocator(state.m_chain_sync.m_work_header->pprev),
4920 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());
4921 state.m_chain_sync.m_sent_getheaders =
true;
4933 void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
4941 if (m_connman.GetExtraBlockRelayCount() > 0) {
4942 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
4944 m_connman.ForEachNode([&](
CNode* pnode) {
4946 if (pnode->
GetId() > youngest_peer.first) {
4947 next_youngest_peer = youngest_peer;
4948 youngest_peer.first = pnode->
GetId();
4952 NodeId to_disconnect = youngest_peer.first;
4953 if (youngest_peer.second > next_youngest_peer.second) {
4956 to_disconnect = next_youngest_peer.first;
4965 CNodeState *node_state =
State(pnode->
GetId());
4966 if (node_state ==
nullptr ||
4969 LogPrint(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
4973 LogPrint(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
4981 if (m_connman.GetExtraFullOutboundCount() > 0) {
4987 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
4996 if (state ==
nullptr)
return;
4998 if (state->m_chain_sync.m_protect)
return;
4999 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->
GetId() > worst_peer)) {
5000 worst_peer = pnode->
GetId();
5001 oldest_block_announcement = state->m_last_block_announcement;
5004 if (worst_peer != -1) {
5015 LogPrint(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5019 LogPrint(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5030 m_connman.SetTryNewOutboundPeer(
false);
5036 void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5040 auto now{GetTime<std::chrono::seconds>()};
5042 EvictExtraOutboundPeers(now);
5044 if (now > m_stale_tip_check_time) {
5047 if (!
fImporting && !
fReindex && m_connman.GetNetworkActive() && m_connman.GetUseAddrmanOutgoing() && TipMayBeStale()) {
5048 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5050 m_connman.SetTryNewOutboundPeer(
true);
5051 }
else if (m_connman.GetTryNewOutboundPeer()) {
5052 m_connman.SetTryNewOutboundPeer(
false);
5057 if (!m_initial_sync_finished && CanDirectFetch()) {
5058 m_connman.StartExtraBlockRelayPeers();
5059 m_initial_sync_finished =
true;
5063 void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5065 if (m_connman.ShouldRunInactivityChecks(node_to, std::chrono::duration_cast<std::chrono::seconds>(now)) &&
5066 peer.m_ping_nonce_sent &&
5077 bool pingSend =
false;
5079 if (peer.m_ping_queued) {
5084 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5092 nonce = GetRand<uint64_t>();
5093 }
while (
nonce == 0);
5094 peer.m_ping_queued =
false;
5095 peer.m_ping_start = now;
5097 peer.m_ping_nonce_sent =
nonce;
5101 peer.m_ping_nonce_sent = 0;
5107 void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5110 if (!peer.m_addr_relay_enabled)
return;
5112 LOCK(peer.m_addr_send_times_mutex);
5114 if (
fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload() &&
5115 peer.m_next_local_addr_send < current_time) {
5122 if (peer.m_next_local_addr_send != 0us) {
5123 peer.m_addr_known->reset();
5126 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5128 PushAddress(peer, local_addr, insecure_rand);
5134 if (current_time <= peer.m_next_addr_send)
return;
5146 auto addr_already_known = [&peer](
const CAddress& addr) {
5147 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5148 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5151 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5152 peer.m_addrs_to_send.end());
5155 if (peer.m_addrs_to_send.empty())
return;
5157 const char* msg_type;
5159 if (peer.m_wants_addrv2) {
5166 m_connman.PushMessage(&
node,
CNetMsgMaker(
node.GetCommonVersion()).Make(make_flags, msg_type, peer.m_addrs_to_send));
5167 peer.m_addrs_to_send.clear();
5170 if (peer.m_addrs_to_send.capacity() > 40) {
5171 peer.m_addrs_to_send.shrink_to_fit();
5175 void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5183 CNodeState &state = *
State(
node.GetId());
5184 if (state.pindexBestKnownBlock !=
nullptr &&
5191 peer.m_sent_sendheaders =
true;
5196 void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5198 if (m_ignore_incoming_txs)
return;
5206 CAmount currentFilter = m_mempool.GetMinFee().GetFeePerK();
5209 if (m_chainman.ActiveChainstate().IsInitialBlockDownload()) {
5215 if (peer.m_fee_filter_sent == MAX_FILTER) {
5218 peer.m_next_send_feefilter = 0us;
5221 if (current_time > peer.m_next_send_feefilter) {
5222 CAmount filterToSend = g_filter_rounder.round(currentFilter);
5224 filterToSend = std::max(filterToSend, m_mempool.m_min_relay_feerate.GetFeePerK());
5225 if (filterToSend != peer.m_fee_filter_sent) {
5227 peer.m_fee_filter_sent = filterToSend;
5234 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5240 class CompareInvMempoolOrder
5245 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5248 m_wtxid_relay = use_wtxid;
5251 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5255 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5260 bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const 5269 bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5274 if (
node.IsBlockOnlyConn())
return false;
5276 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5279 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5285 bool PeerManagerImpl::SendMessages(
CNode* pto)
5287 PeerRef peer = GetPeerRef(pto->
GetId());
5288 if (!peer)
return false;
5293 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5302 const auto current_time{GetTime<std::chrono::microseconds>()};
5310 MaybeSendPing(*pto, *peer, current_time);
5315 MaybeSendAddr(*pto, *peer, current_time);
5317 MaybeSendSendHeaders(*pto, *peer);
5325 if (m_chainman.m_best_header ==
nullptr) {
5326 m_chainman.m_best_header = m_chainman.ActiveChain().Tip();
5332 bool sync_blocks_and_headers_from_peer =
false;
5333 if (state.fPreferredDownload) {
5334 sync_blocks_and_headers_from_peer =
true;
5345 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5346 sync_blocks_and_headers_from_peer =
true;
5352 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
GetAdjustedTime() - 24h) {
5353 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5361 if (pindexStart->
pprev)
5362 pindexStart = pindexStart->
pprev;
5363 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5366 state.fSyncStarted =
true;
5390 LOCK(peer->m_block_inv_mutex);
5391 std::vector<CBlock> vHeaders;
5392 bool fRevertToInv = ((!state.fPreferHeaders &&
5393 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5396 ProcessBlockAvailability(pto->
GetId());
5398 if (!fRevertToInv) {
5399 bool fFoundStartingHeader =
false;
5403 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5404 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
5406 if (m_chainman.ActiveChain()[pindex->
nHeight] != pindex) {
5408 fRevertToInv =
true;
5411 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5423 fRevertToInv =
true;
5426 pBestIndex = pindex;
5427 if (fFoundStartingHeader) {
5430 }
else if (PeerHasHeader(&state, pindex)) {
5432 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5435 fFoundStartingHeader =
true;
5440 fRevertToInv =
true;
5445 if (!fRevertToInv && !vHeaders.empty()) {
5446 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5450 vHeaders.front().GetHash().ToString(), pto->
GetId());
5452 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5454 LOCK(m_most_recent_block_mutex);
5455 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5459 if (cached_cmpctblock_msg.has_value()) {
5460 m_connman.PushMessage(pto, std::move(cached_cmpctblock_msg.value()));
5468 state.pindexBestHeaderSent = pBestIndex;
5469 }
else if (state.fPreferHeaders) {
5470 if (vHeaders.size() > 1) {
5473 vHeaders.front().GetHash().ToString(),
5474 vHeaders.back().GetHash().ToString(), pto->
GetId());
5477 vHeaders.front().GetHash().ToString(), pto->
GetId());
5480 state.pindexBestHeaderSent = pBestIndex;
5482 fRevertToInv =
true;
5488 if (!peer->m_blocks_for_headers_relay.empty()) {
5489 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5490 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hashToAnnounce);
5496 if (m_chainman.ActiveChain()[pindex->
nHeight] != pindex) {
5498 hashToAnnounce.
ToString(), m_chainman.ActiveChain().Tip()->GetBlockHash().ToString());
5502 if (!PeerHasHeader(&state, pindex)) {
5503 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5509 peer->m_blocks_for_headers_relay.clear();
5515 std::vector<CInv> vInv;
5517 LOCK(peer->m_block_inv_mutex);
5521 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5528 peer->m_blocks_for_inv_relay.clear();
5531 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5532 LOCK(tx_relay->m_tx_inventory_mutex);
5535 if (tx_relay->m_next_inv_send_time < current_time) {
5536 fSendTrickle =
true;
5546 LOCK(tx_relay->m_bloom_filter_mutex);
5547 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5551 if (fSendTrickle && tx_relay->m_send_mempool) {
5552 auto vtxinfo = m_mempool.infoAll();
5553 tx_relay->m_send_mempool =
false;
5554 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5556 LOCK(tx_relay->m_bloom_filter_mutex);
5558 for (
const auto& txinfo : vtxinfo) {
5559 const uint256& hash = peer->m_wtxid_relay ? txinfo.tx->GetWitnessHash() : txinfo.tx->GetHash();
5561 tx_relay->m_tx_inventory_to_send.erase(hash);
5563 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5566 if (tx_relay->m_bloom_filter) {
5567 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5569 tx_relay->m_tx_inventory_known_filter.insert(hash);
5571 vInv.push_back(inv);
5577 tx_relay->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time);
5583 std::vector<std::set<uint256>::iterator> vInvTx;
5584 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5585 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5586 vInvTx.push_back(it);
5588 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5591 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
5592 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5595 unsigned int nRelayedTransactions = 0;
5596 LOCK(tx_relay->m_bloom_filter_mutex);
5598 broadcast_max = std::min<size_t>(1000, broadcast_max);
5599 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5601 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5602 std::set<uint256>::iterator it = vInvTx.back();
5607 tx_relay->m_tx_inventory_to_send.erase(it);
5609 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
5613 auto txinfo = m_mempool.info(
ToGenTxid(inv));
5617 auto txid = txinfo.tx->GetHash();
5618 auto wtxid = txinfo.tx->GetWitnessHash();
5620 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5623 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5625 State(pto->
GetId())->m_recently_announced_invs.insert(hash);
5626 vInv.push_back(inv);
5627 nRelayedTransactions++;
5630 while (!g_relay_expiration.empty() && g_relay_expiration.front().first < current_time)
5632 mapRelay.erase(g_relay_expiration.front().second);
5633 g_relay_expiration.pop_front();
5636 auto ret = mapRelay.emplace(txid, std::move(txinfo.tx));
5641 auto ret2 = mapRelay.emplace(wtxid,
ret.first->second);
5650 tx_relay->m_tx_inventory_known_filter.insert(hash);
5657 tx_relay->m_tx_inventory_known_filter.insert(txid);
5670 LogPrintf(
"Peer=%d is stalling block download, disconnecting\n", pto->
GetId());
5679 if (state.vBlocksInFlight.size() > 0) {
5680 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5681 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5683 LogPrintf(
"Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.pindex->GetBlockHash().ToString(), pto->
GetId());
5689 if (state.fSyncStarted && state.m_headers_sync_timeout < std::chrono::microseconds::max()) {
5692 if (current_time > state.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5699 LogPrintf(
"Timeout downloading headers from peer=%d, disconnecting\n", pto->
GetId());
5703 LogPrintf(
"Timeout downloading headers from noban peer=%d, not disconnecting\n", pto->
GetId());
5709 state.fSyncStarted =
false;
5711 state.m_headers_sync_timeout = 0us;
5717 state.m_headers_sync_timeout = std::chrono::microseconds::max();
5723 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5728 std::vector<CInv> vGetData;
5729 if (CanServeBlocks(*peer) && ((sync_blocks_and_headers_from_peer && !IsLimitedPeer(*peer)) || !m_chainman.ActiveChainstate().IsInitialBlockDownload()) && state.nBlocksInFlight <
MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
5730 std::vector<const CBlockIndex*> vToDownload;
5734 uint32_t nFetchFlags = GetFetchFlags(*peer);
5736 BlockRequested(pto->
GetId(), *pindex);
5740 if (state.nBlocksInFlight == 0 && staller != -1) {
5741 if (
State(staller)->m_stalling_since == 0us) {
5742 State(staller)->m_stalling_since = current_time;
5751 std::vector<std::pair<NodeId, GenTxid>> expired;
5752 auto requestable = m_txrequest.GetRequestable(pto->
GetId(), current_time, &expired);
5753 for (
const auto& entry : expired) {
5754 LogPrint(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ?
"wtx" :
"tx",
5755 entry.second.GetHash().ToString(), entry.first);
5757 for (
const GenTxid& gtxid : requestable) {
5758 if (!AlreadyHaveTx(gtxid)) {
5770 m_txrequest.ForgetTxHash(gtxid.
GetHash());
5775 if (!vGetData.empty())
5778 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.
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
RecursiveMutex g_cs_orphans
Guards orphan transactions and extra txs for compact blocks.
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
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 auto UNCONDITIONAL_RELAY_DELAY
How long a transaction has to be in the mempool before it can unconditionally be relayed (even when n...
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).
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos, const Consensus::Params &consensusParams)
Functions for disk access for blocks.
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
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...
#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 ...
void SetIP(const CNetAddr &ip)
uint64_t m_addr_rate_limited
virtual void UnitTestMisbehaving(NodeId peer_id, int howmuch)=0
std::atomic_bool fReindex
std::string ToString() const
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 ...
bool AddTx(const CTransactionRef &tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
Add a new orphan transaction.
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
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
Verify that INVENTORY_MAX_RECENT_RELAY is enough to cache everything typically relayed before uncondi...
reverse_range< T > reverse_iterate(T &x)
std::vector< unsigned char > data
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.
void ignore(size_t num_ignore)
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.
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
Erase all orphans announced by a peer (eg, after that peer disconnects)
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...
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.
RecursiveMutex cs_vProcessMsg
arith_uint256 nMinimumChainWork
Minimum work we will assume exists on some valid chain.
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.
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
Double ended buffer combining vector and stream-like interfaces.
inputs (covered by txid) failed policy rules
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
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
void EraseForBlock(const CBlock &block) LOCKS_EXCLUDED(void LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
Erase all orphans included in or invalidated by a new block.
static constexpr auto RELAY_TX_CACHE_TIME
How long to cache transactions in mapRelay for normal relay.
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.
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...
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
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.
size_t Size() LOCKS_EXCLUDED(
Return how many entries exist in the orphange.
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
virtual void BlockConnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
int EraseTx(const uint256 &txid) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
Erase an orphan by txid.
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)
static constexpr int ADDRV2_FORMAT
A flag that is ORed into the protocol version to designate that addresses should be serialized in (un...
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
uint256 GetBlockHash() const
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.
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.
std::set< CTxMemPoolEntryRef, CompareIteratorByHash > Parents
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, bool ignore_incoming_txs)
std::vector< Byte > ParseHex(std::string_view str)
Parse the hex string into bytes (uint8_t or std::byte).
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
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.
void AddChildrenToWorkSet(const CTransaction &tx, std::set< uint256 > &orphan_work_set) const EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
Add any orphans that list a particular tx as a parent into a peer's work set (ie orphans that may hav...
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.
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, CDataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc)=0
Process a single message from a peer.
bool HaveTx(const GenTxid >xid) const LOCKS_EXCLUDED(std::pair< CTransactionRef, NodeId > GetTx(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
Check if we already have an orphan transaction (by txid or wtxid)
Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
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 (their version message did not include fRelay=false...
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
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 IsPeerAddrLocalGood(CNode *pnode)
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
A combination of a network address (CNetAddr) and a (TCP) port.
Transport protocol agnostic message container.
static constexpr unsigned int INVENTORY_MAX_RECENT_RELAY
The number of most recently announced transactions a peer can request.
int64_t nPowTargetSpacing
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
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.
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.
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.
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
bool ExpectServicesFromConn() const
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
CService GetLocalAddress(const CNetAddr &addrPeer)
std::atomic< bool > m_bip152_highbandwidth_to
std::vector< uint256 > vHave
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...
bool IsMsgWitnessBlk() const
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.
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB...
static const int MAX_UNCONNECTING_HEADERS
Maximum number of unconnecting headers announcements before DoS score.
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::microseconds m_ping_wait
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 fPruneMode
Pruning-related variables and constants.
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.
bool IsReachable(enum Network net)
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"...
static constexpr auto BLOCK_STALLING_TIMEOUT
Time during which a peer must stall block download progress before being disconnected.
the block's data didn't match the data committed to by the PoW
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
#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.
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
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
virtual void RelayTransaction(const uint256 &txid, const uint256 &wtxid)=0
Relay transaction to all peers.
bool IsTxAvailable(size_t index) const
static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN
Default number of orphan+recently-replaced txn to keep around for block reconstruction.
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
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
#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.
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)
this node does not have a mempool so can't validate the transaction
std::string ToString() const
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 ReadRawBlockFromDisk(std::vector< uint8_t > &block, const FlatFilePos &pos, const CMessageHeader::MessageStartChars &message_start)
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
std::atomic_bool fImporting
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
int64_t GetTime()
DEPRECATED, see GetTime.
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS
Default for -maxorphantx, maximum number of orphan transactions kept in memory.
int GetCommonVersion() const
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
const std::string m_addr_name
std::atomic_bool fPauseRecv
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
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).
bool HaveTxsDownloaded() const
Check whether this block's and all previous blocks' transactions have been downloaded (and stored to ...
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
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)
static constexpr auto GETDATA_TX_INTERVAL
How long to wait before downloading a transaction from an additional peer.
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt)=0
Process protocol messages received from a given node.
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...
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.
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(pnode -> cs_sendProcessing)=0
Send queued protocol messages to a given node.