175 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
195 Mutex m_misbehavior_mutex;
197 int m_misbehavior_score
GUARDED_BY(m_misbehavior_mutex){0};
199 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
202 Mutex m_block_inv_mutex;
206 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
210 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
218 std::atomic<int> m_starting_height{-1};
221 std::atomic<uint64_t> m_ping_nonce_sent{0};
223 std::atomic<std::chrono::microseconds> m_ping_start{0us};
225 std::atomic<bool> m_ping_queued{
false};
228 std::vector<CAddress> m_addrs_to_send;
238 std::unique_ptr<CRollingBloomFilter> m_addr_known;
253 std::atomic_bool m_addr_relay_enabled{
false};
255 bool m_getaddr_sent{
false};
257 mutable Mutex m_addr_send_times_mutex;
259 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
261 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
264 std::atomic_bool m_wants_addrv2{
false};
266 bool m_getaddr_recvd{
false};
269 double m_addr_token_bucket{1.0};
271 std::chrono::microseconds m_addr_token_timestamp{GetTime<std::chrono::microseconds>()};
273 std::atomic<uint64_t> m_addr_rate_limited{0};
275 std::atomic<uint64_t> m_addr_processed{0};
281 Mutex m_getdata_requests_mutex;
283 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
290using PeerRef = std::shared_ptr<Peer>;
319 void SetBestHeight(
int height)
override { m_best_height = height; };
320 void Misbehaving(
const NodeId pnode,
const int howmuch,
const std::string& message)
override;
322 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override;
335 void ReattemptInitialBroadcast(
CScheduler& scheduler);
339 PeerRef GetPeerRef(
NodeId id)
const;
343 PeerRef RemovePeer(
NodeId id);
356 bool via_compact_block,
const std::string& message =
"");
371 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
375 void ProcessHeadersMessage(
CNode& pfrom,
const Peer& peer,
376 const std::vector<CBlockHeader>& headers,
377 bool via_compact_block);
384 void AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
388 void PushNodeVersion(
CNode& pnode, int64_t nTime);
394 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
397 void MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time);
406 void RelayAddress(
NodeId originator,
const CAddress& addr,
bool fReachable);
421 std::atomic<int> m_best_height{-1};
424 int64_t m_stale_tip_check_time{0};
427 const bool m_ignore_incoming_txs;
431 bool m_initial_sync_finished{
false};
435 mutable Mutex m_peer_mutex;
442 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
515 Mutex m_recent_confirmed_transactions_mutex;
543 std::atomic<int64_t> m_last_tip_update{0};
551 void ProcessBlock(
CNode&
node, const std::shared_ptr<const
CBlock>& block,
bool force_processing);
557 std::deque<std::pair<std::chrono::microseconds, MapRelay::iterator>> g_relay_expiration
GUARDED_BY(
cs_main);
599 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv);
615 bool PrepareBlockFilterRequest(
CNode& peer,
617 const
uint256& stop_hash, uint32_t max_height_diff,
657 bool SetupAddressRelay(const
CNode&
node, Peer& peer);
677 uint256 hashLastUnknownBlock{};
683 int nUnconnectingHeaders{0};
685 bool fSyncStarted{
false};
687 std::chrono::microseconds m_headers_sync_timeout{0us};
689 std::chrono::microseconds m_stalling_since{0us};
690 std::list<QueuedBlock> vBlocksInFlight;
692 std::chrono::microseconds m_downloading_since{0us};
693 int nBlocksInFlight{0};
695 bool fPreferredDownload{
false};
697 bool fPreferHeaders{
false};
699 bool fPreferHeaderAndIDs{
false};
705 bool fProvidesHeaderAndIDs{
false};
707 bool fHaveWitness{
false};
709 bool fWantsCmpctWitness{
false};
714 bool fSupportsDesiredCmpctVersion{
false};
740 struct ChainSyncTimeoutState {
742 int64_t m_timeout{0};
746 bool m_sent_getheaders{
false};
748 bool m_protect{
false};
751 ChainSyncTimeoutState m_chain_sync;
754 int64_t m_last_block_announcement{0};
757 const bool m_is_inbound;
763 bool m_wtxid_relay{
false};
765 CNodeState(
bool is_inbound) : m_is_inbound(is_inbound) {}
772 std::map<NodeId, CNodeState>::iterator it = mapNodeState.find(pnode);
773 if (it == mapNodeState.end())
783static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
788static void AddAddressKnown(Peer& peer,
const CAddress& addr)
790 assert(peer.m_addr_known);
791 peer.m_addr_known->insert(addr.
GetKey());
799 assert(peer.m_addr_known);
800 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
802 peer.m_addrs_to_send[insecure_rand.
randrange(peer.m_addrs_to_send.size())] = addr;
804 peer.m_addrs_to_send.push_back(addr);
811 nPreferredDownload -= state->fPreferredDownload;
816 nPreferredDownload += state->fPreferredDownload;
819bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
821 return mapBlocksInFlight.find(hash) != mapBlocksInFlight.end();
824void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash)
826 auto it = mapBlocksInFlight.find(hash);
827 if (it == mapBlocksInFlight.end()) {
832 auto [node_id, list_it] = it->second;
833 CNodeState *state = State(node_id);
836 if (state->vBlocksInFlight.begin() == list_it) {
838 state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
840 state->vBlocksInFlight.erase(list_it);
842 state->nBlocksInFlight--;
843 if (state->nBlocksInFlight == 0) {
845 m_peers_downloading_from--;
847 state->m_stalling_since = 0us;
848 mapBlocksInFlight.erase(it);
851bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
855 CNodeState *state = State(nodeid);
859 std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
860 if (itInFlight != mapBlocksInFlight.end() && itInFlight->second.first == nodeid) {
862 *pit = &itInFlight->second.second;
868 RemoveBlockRequest(hash);
870 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
871 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
872 state->nBlocksInFlight++;
873 if (state->nBlocksInFlight == 1) {
875 state->m_downloading_since = GetTime<std::chrono::microseconds>();
876 m_peers_downloading_from++;
878 itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it))).first;
880 *pit = &itInFlight->second.second;
885void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
892 if (m_ignore_incoming_txs)
return;
894 CNodeState* nodestate = State(nodeid);
895 if (!nodestate || !nodestate->fSupportsDesiredCmpctVersion) {
899 if (nodestate->fProvidesHeaderAndIDs) {
900 int num_outbound_hb_peers = 0;
901 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
903 lNodesAnnouncingHeaderAndIDs.erase(it);
904 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
907 CNodeState *state = State(*it);
908 if (state !=
nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
910 if (nodestate->m_is_inbound) {
913 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
914 CNodeState *remove_node = State(lNodesAnnouncingHeaderAndIDs.front());
915 if (remove_node !=
nullptr && !remove_node->m_is_inbound) {
918 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
924 uint64_t nCMPCTBLOCKVersion = 2;
925 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
928 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this, nCMPCTBLOCKVersion](
CNode* pnodeStop){
929 m_connman.PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, false, nCMPCTBLOCKVersion));
931 pnodeStop->m_bip152_highbandwidth_to = false;
934 lNodesAnnouncingHeaderAndIDs.pop_front();
939 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
945bool PeerManagerImpl::TipMayBeStale()
949 if (m_last_tip_update == 0) {
955bool PeerManagerImpl::CanDirectFetch()
962 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
964 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
969void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
970 CNodeState *state = State(nodeid);
973 if (!state->hashLastUnknownBlock.IsNull()) {
974 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock);
976 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
977 state->pindexBestKnownBlock = pindex;
979 state->hashLastUnknownBlock.SetNull();
984void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
985 CNodeState *state = State(nodeid);
988 ProcessBlockAvailability(nodeid);
990 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
993 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
994 state->pindexBestKnownBlock = pindex;
998 state->hashLastUnknownBlock = hash;
1002void PeerManagerImpl::FindNextBlocksToDownload(
NodeId nodeid,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1007 vBlocks.reserve(vBlocks.size() +
count);
1008 CNodeState *state = State(nodeid);
1009 assert(state !=
nullptr);
1012 ProcessBlockAvailability(nodeid);
1019 if (state->pindexLastCommonBlock ==
nullptr) {
1022 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1027 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1028 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1032 std::vector<const CBlockIndex*> vToFetch;
1033 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1038 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1040 while (pindexWalk->
nHeight < nMaxHeight) {
1044 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1045 vToFetch.resize(nToFetch);
1046 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1047 vToFetch[nToFetch - 1] = pindexWalk;
1048 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1049 vToFetch[i - 1] = vToFetch[i]->
pprev;
1067 state->pindexLastCommonBlock = pindex;
1068 }
else if (!IsBlockRequested(pindex->
GetBlockHash())) {
1070 if (pindex->
nHeight > nWindowEnd) {
1072 if (vBlocks.size() == 0 && waitingfor != nodeid) {
1074 nodeStaller = waitingfor;
1078 vBlocks.push_back(pindex);
1079 if (vBlocks.size() ==
count) {
1082 }
else if (waitingfor == -1) {
1084 waitingfor = mapBlocksInFlight[pindex->
GetBlockHash()].first;
1092void PeerManagerImpl::PushNodeVersion(
CNode& pnode, int64_t nTime)
1099 const int nNodeStartingHeight{m_best_height};
1106 const bool tx_relay = !m_ignore_incoming_txs && pnode.
m_tx_relay !=
nullptr;
1108 your_services, addr_you,
1113 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);
1119void PeerManagerImpl::AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
1127 const CNodeState* state = State(nodeid);
1136 auto delay = std::chrono::microseconds{0};
1137 const bool preferred = state->fPreferredDownload;
1143 m_txrequest.ReceivedInv(nodeid, gtxid, preferred, current_time + delay);
1151 CNodeState *state = State(
node);
1152 if (state) state->m_last_block_announcement = time_in_seconds;
1155void PeerManagerImpl::InitializeNode(
CNode *pnode)
1160 mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(pnode->
IsInboundConn()));
1161 assert(m_txrequest.Count(nodeid) == 0);
1164 PeerRef peer = std::make_shared<Peer>(nodeid);
1166 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer));
1169 PushNodeVersion(*pnode,
GetTime());
1173void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1177 for (
const auto& txid : unbroadcast_txids) {
1180 if (tx !=
nullptr) {
1182 _RelayTransaction(txid, tx->GetWitnessHash());
1190 const std::chrono::milliseconds delta = std::chrono::minutes{10} +
GetRandMillis(std::chrono::minutes{5});
1191 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1194void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1206 PeerRef peer = RemovePeer(nodeid);
1208 misbehavior =
WITH_LOCK(peer->m_misbehavior_mutex,
return peer->m_misbehavior_score);
1210 CNodeState *state = State(nodeid);
1211 assert(state !=
nullptr);
1213 if (state->fSyncStarted)
1216 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1217 mapBlocksInFlight.erase(entry.pindex->GetBlockHash());
1220 m_txrequest.DisconnectedPeer(nodeid);
1221 nPreferredDownload -= state->fPreferredDownload;
1222 m_peers_downloading_from -= (state->nBlocksInFlight != 0);
1223 assert(m_peers_downloading_from >= 0);
1224 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1225 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1226 m_wtxid_relay_peers -= state->m_wtxid_relay;
1227 assert(m_wtxid_relay_peers >= 0);
1229 mapNodeState.erase(nodeid);
1231 if (mapNodeState.empty()) {
1233 assert(mapBlocksInFlight.empty());
1234 assert(nPreferredDownload == 0);
1235 assert(m_peers_downloading_from == 0);
1236 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1237 assert(m_wtxid_relay_peers == 0);
1238 assert(m_txrequest.Size() == 0);
1239 assert(m_orphanage.Size() == 0);
1242 if (
node.fSuccessfullyConnected && misbehavior == 0 &&
1243 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1252PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1255 auto it = m_peer_map.find(
id);
1256 return it != m_peer_map.end() ? it->second :
nullptr;
1259PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1263 auto it = m_peer_map.find(
id);
1264 if (it != m_peer_map.end()) {
1265 ret = std::move(it->second);
1266 m_peer_map.erase(it);
1275 CNodeState* state = State(nodeid);
1276 if (state ==
nullptr)
1278 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1279 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1280 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1286 PeerRef peer = GetPeerRef(nodeid);
1287 if (peer ==
nullptr)
return false;
1295 std::chrono::microseconds ping_wait{0};
1296 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1297 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1308void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1311 if (max_extra_txn <= 0)
1313 if (!vExtraTxnForCompact.size())
1314 vExtraTxnForCompact.resize(max_extra_txn);
1315 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1316 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % max_extra_txn;
1319void PeerManagerImpl::Misbehaving(
const NodeId pnode,
const int howmuch,
const std::string& message)
1323 PeerRef peer = GetPeerRef(pnode);
1324 if (peer ==
nullptr)
return;
1326 LOCK(peer->m_misbehavior_mutex);
1327 const int score_before{peer->m_misbehavior_score};
1328 peer->m_misbehavior_score += howmuch;
1329 const int score_now{peer->m_misbehavior_score};
1331 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1332 std::string warning;
1335 warning =
" DISCOURAGE THRESHOLD EXCEEDED";
1336 peer->m_should_discourage =
true;
1340 pnode, score_before, score_now, warning, message_prefixed);
1344 bool via_compact_block,
const std::string& message)
1352 if (!via_compact_block) {
1360 CNodeState *node_state = State(nodeid);
1361 if (node_state ==
nullptr) {
1367 if (!via_compact_block && !node_state->m_is_inbound) {
1387 if (message !=
"") {
1393bool PeerManagerImpl::MaybePunishNodeForTx(
NodeId nodeid,
const TxValidationState& state,
const std::string& message)
1414 if (message !=
"") {
1420bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1433 return std::make_unique<PeerManagerImpl>(chainparams, connman, addrman, banman, chainman, pool, ignore_incoming_txs);
1439 : m_chainparams(chainparams),
1443 m_chainman(chainman),
1445 m_ignore_incoming_txs(ignore_incoming_txs)
1449void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1459 const std::chrono::milliseconds delta = std::chrono::minutes{10} +
GetRandMillis(std::chrono::minutes{5});
1460 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1468void PeerManagerImpl::BlockConnected(
const std::shared_ptr<const CBlock>& pblock,
const CBlockIndex* pindex)
1470 m_orphanage.EraseForBlock(*pblock);
1471 m_last_tip_update =
GetTime();
1474 LOCK(m_recent_confirmed_transactions_mutex);
1475 for (
const auto& ptx : pblock->vtx) {
1476 m_recent_confirmed_transactions.insert(ptx->GetHash());
1477 if (ptx->GetHash() != ptx->GetWitnessHash()) {
1478 m_recent_confirmed_transactions.insert(ptx->GetWitnessHash());
1484 for (
const auto& ptx : pblock->vtx) {
1485 m_txrequest.ForgetTxHash(ptx->GetHash());
1486 m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
1491void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1501 LOCK(m_recent_confirmed_transactions_mutex);
1502 m_recent_confirmed_transactions.reset();
1516void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1518 std::shared_ptr<const CBlockHeaderAndShortTxIDs> pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs> (*pblock,
true);
1523 static int nHighestFastAnnounce = 0;
1524 if (pindex->
nHeight <= nHighestFastAnnounce)
1526 nHighestFastAnnounce = pindex->
nHeight;
1529 uint256 hashBlock(pblock->GetHash());
1533 most_recent_block_hash = hashBlock;
1534 most_recent_block = pblock;
1535 most_recent_compact_block = pcmpctblock;
1536 fWitnessesPresentInMostRecentCompactBlock = fWitnessEnabled;
1545 ProcessBlockAvailability(pnode->
GetId());
1546 CNodeState &state = *State(pnode->
GetId());
1549 if (state.fPreferHeaderAndIDs && (!fWitnessEnabled || state.fWantsCmpctWitness) &&
1550 !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
1552 LogPrint(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
1553 hashBlock.ToString(), pnode->
GetId());
1555 state.pindexBestHeaderSent = pindex;
1564void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
1566 SetBestHeight(pindexNew->
nHeight);
1570 if (fInitialDownload)
return;
1573 std::vector<uint256> vHashes;
1575 while (pindexToAnnounce != pindexFork) {
1577 pindexToAnnounce = pindexToAnnounce->
pprev;
1587 for (
auto& it : m_peer_map) {
1588 Peer& peer = *it.second;
1589 LOCK(peer.m_block_inv_mutex);
1591 peer.m_blocks_for_headers_relay.push_back(hash);
1608 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
1613 it != mapBlockSource.end() &&
1614 State(it->second.first)) {
1615 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
1625 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
1626 if (it != mapBlockSource.end()) {
1627 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
1630 if (it != mapBlockSource.end())
1631 mapBlockSource.erase(it);
1640bool PeerManagerImpl::AlreadyHaveTx(
const GenTxid& gtxid)
1648 m_recent_rejects.reset();
1653 if (m_orphanage.HaveTx(gtxid))
return true;
1656 LOCK(m_recent_confirmed_transactions_mutex);
1657 if (m_recent_confirmed_transactions.contains(hash))
return true;
1660 return m_recent_rejects.contains(hash) || m_mempool.
exists(gtxid);
1663bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
1665 return m_chainman.m_blockman.LookupBlockIndex(block_hash) !=
nullptr;
1668void PeerManagerImpl::SendPings()
1671 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
1674void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
1679void PeerManagerImpl::_RelayTransaction(
const uint256& txid,
const uint256& wtxid)
1684 CNodeState* state = State(pnode->
GetId());
1685 if (state ==
nullptr)
return;
1686 if (state->m_wtxid_relay) {
1694void PeerManagerImpl::RelayAddress(
NodeId originator,
1709 uint64_t hashAddr = addr.
GetHash();
1714 unsigned int nRelayNodes = (fReachable || (hasher.
Finalize() & 1)) ? 2 : 1;
1716 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
1717 assert(nRelayNodes <= best.size());
1721 for (
auto& [
id, peer] : m_peer_map) {
1722 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
1724 for (
unsigned int i = 0; i < nRelayNodes; i++) {
1725 if (hashKey > best[i].first) {
1726 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
1727 best[i] = std::make_pair(hashKey, peer.get());
1734 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
1735 PushAddress(*best[i].second, addr, insecure_rand);
1739void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
1741 std::shared_ptr<const CBlock> a_recent_block;
1742 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
1743 bool fWitnessesPresentInARecentCompactBlock;
1746 a_recent_block = most_recent_block;
1747 a_recent_compact_block = most_recent_compact_block;
1748 fWitnessesPresentInARecentCompactBlock = fWitnessesPresentInMostRecentCompactBlock;
1751 bool need_activate_chain =
false;
1754 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.
hash);
1763 need_activate_chain =
true;
1767 if (need_activate_chain) {
1775 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.
hash);
1779 if (!BlockRequestAllowed(pindex)) {
1780 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
1797 LogPrint(
BCLog::NET,
"Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.
GetId());
1807 std::shared_ptr<const CBlock> pblock;
1808 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
1809 pblock = a_recent_block;
1813 std::vector<uint8_t> block_data;
1815 assert(!
"cannot load block from disk");
1821 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
1823 assert(!
"cannot load block from disk");
1825 pblock = pblockRead;
1833 bool sendMerkleBlock =
false;
1838 sendMerkleBlock =
true;
1842 if (sendMerkleBlock) {
1850 typedef std::pair<unsigned int, uint256> PairType;
1861 bool fPeerWantsWitness = State(pfrom.
GetId())->fWantsCmpctWitness;
1864 if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
1877 LOCK(peer.m_block_inv_mutex);
1879 if (inv.
hash == peer.m_continuation_block) {
1883 std::vector<CInv> vInv;
1886 peer.m_continuation_block.SetNull();
1891CTransactionRef PeerManagerImpl::FindTxForGetData(
const CNode& peer,
const GenTxid& gtxid,
const std::chrono::seconds mempool_req,
const std::chrono::seconds now)
1893 auto txinfo = m_mempool.
info(gtxid);
1899 return std::move(txinfo.tx);
1906 if (State(peer.
GetId())->m_recently_announced_invs.contains(gtxid.
GetHash())) {
1908 if (txinfo.tx)
return std::move(txinfo.tx);
1910 auto mi = mapRelay.find(gtxid.
GetHash());
1911 if (mi != mapRelay.end())
return mi->second;
1918void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
1922 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
1923 std::vector<CInv> vNotFound;
1926 const std::chrono::seconds now = GetTime<std::chrono::seconds>();
1928 const std::chrono::seconds mempool_req = pfrom.
m_tx_relay !=
nullptr ? pfrom.
m_tx_relay->m_last_mempool_req.load()
1929 : std::chrono::seconds::min();
1934 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
1935 if (interruptMsgProc)
return;
1940 const CInv &inv = *it++;
1954 std::vector<uint256> parent_ids_to_add;
1957 auto txiter = m_mempool.
GetIter(tx->GetHash());
1960 parent_ids_to_add.reserve(parents.size());
1963 parent_ids_to_add.push_back(parent.GetTx().GetHash());
1968 for (
const uint256& parent_txid : parent_ids_to_add) {
1972 State(pfrom.
GetId())->m_recently_announced_invs.insert(parent_txid);
1976 vNotFound.push_back(inv);
1982 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
1983 const CInv &inv = *it++;
1985 ProcessGetBlockData(pfrom, peer, inv);
1991 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
1993 if (!vNotFound.empty()) {
2013 uint32_t nFetchFlags = 0;
2014 if (State(pfrom.
GetId())->fHaveWitness) {
2023 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2025 Misbehaving(pfrom.
GetId(), 100,
"getblocktxn with out-of-bounds tx indices");
2036void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom,
const Peer& peer,
2037 const std::vector<CBlockHeader>& headers,
2038 bool via_compact_block)
2041 size_t nCount = headers.size();
2048 bool received_new_header =
false;
2052 CNodeState *nodestate = State(pfrom.
GetId());
2062 if (!m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount <
MAX_BLOCKS_TO_ANNOUNCE) {
2063 nodestate->nUnconnectingHeaders++;
2065 LogPrint(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
2067 headers[0].hashPrevBlock.ToString(),
2069 pfrom.
GetId(), nodestate->nUnconnectingHeaders);
2073 UpdateBlockAvailability(pfrom.
GetId(), headers.back().GetHash());
2076 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"%d non-connecting headers", nodestate->nUnconnectingHeaders));
2083 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2084 Misbehaving(pfrom.
GetId(), 20,
"non-continuous headers sequence");
2087 hashLastBlock = header.GetHash();
2092 if (!m_chainman.m_blockman.LookupBlockIndex(hashLastBlock)) {
2093 received_new_header =
true;
2100 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2107 CNodeState *nodestate = State(pfrom.
GetId());
2108 if (nodestate->nUnconnectingHeaders > 0) {
2109 LogPrint(
BCLog::NET,
"peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom.
GetId(), nodestate->nUnconnectingHeaders);
2111 nodestate->nUnconnectingHeaders = 0;
2121 nodestate->m_last_block_announcement =
GetTime();
2129 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2136 std::vector<const CBlockIndex*> vToFetch;
2144 vToFetch.push_back(pindexWalk);
2146 pindexWalk = pindexWalk->
pprev;
2157 std::vector<CInv> vGetData;
2166 BlockRequested(pfrom.
GetId(), *pindex);
2170 if (vGetData.size() > 1) {
2174 if (vGetData.size() > 0) {
2175 if (!m_ignore_incoming_txs &&
2176 nodestate->fSupportsDesiredCmpctVersion &&
2177 vGetData.size() == 1 &&
2178 mapBlocksInFlight.size() == 1 &&
2192 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork <
nMinimumChainWork) {
2202 LogPrintf(
"Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.
GetId());
2214 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) {
2216 nodestate->m_chain_sync.m_protect =
true;
2217 ++m_outbound_peers_with_protect_from_disconnect;
2233void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
2238 while (!orphan_work_set.empty()) {
2240 orphan_work_set.erase(orphan_work_set.begin());
2242 const auto [porphanTx, from_peer] = m_orphanage.GetTx(orphanHash);
2243 if (porphanTx ==
nullptr)
continue;
2250 _RelayTransaction(orphanHash, porphanTx->GetWitnessHash());
2251 m_orphanage.AddChildrenToWorkSet(*porphanTx, orphan_work_set);
2252 m_orphanage.EraseTx(orphanHash);
2254 AddToCompactExtraTransactions(removedTx);
2264 MaybePunishNodeForTx(from_peer, state);
2283 m_recent_rejects.insert(porphanTx->GetWitnessHash());
2295 m_recent_rejects.insert(porphanTx->GetHash());
2298 m_orphanage.EraseTx(orphanHash);
2306bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode& peer,
2308 const uint256& stop_hash, uint32_t max_height_diff,
2312 const bool supported_filter_type =
2315 if (!supported_filter_type) {
2317 peer.
GetId(),
static_cast<uint8_t
>(filter_type));
2324 stop_index = m_chainman.m_blockman.LookupBlockIndex(stop_hash);
2327 if (!stop_index || !BlockRequestAllowed(stop_index)) {
2335 uint32_t stop_height = stop_index->
nHeight;
2336 if (start_height > stop_height) {
2338 "start height %d and stop height %d\n",
2339 peer.
GetId(), start_height, stop_height);
2343 if (stop_height - start_height >= max_height_diff) {
2345 peer.
GetId(), stop_height - start_height + 1, max_height_diff);
2351 if (!filter_index) {
2361 uint8_t filter_type_ser;
2362 uint32_t start_height;
2365 vRecv >> filter_type_ser >> start_height >> stop_hash;
2371 if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
2376 std::vector<BlockFilter> filters;
2378 LogPrint(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
2383 for (
const auto& filter : filters) {
2392 uint8_t filter_type_ser;
2393 uint32_t start_height;
2396 vRecv >> filter_type_ser >> start_height >> stop_hash;
2402 if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
2408 if (start_height > 0) {
2410 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
2412 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
2418 std::vector<uint256> filter_hashes;
2420 LogPrint(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
2436 uint8_t filter_type_ser;
2439 vRecv >> filter_type_ser >> stop_hash;
2445 if (!PrepareBlockFilterRequest(peer, filter_type, 0, stop_hash,
2446 std::numeric_limits<uint32_t>::max(),
2447 stop_index, filter_index)) {
2455 for (
int i = headers.size() - 1; i >= 0; i--) {
2460 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
2474void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing)
2476 bool new_block{
false};
2477 m_chainman.
ProcessNewBlock(m_chainparams, block, force_processing, &new_block);
2482 mapBlockSource.erase(block->GetHash());
2486void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
CDataStream& vRecv,
2487 const std::chrono::microseconds time_received,
2488 const std::atomic<bool>& interruptMsgProc)
2492 PeerRef peer = GetPeerRef(pfrom.
GetId());
2493 if (peer ==
nullptr)
return;
2503 uint64_t nNonce = 1;
2506 std::string cleanSubVer;
2507 int starting_height = -1;
2510 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
2534 if (!vRecv.
empty()) {
2542 if (!vRecv.
empty()) {
2543 std::string strSubVer;
2547 if (!vRecv.
empty()) {
2548 vRecv >> starting_height;
2581 if (greatest_common_version >= 70016) {
2595 pfrom.cleanSubVer = cleanSubVer;
2597 peer->m_starting_height = starting_height;
2613 State(pfrom.
GetId())->fHaveWitness =
true;
2619 UpdatePreferredDownload(pfrom, State(pfrom.
GetId()));
2623 if (!pfrom.
IsInboundConn() && SetupAddressRelay(pfrom, *peer)) {
2642 PushAddress(*peer, addr, insecure_rand);
2646 PushAddress(*peer, addr, insecure_rand);
2652 peer->m_getaddr_sent =
true;
2676 std::string remoteAddr;
2680 LogPrint(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s\n",
2682 peer->m_starting_height, addrMe.ToString(), fRelay, pfrom.
GetId(),
2685 int64_t nTimeOffset = nTime -
GetTime();
2690 if (greatest_common_version <= 70012) {
2691 CDataStream finalAlert(
ParseHex(
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"),
SER_NETWORK,
PROTOCOL_VERSION);
2719 LogPrintf(
"New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n",
2720 pfrom.
nVersion.load(), peer->m_starting_height,
2738 bool fAnnounceUsingCMPCTBLOCK =
false;
2739 uint64_t nCMPCTBLOCKVersion = 2;
2741 nCMPCTBLOCKVersion = 1;
2750 State(pfrom.
GetId())->fPreferHeaders =
true;
2755 bool fAnnounceUsingCMPCTBLOCK =
false;
2756 uint64_t nCMPCTBLOCKVersion = 0;
2757 vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
2758 if (nCMPCTBLOCKVersion == 1 || nCMPCTBLOCKVersion == 2) {
2761 if (!State(pfrom.
GetId())->fProvidesHeaderAndIDs) {
2762 State(pfrom.
GetId())->fProvidesHeaderAndIDs =
true;
2763 State(pfrom.
GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2;
2765 if (State(pfrom.
GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) {
2766 State(pfrom.
GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
2771 if (!State(pfrom.
GetId())->fSupportsDesiredCmpctVersion) {
2772 State(pfrom.
GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2);
2789 if (!State(pfrom.
GetId())->m_wtxid_relay) {
2790 State(pfrom.
GetId())->m_wtxid_relay =
true;
2791 m_wtxid_relay_peers++;
2810 peer->m_wants_addrv2 =
true;
2828 std::vector<CAddress> vAddr;
2832 if (!SetupAddressRelay(pfrom, *peer)) {
2839 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
2844 std::vector<CAddress> vAddrOk;
2846 int64_t nSince = nNow - 10 * 60;
2849 const auto current_time = GetTime<std::chrono::microseconds>();
2852 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
2856 peer->m_addr_token_timestamp = current_time;
2859 uint64_t num_proc = 0;
2860 uint64_t num_rate_limit = 0;
2864 if (interruptMsgProc)
2868 if (peer->m_addr_token_bucket < 1.0) {
2874 peer->m_addr_token_bucket -= 1.0;
2882 if (addr.
nTime <= 100000000 || addr.
nTime > nNow + 10 * 60)
2883 addr.
nTime = nNow - 5 * 24 * 60 * 60;
2884 AddAddressKnown(*peer, addr);
2891 if (addr.
nTime > nSince && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
2893 RelayAddress(pfrom.
GetId(), addr, fReachable);
2897 vAddrOk.push_back(addr);
2899 peer->m_addr_processed += num_proc;
2900 peer->m_addr_rate_limited += num_rate_limit;
2901 LogPrint(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
2902 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
2904 m_addrman.
Add(vAddrOk, pfrom.
addr, 2 * 60 * 60);
2905 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
2916 std::vector<CInv> vInv;
2920 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"inv message size = %u", vInv.size()));
2926 bool reject_tx_invs{m_ignore_incoming_txs || (pfrom.
m_tx_relay ==
nullptr)};
2930 reject_tx_invs =
false;
2935 const auto current_time = GetTime<std::chrono::microseconds>();
2938 for (
CInv& inv : vInv) {
2939 if (interruptMsgProc)
return;
2944 if (State(pfrom.
GetId())->m_wtxid_relay) {
2951 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
2954 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
2961 best_block = &inv.
hash;
2964 if (reject_tx_invs) {
2970 const bool fAlreadyHave = AlreadyHaveTx(gtxid);
2975 AddTxAnnouncement(pfrom, gtxid, current_time);
2982 if (best_block !=
nullptr) {
2991 std::vector<CInv> vInv;
2995 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"getdata message size = %u", vInv.size()));
3001 if (vInv.size() > 0) {
3006 LOCK(peer->m_getdata_requests_mutex);
3007 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
3008 ProcessGetData(pfrom, *peer, interruptMsgProc);
3017 vRecv >> locator >> hashStop;
3033 std::shared_ptr<const CBlock> a_recent_block;
3036 a_recent_block = most_recent_block;
3047 const CBlockIndex* pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.
ActiveChain(), locator);
3054 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
3070 if (--nLimit <= 0) {
3074 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
3085 std::shared_ptr<const CBlock> recent_block;
3088 if (most_recent_block_hash == req.
blockhash)
3089 recent_block = most_recent_block;
3093 SendBlockTransactions(pfrom, *recent_block, req);
3111 SendBlockTransactions(pfrom, block, req);
3127 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
3135 vRecv >> locator >> hashStop;
3145 LogPrint(
BCLog::NET,
"Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom.
GetId());
3149 CNodeState *nodestate = State(pfrom.
GetId());
3154 pindex = m_chainman.m_blockman.LookupBlockIndex(hashStop);
3159 if (!BlockRequestAllowed(pindex)) {
3160 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
3167 pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.
ActiveChain(), locator);
3173 std::vector<CBlock> vHeaders;
3176 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
3179 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
3194 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
3214 const uint256& txid = ptx->GetHash();
3215 const uint256& wtxid = ptx->GetWitnessHash();
3219 CNodeState* nodestate = State(pfrom.
GetId());
3221 const uint256& hash = nodestate->m_wtxid_relay ? wtxid : txid;
3223 if (nodestate->m_wtxid_relay && txid != wtxid) {
3232 m_txrequest.ReceivedResponse(pfrom.
GetId(), txid);
3233 if (tx.
HasWitness()) m_txrequest.ReceivedResponse(pfrom.
GetId(), wtxid);
3270 m_txrequest.ForgetTxHash(tx.
GetHash());
3273 m_orphanage.AddChildrenToWorkSet(tx, peer->m_orphan_work_set);
3283 AddToCompactExtraTransactions(removedTx);
3287 ProcessOrphanTx(peer->m_orphan_work_set);
3291 bool fRejectedParents =
false;
3295 std::vector<uint256> unique_parents;
3296 unique_parents.reserve(tx.
vin.size());
3301 std::sort(unique_parents.begin(), unique_parents.end());
3302 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
3303 for (
const uint256& parent_txid : unique_parents) {
3304 if (m_recent_rejects.contains(parent_txid)) {
3305 fRejectedParents =
true;
3309 if (!fRejectedParents) {
3310 const auto current_time = GetTime<std::chrono::microseconds>();
3312 for (
const uint256& parent_txid : unique_parents) {
3320 if (!AlreadyHaveTx(gtxid)) AddTxAnnouncement(pfrom, gtxid, current_time);
3323 if (m_orphanage.AddTx(ptx, pfrom.
GetId())) {
3324 AddToCompactExtraTransactions(ptx);
3328 m_txrequest.ForgetTxHash(tx.
GetHash());
3333 unsigned int nEvicted = m_orphanage.LimitOrphans(nMaxOrphanTx);
3345 m_recent_rejects.insert(tx.
GetHash());
3347 m_txrequest.ForgetTxHash(tx.
GetHash());
3376 m_recent_rejects.insert(tx.
GetHash());
3377 m_txrequest.ForgetTxHash(tx.
GetHash());
3380 AddToCompactExtraTransactions(ptx);
3406 MaybePunishNodeForTx(pfrom.
GetId(), state);
3420 vRecv >> cmpctblock;
3422 bool received_new_header =
false;
3434 if (!m_chainman.m_blockman.LookupBlockIndex(cmpctblock.
header.
GetHash())) {
3435 received_new_header =
true;
3443 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
3452 bool fProcessBLOCKTXN =
false;
3457 bool fRevertToHeaderProcessing =
false;
3461 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3462 bool fBlockReconstructed =
false;
3470 CNodeState *nodestate = State(pfrom.
GetId());
3475 nodestate->m_last_block_announcement =
GetTime();
3478 std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator blockInFlightIt = mapBlocksInFlight.find(pindex->
GetBlockHash());
3479 bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end();
3486 if (fAlreadyInFlight) {
3489 std::vector<CInv> vInv(1);
3497 if (!fAlreadyInFlight && !CanDirectFetch()) {
3511 (fAlreadyInFlight && blockInFlightIt->second.first == pfrom.
GetId())) {
3512 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
3513 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
3514 if (!(*queuedBlockIt)->partialBlock)
3527 Misbehaving(pfrom.
GetId(), 100,
"invalid compact block");
3531 std::vector<CInv> vInv(1);
3538 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
3547 fProcessBLOCKTXN =
true;
3559 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
3564 std::vector<CTransactionRef> dummy;
3565 status = tempBlock.FillBlock(*pblock, dummy);
3567 fBlockReconstructed =
true;
3571 if (fAlreadyInFlight) {
3574 std::vector<CInv> vInv(1);
3580 fRevertToHeaderProcessing =
true;
3585 if (fProcessBLOCKTXN) {
3586 return ProcessMessage(pfrom,
NetMsgType::BLOCKTXN, blockTxnMsg, time_received, interruptMsgProc);
3589 if (fRevertToHeaderProcessing) {
3595 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
3598 if (fBlockReconstructed) {
3603 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
3614 ProcessBlock(pfrom, pblock,
true);
3621 RemoveBlockRequest(pblock->GetHash());
3638 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3639 bool fBlockRead =
false;
3643 std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator it = mapBlocksInFlight.find(resp.
blockhash);
3644 if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock ||
3645 it->second.first != pfrom.
GetId()) {
3654 Misbehaving(pfrom.
GetId(), 100,
"invalid compact block/non-matching block transactions");
3658 std::vector<CInv> invs;
3687 mapBlockSource.emplace(resp.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3697 ProcessBlock(pfrom, pblock,
true);
3710 std::vector<CBlockHeader> headers;
3715 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"headers message size = %u", nCount));
3718 headers.resize(nCount);
3719 for (
unsigned int n = 0; n < nCount; n++) {
3720 vRecv >> headers[n];
3724 return ProcessHeadersMessage(pfrom, *peer, headers,
false);
3735 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3740 bool forceProcessing =
false;
3741 const uint256 hash(pblock->GetHash());
3746 forceProcessing = IsBlockRequested(hash);
3747 RemoveBlockRequest(hash);
3751 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
3753 ProcessBlock(pfrom, pblock, forceProcessing);
3770 Assume(SetupAddressRelay(pfrom, *peer));
3774 if (peer->m_getaddr_recvd) {
3778 peer->m_getaddr_recvd =
true;
3780 peer->m_addrs_to_send.clear();
3781 std::vector<CAddress> vAddr;
3788 for (
const CAddress &addr : vAddr) {
3789 PushAddress(*peer, addr, insecure_rand);
3843 const auto ping_end = time_received;
3846 bool bPingFinished =
false;
3847 std::string sProblem;
3849 if (nAvail >=
sizeof(
nonce)) {
3853 if (peer->m_ping_nonce_sent != 0) {
3854 if (
nonce == peer->m_ping_nonce_sent) {
3856 bPingFinished =
true;
3857 const auto ping_time = ping_end - peer->m_ping_start.load();
3858 if (ping_time.count() >= 0) {
3863 sProblem =
"Timing mishap";
3867 sProblem =
"Nonce mismatch";
3870 bPingFinished =
true;
3871 sProblem =
"Nonce zero";
3875 sProblem =
"Unsolicited pong without ping";
3879 bPingFinished =
true;
3880 sProblem =
"Short payload";
3883 if (!(sProblem.empty())) {
3887 peer->m_ping_nonce_sent,
3891 if (bPingFinished) {
3892 peer->m_ping_nonce_sent = 0;
3899 LogPrint(
BCLog::NET,
"filterload received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
3909 Misbehaving(pfrom.
GetId(), 100,
"too-large bloom filter");
3922 LogPrint(
BCLog::NET,
"filteradd received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
3926 std::vector<unsigned char> vData;
3943 Misbehaving(pfrom.
GetId(), 100,
"bad filteradd message");
3950 LogPrint(
BCLog::NET,
"filterclear received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
3965 vRecv >> newFeeFilter;
3968 pfrom.
m_tx_relay->minFeeFilter = newFeeFilter;
3976 ProcessGetCFilters(pfrom, vRecv);
3981 ProcessGetCFHeaders(pfrom, vRecv);
3986 ProcessGetCFCheckPt(pfrom, vRecv);
3991 std::vector<CInv> vInv;
3995 for (
CInv &inv : vInv) {
3999 m_txrequest.ReceivedResponse(pfrom.
GetId(), inv.
hash);
4011bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
4014 LOCK(peer.m_misbehavior_mutex);
4017 if (!peer.m_should_discourage)
return false;
4019 peer.m_should_discourage =
false;
4024 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
4030 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
4050bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4052 bool fMoreWork =
false;
4054 PeerRef peer = GetPeerRef(pfrom->
GetId());
4055 if (peer ==
nullptr)
return false;
4058 LOCK(peer->m_getdata_requests_mutex);
4059 if (!peer->m_getdata_requests.empty()) {
4060 ProcessGetData(*pfrom, *peer, interruptMsgProc);
4066 if (!peer->m_orphan_work_set.empty()) {
4067 ProcessOrphanTx(peer->m_orphan_work_set);
4077 LOCK(peer->m_getdata_requests_mutex);
4078 if (!peer->m_getdata_requests.empty())
return true;
4083 if (!peer->m_orphan_work_set.empty())
return true;
4089 std::list<CNetMessage> msgs;
4092 if (pfrom->vProcessMsg.empty())
return false;
4094 msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin());
4097 fMoreWork = !pfrom->vProcessMsg.empty();
4101 TRACE6(net, inbound_message,
4105 msg.m_command.c_str(),
4115 const std::string& msg_type = msg.m_command;
4118 unsigned int nMessageSize = msg.m_message_size;
4121 ProcessMessage(*pfrom, msg_type, msg.m_recv, msg.m_time, interruptMsgProc);
4122 if (interruptMsgProc)
return false;
4124 LOCK(peer->m_getdata_requests_mutex);
4125 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
4127 }
catch (
const std::exception& e) {
4136void PeerManagerImpl::ConsiderEviction(
CNode& pto, int64_t time_in_seconds)
4140 CNodeState &state = *State(pto.
GetId());
4150 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
4151 if (state.m_chain_sync.m_timeout != 0) {
4152 state.m_chain_sync.m_timeout = 0;
4153 state.m_chain_sync.m_work_header =
nullptr;
4154 state.m_chain_sync.m_sent_getheaders =
false;
4156 }
else if (state.m_chain_sync.m_timeout == 0 || (state.m_chain_sync.m_work_header !=
nullptr && state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= state.m_chain_sync.m_work_header->nChainWork)) {
4162 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
4163 state.m_chain_sync.m_sent_getheaders =
false;
4164 }
else if (state.m_chain_sync.m_timeout > 0 && time_in_seconds > state.m_chain_sync.m_timeout) {
4168 if (state.m_chain_sync.m_sent_getheaders) {
4170 LogPrintf(
"Disconnecting outbound peer %d for old chain, best known block = %s\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>");
4173 assert(state.m_chain_sync.m_work_header);
4174 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());
4176 state.m_chain_sync.m_sent_getheaders =
true;
4177 constexpr int64_t HEADERS_RESPONSE_TIME = 120;
4183 state.m_chain_sync.m_timeout = time_in_seconds + HEADERS_RESPONSE_TIME;
4189void PeerManagerImpl::EvictExtraOutboundPeers(int64_t time_in_seconds)
4198 std::pair<NodeId, int64_t> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
4202 if (pnode->
GetId() > youngest_peer.first) {
4203 next_youngest_peer = youngest_peer;
4204 youngest_peer.first = pnode->GetId();
4205 youngest_peer.second = pnode->nLastBlockTime;
4208 NodeId to_disconnect = youngest_peer.first;
4209 if (youngest_peer.second > next_youngest_peer.second) {
4212 to_disconnect = next_youngest_peer.first;
4221 CNodeState *node_state = State(pnode->
GetId());
4222 if (node_state ==
nullptr ||
4228 LogPrint(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
4242 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
4250 CNodeState *state = State(pnode->
GetId());
4251 if (state ==
nullptr)
return;
4253 if (state->m_chain_sync.m_protect)
return;
4254 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->
GetId() > worst_peer)) {
4255 worst_peer = pnode->
GetId();
4256 oldest_block_announcement = state->m_last_block_announcement;
4259 if (worst_peer != -1) {
4268 CNodeState &state = *State(pnode->
GetId());
4270 LogPrint(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
4290void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
4294 int64_t time_in_seconds =
GetTime();
4296 EvictExtraOutboundPeers(time_in_seconds);
4298 if (time_in_seconds > m_stale_tip_check_time) {
4302 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n", time_in_seconds - m_last_tip_update);
4310 if (!m_initial_sync_finished && CanDirectFetch()) {
4312 m_initial_sync_finished =
true;
4316void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
4319 peer.m_ping_nonce_sent &&
4320 now > peer.m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL}) {
4329 bool pingSend =
false;
4331 if (peer.m_ping_queued) {
4336 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
4343 while (
nonce == 0) {
4346 peer.m_ping_queued =
false;
4347 peer.m_ping_start = now;
4349 peer.m_ping_nonce_sent =
nonce;
4353 peer.m_ping_nonce_sent = 0;
4359void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
4362 if (!peer.m_addr_relay_enabled)
return;
4364 LOCK(peer.m_addr_send_times_mutex);
4367 peer.m_next_local_addr_send < current_time) {
4374 if (peer.m_next_local_addr_send != 0us) {
4375 peer.m_addr_known->reset();
4379 PushAddress(peer, *local_addr, insecure_rand);
4385 if (current_time <= peer.m_next_addr_send)
return;
4397 auto addr_already_known = [&peer](
const CAddress& addr) {
4398 bool ret = peer.m_addr_known->contains(addr.
GetKey());
4399 if (!ret) peer.m_addr_known->insert(addr.
GetKey());
4402 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
4403 peer.m_addrs_to_send.end());
4406 if (peer.m_addrs_to_send.empty())
return;
4408 const char* msg_type;
4410 if (peer.m_wants_addrv2) {
4418 peer.m_addrs_to_send.clear();
4421 if (peer.m_addrs_to_send.capacity() > 40) {
4422 peer.m_addrs_to_send.shrink_to_fit();
4426void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, std::chrono::microseconds current_time)
4430 if (m_ignore_incoming_txs)
return;
4445 if (pto.
m_tx_relay->lastSentFeeFilter == MAX_FILTER) {
4451 if (current_time > pto.
m_tx_relay->m_next_send_feefilter) {
4452 CAmount filterToSend = g_filter_rounder.round(currentFilter);
4455 if (filterToSend != pto.
m_tx_relay->lastSentFeeFilter) {
4457 pto.
m_tx_relay->lastSentFeeFilter = filterToSend;
4463 else if (current_time + MAX_FEEFILTER_CHANGE_DELAY < pto.m_tx_relay->m_next_send_feefilter &&
4464 (currentFilter < 3 * pto.m_tx_relay->lastSentFeeFilter / 4 || currentFilter > 4 * pto.
m_tx_relay->lastSentFeeFilter / 3)) {
4470class CompareInvMempoolOrder
4475 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
4478 m_wtxid_relay = use_wtxid;
4481 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
4490bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
4495 if (
node.IsBlockOnlyConn())
return false;
4497 if (!peer.m_addr_relay_enabled.exchange(
true)) {
4500 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
4506bool PeerManagerImpl::SendMessages(
CNode* pto)
4508 PeerRef peer = GetPeerRef(pto->
GetId());
4509 if (!peer)
return false;
4514 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
4523 const auto current_time = GetTime<std::chrono::microseconds>();
4531 MaybeSendPing(*pto, *peer, current_time);
4536 MaybeSendAddr(*pto, *peer, current_time);
4541 CNodeState &state = *State(pto->
GetId());
4546 bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->
fClient && !pto->
IsAddrFetchConn());
4550 state.fSyncStarted =
true;
4567 if (pindexStart->
pprev)
4568 pindexStart = pindexStart->
pprev;
4585 LOCK(peer->m_block_inv_mutex);
4586 std::vector<CBlock> vHeaders;
4587 bool fRevertToInv = ((!state.fPreferHeaders &&
4588 (!state.fPreferHeaderAndIDs || peer->m_blocks_for_headers_relay.size() > 1)) ||
4591 ProcessBlockAvailability(pto->
GetId());
4593 if (!fRevertToInv) {
4594 bool fFoundStartingHeader =
false;
4598 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
4599 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
4603 fRevertToInv =
true;
4606 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
4618 fRevertToInv =
true;
4621 pBestIndex = pindex;
4622 if (fFoundStartingHeader) {
4625 }
else if (PeerHasHeader(&state, pindex)) {
4627 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
4630 fFoundStartingHeader =
true;
4635 fRevertToInv =
true;
4640 if (!fRevertToInv && !vHeaders.empty()) {
4641 if (vHeaders.size() == 1 && state.fPreferHeaderAndIDs) {
4645 vHeaders.front().GetHash().ToString(), pto->
GetId());
4649 bool fGotBlockFromCache =
false;
4652 if (most_recent_block_hash == pBestIndex->
GetBlockHash()) {
4653 if (state.fWantsCmpctWitness || !fWitnessesPresentInMostRecentCompactBlock)
4659 fGotBlockFromCache =
true;
4662 if (!fGotBlockFromCache) {
4669 state.pindexBestHeaderSent = pBestIndex;
4670 }
else if (state.fPreferHeaders) {
4671 if (vHeaders.size() > 1) {
4674 vHeaders.front().GetHash().ToString(),
4675 vHeaders.back().GetHash().ToString(), pto->
GetId());
4678 vHeaders.front().GetHash().ToString(), pto->
GetId());
4681 state.pindexBestHeaderSent = pBestIndex;
4683 fRevertToInv =
true;
4689 if (!peer->m_blocks_for_headers_relay.empty()) {
4690 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
4691 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hashToAnnounce);
4703 if (!PeerHasHeader(&state, pindex)) {
4704 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
4710 peer->m_blocks_for_headers_relay.clear();
4716 std::vector<CInv> vInv;
4718 LOCK(peer->m_block_inv_mutex);
4722 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
4729 peer->m_blocks_for_inv_relay.clear();
4736 if (pto->
m_tx_relay->nNextInvSend < current_time) {
4737 fSendTrickle =
true;
4752 if (fSendTrickle && pto->
m_tx_relay->fSendMempool) {
4753 auto vtxinfo = m_mempool.
infoAll();
4759 for (
const auto& txinfo : vtxinfo) {
4760 const uint256& hash = state.m_wtxid_relay ? txinfo.tx->GetWitnessHash() : txinfo.tx->GetHash();
4762 pto->
m_tx_relay->setInventoryTxToSend.erase(hash);
4764 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
4768 if (!pto->
m_tx_relay->pfilter->IsRelevantAndUpdate(*txinfo.tx))
continue;
4770 pto->
m_tx_relay->filterInventoryKnown.insert(hash);
4772 vInv.push_back(inv);
4778 pto->
m_tx_relay->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time);
4784 std::vector<std::set<uint256>::iterator> vInvTx;
4785 vInvTx.reserve(pto->
m_tx_relay->setInventoryTxToSend.size());
4786 for (std::set<uint256>::iterator it = pto->
m_tx_relay->setInventoryTxToSend.begin(); it != pto->
m_tx_relay->setInventoryTxToSend.end(); it++) {
4787 vInvTx.push_back(it);
4792 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, state.m_wtxid_relay);
4793 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
4796 unsigned int nRelayedTransactions = 0;
4800 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
4801 std::set<uint256>::iterator it = vInvTx.back();
4806 pto->
m_tx_relay->setInventoryTxToSend.erase(it);
4808 if (pto->
m_tx_relay->filterInventoryKnown.contains(hash)) {
4816 auto txid = txinfo.tx->GetHash();
4817 auto wtxid = txinfo.tx->GetWitnessHash();
4819 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
4822 if (pto->
m_tx_relay->pfilter && !pto->
m_tx_relay->pfilter->IsRelevantAndUpdate(*txinfo.tx))
continue;
4824 State(pto->
GetId())->m_recently_announced_invs.insert(hash);
4825 vInv.push_back(inv);
4826 nRelayedTransactions++;
4829 while (!g_relay_expiration.empty() && g_relay_expiration.front().first < current_time)
4831 mapRelay.erase(g_relay_expiration.front().second);
4832 g_relay_expiration.pop_front();
4835 auto ret = mapRelay.emplace(txid, std::move(txinfo.tx));
4840 auto ret2 = mapRelay.emplace(wtxid, ret.first->second);
4849 pto->
m_tx_relay->filterInventoryKnown.insert(hash);
4856 pto->
m_tx_relay->filterInventoryKnown.insert(txid);
4869 LogPrintf(
"Peer=%d is stalling block download, disconnecting\n", pto->
GetId());
4878 if (state.vBlocksInFlight.size() > 0) {
4879 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
4880 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
4882 LogPrintf(
"Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.pindex->GetBlockHash().ToString(), pto->
GetId());
4888 if (state.fSyncStarted && state.m_headers_sync_timeout < std::chrono::microseconds::max()) {
4891 if (current_time > state.m_headers_sync_timeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1)) {
4898 LogPrintf(
"Timeout downloading headers from peer=%d, disconnecting\n", pto->
GetId());
4902 LogPrintf(
"Timeout downloading headers from noban peer=%d, not disconnecting\n", pto->
GetId());
4908 state.fSyncStarted =
false;
4910 state.m_headers_sync_timeout = 0us;
4916 state.m_headers_sync_timeout = std::chrono::microseconds::max();
4922 ConsiderEviction(*pto,
GetTime());
4927 std::vector<CInv> vGetData;
4929 std::vector<const CBlockIndex*> vToDownload;
4935 BlockRequested(pto->
GetId(), *pindex);
4939 if (state.nBlocksInFlight == 0 && staller != -1) {
4940 if (State(staller)->m_stalling_since == 0us) {
4941 State(staller)->m_stalling_since = current_time;
4950 std::vector<std::pair<NodeId, GenTxid>> expired;
4951 auto requestable = m_txrequest.GetRequestable(pto->
GetId(), current_time, &expired);
4952 for (
const auto& entry : expired) {
4953 LogPrint(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ?
"wtx" :
"tx",
4954 entry.second.GetHash().ToString(), entry.first);
4956 for (
const GenTxid& gtxid : requestable) {
4957 if (!AlreadyHaveTx(gtxid)) {
4969 m_txrequest.ForgetTxHash(gtxid.
GetHash());
4974 if (!vGetData.empty())
4977 MaybeSendFeefilter(*pto, current_time);
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
bool ReadRawBlockFromDisk(std::vector< uint8_t > &block, const FlatFilePos &pos, const CMessageHeader::MessageStartChars &message_start)
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos, const Consensus::Params &consensusParams)
Functions for disk access for blocks.
bool fPruneMode
True if we're running in -prune mode.
std::atomic_bool fReindex
std::atomic_bool fImporting
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
@ BLOCK_VALID_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
@ BLOCK_HAVE_DATA
full block available in blk*.dat
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Attempt to add one or more addresses to addrman's new table.
void Good(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as accessible, possibly moving it from "new" to "tried".
void Connected(const CService &addr, int64_t nTime=GetAdjustedTime())
We have successfully connected to this peer.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void Discourage(const CNetAddr &net_addr)
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out)
Get a single filter header by block.
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.
std::vector< CTransactionRef > txn
std::vector< uint16_t > indexes
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
uint32_t nTime
Always included in serialization.
size_t BlockTxCount() const
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveTxsDownloaded() const
Check whether this block's and all previous blocks' transactions have been downloaded (and stored to ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
unsigned int nTx
Number of transactions in this block.
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
uint32_t nStatus
Verification status of this block.
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockLocator GetLocator(const CBlockIndex *pindex=nullptr) const
Return a CBlockLocator that refers to a block in this chain (by default the tip).
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const Consensus::Params & GetConsensus() const
const CMessageHeader::MessageStartChars & MessageStart() const
CChainState stores and provides an API to update our local knowledge of the current best chain.
bool ActivateBestChain(BlockValidationState &state, std::shared_ptr< const CBlock > pblock=nullptr) LOCKS_EXCLUDED(cs_main)
Find the best known block, and make it the tip of the block chain.
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void UnloadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
CChain m_chain
The current chain of blockheaders we consult and build on.
void ForEachNode(const NodeFn &func)
bool OutboundTargetReached(bool historicalBlockServingLimit) const
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool GetTryNewOutboundPeer() const
void SetTryNewOutboundPeer(bool flag)
unsigned int GetReceiveFloodSize() const
bool ShouldRunInactivityChecks(const CNode &node, int64_t secs_now) const
Return true if we should disconnect the peer for failing an inactivity check.
int GetExtraBlockRelayCount() const
void StartExtraBlockRelayPeers()
bool DisconnectNode(const std::string &node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network) const
Return all or many randomly selected addresses, optionally by network.
void WakeMessageHandler()
std::chrono::microseconds PoissonNextSendInbound(std::chrono::microseconds now, std::chrono::seconds average_interval)
Attempts to obfuscate tx time through exponentially distributed emitting.
bool CheckIncomingNonce(uint64_t nonce)
void PushMessage(CNode *pnode, CSerializedNetMsg &&msg)
bool GetUseAddrmanOutgoing() const
Double ended buffer combining vector and stream-like interfaces.
Fee rate in satoshis per kilobyte: CAmount / kB.
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, uint256 > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
void SetIP(const CNetAddr &ip)
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
CSerializedNetMsg Make(int nFlags, std::string msg_type, Args &&... args) const
Information about a peer.
RecursiveMutex cs_vProcessMsg
bool IsFeelerConn() const
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
std::atomic_bool fPauseRecv
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
void PushTxInventory(const uint256 &hash)
std::atomic< int64_t > nTimeOffset
const std::string m_addr_name
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
void SetAddrLocal(const CService &addrLocalIn)
May not be called more than once.
std::atomic< bool > m_bip152_highbandwidth_from
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
std::atomic< ServiceFlags > nServices
const int64_t nTimeConnected
Unix epoch time at peer connection, in seconds.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
std::atomic_bool fPauseSend
std::unique_ptr< TxRelay > m_tx_relay
std::atomic< int64_t > nLastTXTime
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
ServiceFlags GetLocalServices() const
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
void AddKnownTx(const uint256 &hash)
std::atomic< int64_t > nLastBlockTime
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::atomic_bool fDisconnect
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleFromNow(Function f, std::chrono::milliseconds delta)
Call f once after the delta has passed.
void scheduleEvery(Function f, std::chrono::milliseconds delta)
Repeat f until the scheduler is stopped.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToString() const
std::vector< unsigned char > GetKey() const
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
The basic transaction that is broadcasted on the network and contained in blocks.
const uint256 & GetWitnessHash() const
const uint256 & GetHash() const
const std::vector< CTxIn > vin
An input of a transaction.
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
std::set< CTxMemPoolEntryRef, CompareIteratorByHash > Parents
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
std::set< uint256 > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
CFeeRate GetMinFee(size_t sizelimit) const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
std::optional< txiter > GetIter(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given hash, if found.
CTransactionRef get(const uint256 &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
TxMempoolInfo info(const GenTxid >xid) const
bool exists(const GenTxid >xid) const
bool CompareDepthAndScore(const uint256 &hasha, const uint256 &hashb, bool wtxid=false)
unsigned long size() const
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void BlockConnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
bool ProcessNewBlock(const CChainParams &chainparams, const std::shared_ptr< const CBlock > &block, bool force_processing, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
CChainState & ActiveChainstate() const
The most-work chain.
bool ProcessNewBlockHeaders(const std::vector< CBlockHeader > &block, BlockValidationState &state, const CChainParams &chainparams, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
CChain & ActiveChain() const
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
A generic txid reference (txid or wtxid).
const uint256 & GetHash() const
static GenTxid Wtxid(const uint256 &hash)
static GenTxid Txid(const uint256 &hash)
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual void InitializeNode(CNode *pnode)=0
Initialize a peer (setup state, queue any initial messages)
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(pnode -> cs_sendProcessing)=0
Send queued protocol messages to a given node.
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt)=0
Process protocol messages received from a given node.
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< uint256, CTransactionRef > > &extra_txn)
bool IsTxAvailable(size_t index) const
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
virtual void RelayTransaction(const uint256 &txid, const uint256 &wtxid)=0
Relay transaction to all peers.
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.
static std::unique_ptr< PeerManager > make(const CChainParams &chainparams, CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, bool ignore_incoming_txs)
virtual void SendPings()=0
Send ping message to all peers.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
virtual void SetBestHeight(int height)=0
Set the best height.
virtual bool IgnoresIncomingTxs()=0
Whether this node ignores txs received over p2p.
virtual void Misbehaving(const NodeId pnode, const int howmuch, const std::string &message)=0
Increment peer's misbehavior score.
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
Data structure to keep track of, and schedule, transaction downloads from peers.
std::string ToString() const
std::string ToString() const
@ BLOCK_CHECKPOINT
the block failed to meet one of our checkpoints
@ BLOCK_RECENT_CONSENSUS_CHANGE
Invalid by a change to consensus rules more recent than SegWit.
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ BLOCK_RESULT_UNSET
initial value. Block has not yet been rejected
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_MEMPOOL_POLICY
violated mempool's fee/size/descendant/RBF/etc limits
@ TX_PREMATURE_SPEND
transaction spends a coinbase too early, or violates locktime/sequence locks
@ TX_INPUTS_NOT_STANDARD
inputs (covered by txid) failed policy rules
@ TX_WITNESS_STRIPPED
Transaction is missing a witness.
@ TX_CONFLICT
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
@ TX_RECENT_CONSENSUS_CHANGE
Invalid by a change to consensus rules more recent than SegWit.
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
@ TX_WITNESS_MUTATED
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
@ TX_RESULT_UNSET
initial value. Tx has not yet been rejected
@ TX_CONSENSUS
invalid by consensus rules
static size_t RecursiveDynamicUsage(const CScript &script)
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep)
Determine if a deployment is active for this block.
if(na.IsAddrV1Compatible())
#define LogPrint(category,...)
const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
const char * BLOCK
The block message transmits a single serialized block.
const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
const char * TX
The tx message transmits a single transaction.
const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
const char * GETDATA
The getdata message requests one or more data objects from another node.
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
const char * BLOCKTXN
Contains a BlockTransactions.
const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
bool IsPeerAddrLocalGood(CNode *pnode)
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
void CaptureMessage(const CAddress &addr, const std::string &msg_type, const Span< const unsigned char > &data, bool is_incoming)
Dump binary message to file, with timestamp.
std::optional< CAddress > GetLocalAddrForPeer(CNode *pnode)
Returns a local address that we should advertise to this peer.
bool IsReachable(enum Network net)
bool SeenLocal(const CService &addr)
vote for a local address
std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::seconds average_interval)
Return a timestamp in the future (in microseconds) for exponentially distributed events.
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
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 AVG_FEEFILTER_BROADCAST_INTERVAL
Verify that INVENTORY_MAX_RECENT_RELAY is enough to cache everything typically relayed before uncondi...
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static const int MAX_UNCONNECTING_HEADERS
Maximum number of unconnecting headers announcements before DoS score.
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static constexpr auto RELAY_TX_CACHE_TIME
How long to cache transactions in mapRelay for normal relay.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static std::shared_ptr< const CBlock > most_recent_block GUARDED_BY(cs_most_recent_block)
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT
Maximum number of in-flight transaction requests from a peer.
static constexpr auto OVERLOADED_PEER_TX_DELAY
How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT).
static RecursiveMutex cs_most_recent_block
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr std::chrono::microseconds GETDATA_TX_INTERVAL
How long to wait (in microseconds) before downloading a transaction from an additional peer.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr auto BLOCK_STALLING_TIMEOUT
Time during which a peer must stall block download progress before being disconnected.
static uint32_t GetFetchFlags(const CNode &pfrom) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr int64_t STALE_CHECK_INTERVAL
How frequently to check for stale tips, in seconds.
void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)
static constexpr std::chrono::minutes PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr int64_t MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict,...
static constexpr unsigned int INVENTORY_MAX_RECENT_RELAY
The number of most recently announced transactions a peer can request.
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 auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static constexpr int64_t EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect, in seconds.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
static constexpr auto TXID_RELAY_DELAY
How long to delay requesting transactions via txids, if we have wtxid-relaying peers.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr auto NONPREF_PEER_TX_DELAY
How long to delay requesting transactions from non-preferred peers.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static constexpr int64_t CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork, in seconds.
static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN
Default number of orphan+recently-replaced txn to keep around for block reconstruction.
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS
Default for -maxorphantx, maximum number of orphan transactions kept in memory.
static const int DISCOURAGEMENT_THRESHOLD
Threshold for marking a node to be discouraged, e.g.
static constexpr int ADDRV2_FORMAT
A flag that is ORed into the protocol version to designate that addresses should be serialized in (un...
bool IsProxy(const CNetAddr &addr)
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE
Default for -maxmempool, maximum megabytes of mempool memory usage.
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...
std::shared_ptr< const CTransaction > CTransactionRef
void SetServiceFlagsIBDCache(bool state)
Set the current IBD status in order to figure out the desirable service flags.
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
ServiceFlags GetDesirableServiceFlags(ServiceFlags services)
Gets the set of service flags which are "desirable" for a given peer.
static bool HasAllDesirableServiceFlags(ServiceFlags services)
A shortcut for (services & GetDesirableServiceFlags(services)) == GetDesirableServiceFlags(services),...
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
constexpr auto GetRandMillis
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
reverse_range< T > reverse_iterate(T &x)
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(MakeSpan(std::forward< V >(v))))
Like MakeSpan, but for (const) unsigned char member types only.
std::vector< unsigned char > ParseHex(const char *psz)
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds m_ping_wait
std::vector< int > vHeightInFlight
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
std::vector< unsigned char > data
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
Validation result for a single transaction mempool acceptance.
const ResultType m_result_type
const std::optional< std::list< CTransactionRef > > m_replaced_transactions
Mempool transactions replaced by the tx per BIP 125 rules.
const TxValidationState m_state
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
int64_t GetTime()
DEPRECATED Use either GetTimeSeconds (not mockable) or GetTime<T> (mockable)
constexpr int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
Helper to count the seconds of a duration.
double CountSecondsDouble(SecondsDouble t)
Helper to count the seconds in any std::chrono::duration type.
int64_t GetAdjustedTime()
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
#define TRACE6(context, event, a, b, c, d, e, f)
RecursiveMutex g_cs_orphans
Guards orphan transactions and extra txs for compact blocks.
arith_uint256 nMinimumChainWork
Minimum work we will assume exists on some valid chain.
CFeeRate minRelayTxFee
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
MempoolAcceptResult AcceptToMemoryPool(CChainState &active_chainstate, CTxMemPool &pool, const CTransactionRef &tx, bool bypass_limits, bool test_accept)
(Try to) add a transaction to the memory pool.
CBlockIndex * pindexBestHeader
Best header we've seen so far (used for getheaders queries' starting points).
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...
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static const int WTXID_RELAY_VERSION
"wtxidrelay" command for wtxid-based relay starts with this version
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.