173 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
193 Mutex m_misbehavior_mutex;
195 int m_misbehavior_score
GUARDED_BY(m_misbehavior_mutex){0};
197 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
200 Mutex m_block_inv_mutex;
204 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
208 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
216 std::atomic<int> m_starting_height{-1};
219 std::atomic<uint64_t> m_ping_nonce_sent{0};
221 std::atomic<std::chrono::microseconds> m_ping_start{0us};
223 std::atomic<bool> m_ping_queued{
false};
226 std::vector<CAddress> m_addrs_to_send;
229 const std::unique_ptr<CRollingBloomFilter> m_addr_known;
231 bool m_getaddr_sent{
false};
233 mutable Mutex m_addr_send_times_mutex;
235 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
237 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
240 std::atomic_bool m_wants_addrv2{
false};
242 bool m_getaddr_recvd{
false};
245 double m_addr_token_bucket{1.0};
247 std::chrono::microseconds m_addr_token_timestamp{GetTime<std::chrono::microseconds>()};
249 std::atomic<uint64_t> m_addr_rate_limited{0};
251 std::atomic<uint64_t> m_addr_processed{0};
257 Mutex m_getdata_requests_mutex;
259 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
261 explicit Peer(
NodeId id,
bool addr_relay)
263 , m_addr_known{addr_relay ? std::make_unique<CRollingBloomFilter>(5000, 0.001) : nullptr}
267 using PeerRef = std::shared_ptr<Peer>;
295 void SetBestHeight(
int height)
override { m_best_height = height; };
296 void Misbehaving(
const NodeId pnode,
const int howmuch,
const std::string& message)
override;
298 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override;
311 void ReattemptInitialBroadcast(
CScheduler& scheduler);
315 PeerRef GetPeerRef(
NodeId id)
const;
319 PeerRef RemovePeer(
NodeId id);
332 bool via_compact_block,
const std::string& message =
"");
347 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
351 void ProcessHeadersMessage(
CNode& pfrom,
const Peer& peer,
352 const std::vector<CBlockHeader>& headers,
353 bool via_compact_block);
360 void AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
364 void PushNodeVersion(
CNode& pnode, int64_t nTime);
370 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
373 void MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time);
382 void RelayAddress(
NodeId originator,
const CAddress& addr,
bool fReachable);
397 std::atomic<int> m_best_height{-1};
399 int64_t m_stale_tip_check_time;
402 const bool m_ignore_incoming_txs;
406 bool m_initial_sync_finished{
false};
410 mutable Mutex m_peer_mutex;
417 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
480 Mutex m_recent_confirmed_transactions_mutex;
481 std::unique_ptr<CRollingBloomFilter> m_recent_confirmed_transactions
GUARDED_BY(m_recent_confirmed_transactions_mutex);
508 std::atomic<int64_t> m_last_tip_update{0};
516 void ProcessBlock(
CNode&
node, const
std::shared_ptr<const
CBlock>& block,
bool force_processing);
564 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv);
580 bool PrepareBlockFilterRequest(
CNode& peer,
582 const
uint256& stop_hash, uint32_t max_height_diff,
634 uint256 hashLastUnknownBlock{};
640 int nUnconnectingHeaders{0};
642 bool fSyncStarted{
false};
644 std::chrono::microseconds m_headers_sync_timeout{0us};
646 std::chrono::microseconds m_stalling_since{0us};
647 std::list<QueuedBlock> vBlocksInFlight;
649 std::chrono::microseconds m_downloading_since{0us};
650 int nBlocksInFlight{0};
652 bool fPreferredDownload{
false};
654 bool fPreferHeaders{
false};
656 bool fPreferHeaderAndIDs{
false};
662 bool fProvidesHeaderAndIDs{
false};
664 bool fHaveWitness{
false};
666 bool fWantsCmpctWitness{
false};
671 bool fSupportsDesiredCmpctVersion{
false};
697 struct ChainSyncTimeoutState {
699 int64_t m_timeout{0};
703 bool m_sent_getheaders{
false};
705 bool m_protect{
false};
708 ChainSyncTimeoutState m_chain_sync;
711 int64_t m_last_block_announcement{0};
714 const bool m_is_inbound;
720 bool m_wtxid_relay{
false};
722 CNodeState(
bool is_inbound) : m_is_inbound(is_inbound) {}
729 std::map<NodeId, CNodeState>::iterator it = mapNodeState.find(pnode);
730 if (it == mapNodeState.end())
735 static bool RelayAddrsWithPeer(
const Peer& peer)
737 return peer.m_addr_known !=
nullptr;
745 static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
750 static void AddAddressKnown(Peer& peer,
const CAddress& addr)
752 assert(peer.m_addr_known);
753 peer.m_addr_known->insert(addr.
GetKey());
761 assert(peer.m_addr_known);
762 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
764 peer.m_addrs_to_send[insecure_rand.
randrange(peer.m_addrs_to_send.size())] = addr;
766 peer.m_addrs_to_send.push_back(addr);
773 nPreferredDownload -= state->fPreferredDownload;
778 nPreferredDownload += state->fPreferredDownload;
781 bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
783 return mapBlocksInFlight.find(hash) != mapBlocksInFlight.end();
786 void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash)
788 auto it = mapBlocksInFlight.find(hash);
789 if (it == mapBlocksInFlight.end()) {
794 auto [node_id, list_it] = it->second;
795 CNodeState *state =
State(node_id);
798 if (state->vBlocksInFlight.begin() == list_it) {
800 state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
802 state->vBlocksInFlight.erase(list_it);
804 state->nBlocksInFlight--;
805 if (state->nBlocksInFlight == 0) {
807 m_peers_downloading_from--;
809 state->m_stalling_since = 0us;
810 mapBlocksInFlight.erase(it);
813 bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
817 CNodeState *state =
State(nodeid);
821 std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
822 if (itInFlight != mapBlocksInFlight.end() && itInFlight->second.first == nodeid) {
824 *pit = &itInFlight->second.second;
830 RemoveBlockRequest(hash);
832 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
834 state->nBlocksInFlight++;
835 if (state->nBlocksInFlight == 1) {
837 state->m_downloading_since = GetTime<std::chrono::microseconds>();
838 m_peers_downloading_from++;
840 itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it))).first;
842 *pit = &itInFlight->second.second;
847 void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
850 CNodeState* nodestate =
State(nodeid);
851 if (!nodestate || !nodestate->fSupportsDesiredCmpctVersion) {
855 if (nodestate->fProvidesHeaderAndIDs) {
856 int num_outbound_hb_peers = 0;
857 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
859 lNodesAnnouncingHeaderAndIDs.erase(it);
860 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
863 CNodeState *state =
State(*it);
864 if (state !=
nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
866 if (nodestate->m_is_inbound) {
869 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
870 CNodeState *remove_node =
State(lNodesAnnouncingHeaderAndIDs.front());
871 if (remove_node !=
nullptr && !remove_node->m_is_inbound) {
874 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
881 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
884 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this, nCMPCTBLOCKVersion](
CNode* pnodeStop){
887 pnodeStop->m_bip152_highbandwidth_to =
false;
890 lNodesAnnouncingHeaderAndIDs.pop_front();
895 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
901 bool PeerManagerImpl::TipMayBeStale()
905 if (m_last_tip_update == 0) {
911 bool PeerManagerImpl::CanDirectFetch()
918 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
920 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
925 void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
926 CNodeState *state =
State(nodeid);
929 if (!state->hashLastUnknownBlock.IsNull()) {
930 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock);
932 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
933 state->pindexBestKnownBlock = pindex;
935 state->hashLastUnknownBlock.SetNull();
940 void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
941 CNodeState *state =
State(nodeid);
944 ProcessBlockAvailability(nodeid);
946 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
949 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
950 state->pindexBestKnownBlock = pindex;
954 state->hashLastUnknownBlock = hash;
958 void PeerManagerImpl::FindNextBlocksToDownload(
NodeId nodeid,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
963 vBlocks.reserve(vBlocks.size() +
count);
964 CNodeState *state =
State(nodeid);
968 ProcessBlockAvailability(nodeid);
975 if (state->pindexLastCommonBlock ==
nullptr) {
978 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
983 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
984 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
988 std::vector<const CBlockIndex*> vToFetch;
989 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
994 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
996 while (pindexWalk->
nHeight < nMaxHeight) {
1000 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1001 vToFetch.resize(nToFetch);
1002 pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->
nHeight + nToFetch);
1003 vToFetch[nToFetch - 1] = pindexWalk;
1004 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1005 vToFetch[i - 1] = vToFetch[i]->
pprev;
1023 state->pindexLastCommonBlock = pindex;
1024 }
else if (!IsBlockRequested(pindex->
GetBlockHash())) {
1026 if (pindex->
nHeight > nWindowEnd) {
1028 if (vBlocks.size() == 0 && waitingfor != nodeid) {
1030 nodeStaller = waitingfor;
1034 vBlocks.push_back(pindex);
1035 if (vBlocks.size() ==
count) {
1038 }
else if (waitingfor == -1) {
1040 waitingfor = mapBlocksInFlight[pindex->
GetBlockHash()].first;
1048 void PeerManagerImpl::PushNodeVersion(
CNode& pnode, int64_t nTime)
1055 const int nNodeStartingHeight{m_best_height};
1064 const bool tx_relay = !m_ignore_incoming_txs && pnode.
m_tx_relay !=
nullptr;
1069 LogPrint(
BCLog::NET,
"send version message: version %d, blocks=%d, us=%s, them=%s, txrelay=%d, peer=%d\n",
PROTOCOL_VERSION, nNodeStartingHeight, addrMe.
ToString(), addrYou.
ToString(), tx_relay, nodeid);
1071 LogPrint(
BCLog::NET,
"send version message: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d\n",
PROTOCOL_VERSION, nNodeStartingHeight, addrMe.
ToString(), tx_relay, nodeid);
1075 void PeerManagerImpl::AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
1083 const CNodeState* state =
State(nodeid);
1092 auto delay = std::chrono::microseconds{0};
1093 const bool preferred = state->fPreferredDownload;
1099 m_txrequest.ReceivedInv(nodeid, gtxid, preferred, current_time + delay);
1108 if (state) state->m_last_block_announcement = time_in_seconds;
1111 void PeerManagerImpl::InitializeNode(
CNode *pnode)
1116 mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(pnode->
IsInboundConn()));
1117 assert(m_txrequest.Count(nodeid) == 0);
1122 PeerRef peer = std::make_shared<Peer>(nodeid, !pnode->
IsBlockOnlyConn());
1124 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer));
1127 PushNodeVersion(*pnode,
GetTime());
1131 void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1135 for (
const auto& txid : unbroadcast_txids) {
1138 if (tx !=
nullptr) {
1140 _RelayTransaction(txid, tx->GetWitnessHash());
1148 const std::chrono::milliseconds delta = std::chrono::minutes{10} +
GetRandMillis(std::chrono::minutes{5});
1149 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1152 void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1164 PeerRef peer = RemovePeer(nodeid);
1166 misbehavior =
WITH_LOCK(peer->m_misbehavior_mutex,
return peer->m_misbehavior_score);
1168 CNodeState *state =
State(nodeid);
1169 assert(state !=
nullptr);
1171 if (state->fSyncStarted)
1174 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1175 mapBlocksInFlight.erase(entry.pindex->GetBlockHash());
1178 m_txrequest.DisconnectedPeer(nodeid);
1179 nPreferredDownload -= state->fPreferredDownload;
1180 m_peers_downloading_from -= (state->nBlocksInFlight != 0);
1181 assert(m_peers_downloading_from >= 0);
1182 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1183 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1184 m_wtxid_relay_peers -= state->m_wtxid_relay;
1185 assert(m_wtxid_relay_peers >= 0);
1187 mapNodeState.erase(nodeid);
1189 if (mapNodeState.empty()) {
1191 assert(mapBlocksInFlight.empty());
1192 assert(nPreferredDownload == 0);
1193 assert(m_peers_downloading_from == 0);
1194 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1195 assert(m_wtxid_relay_peers == 0);
1196 assert(m_txrequest.Size() == 0);
1199 if (
node.fSuccessfullyConnected && misbehavior == 0 &&
1200 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1209 PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const 1212 auto it = m_peer_map.find(
id);
1213 return it != m_peer_map.end() ? it->second :
nullptr;
1216 PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1220 auto it = m_peer_map.find(
id);
1221 if (it != m_peer_map.end()) {
1222 ret = std::move(it->second);
1223 m_peer_map.erase(it);
1232 CNodeState* state =
State(nodeid);
1233 if (state ==
nullptr)
1235 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1236 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1237 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1243 PeerRef peer = GetPeerRef(nodeid);
1244 if (peer ==
nullptr)
return false;
1252 std::chrono::microseconds ping_wait{0};
1253 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1254 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1264 void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1267 if (max_extra_txn <= 0)
1269 if (!vExtraTxnForCompact.size())
1270 vExtraTxnForCompact.resize(max_extra_txn);
1271 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1272 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % max_extra_txn;
1275 void PeerManagerImpl::Misbehaving(
const NodeId pnode,
const int howmuch,
const std::string& message)
1279 PeerRef peer = GetPeerRef(pnode);
1280 if (peer ==
nullptr)
return;
1282 LOCK(peer->m_misbehavior_mutex);
1283 peer->m_misbehavior_score += howmuch;
1284 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1286 LogPrint(
BCLog::NET,
"Misbehaving: peer=%d (%d -> %d) DISCOURAGE THRESHOLD EXCEEDED%s\n", pnode, peer->m_misbehavior_score - howmuch, peer->m_misbehavior_score, message_prefixed);
1287 peer->m_should_discourage =
true;
1289 LogPrint(
BCLog::NET,
"Misbehaving: peer=%d (%d -> %d)%s\n", pnode, peer->m_misbehavior_score - howmuch, peer->m_misbehavior_score, message_prefixed);
1294 bool via_compact_block,
const std::string& message)
1302 if (!via_compact_block) {
1310 CNodeState *node_state =
State(nodeid);
1311 if (node_state ==
nullptr) {
1317 if (!via_compact_block && !node_state->m_is_inbound) {
1337 if (message !=
"") {
1343 bool PeerManagerImpl::MaybePunishNodeForTx(
NodeId nodeid,
const TxValidationState& state,
const std::string& message)
1364 if (message !=
"") {
1370 bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1383 return std::make_unique<PeerManagerImpl>(chainparams, connman, addrman, banman, scheduler, chainman, pool, ignore_incoming_txs);
1389 : m_chainparams(chainparams),
1393 m_chainman(chainman),
1395 m_stale_tip_check_time(0),
1396 m_ignore_incoming_txs(ignore_incoming_txs)
1420 const std::chrono::milliseconds delta = std::chrono::minutes{10} +
GetRandMillis(std::chrono::minutes{5});
1421 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1429 void PeerManagerImpl::BlockConnected(
const std::shared_ptr<const CBlock>& pblock,
const CBlockIndex* pindex)
1431 m_orphanage.EraseForBlock(*pblock);
1432 m_last_tip_update =
GetTime();
1435 LOCK(m_recent_confirmed_transactions_mutex);
1436 for (
const auto& ptx : pblock->vtx) {
1437 m_recent_confirmed_transactions->insert(ptx->GetHash());
1438 if (ptx->GetHash() != ptx->GetWitnessHash()) {
1439 m_recent_confirmed_transactions->insert(ptx->GetWitnessHash());
1445 for (
const auto& ptx : pblock->vtx) {
1446 m_txrequest.ForgetTxHash(ptx->GetHash());
1447 m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
1452 void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
1462 LOCK(m_recent_confirmed_transactions_mutex);
1463 m_recent_confirmed_transactions->reset();
1477 void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
1479 std::shared_ptr<const CBlockHeaderAndShortTxIDs> pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs> (*pblock,
true);
1484 static int nHighestFastAnnounce = 0;
1485 if (pindex->
nHeight <= nHighestFastAnnounce)
1487 nHighestFastAnnounce = pindex->
nHeight;
1490 uint256 hashBlock(pblock->GetHash());
1494 most_recent_block_hash = hashBlock;
1495 most_recent_block = pblock;
1496 most_recent_compact_block = pcmpctblock;
1497 fWitnessesPresentInMostRecentCompactBlock = fWitnessEnabled;
1506 ProcessBlockAvailability(pnode->
GetId());
1510 if (state.fPreferHeaderAndIDs && (!fWitnessEnabled || state.fWantsCmpctWitness) &&
1511 !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
1513 LogPrint(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
1514 hashBlock.ToString(), pnode->
GetId());
1516 state.pindexBestHeaderSent = pindex;
1525 void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
1527 SetBestHeight(pindexNew->
nHeight);
1531 if (fInitialDownload)
return;
1534 std::vector<uint256> vHashes;
1536 while (pindexToAnnounce != pindexFork) {
1538 pindexToAnnounce = pindexToAnnounce->
pprev;
1548 for (
auto& it : m_peer_map) {
1549 Peer& peer = *it.second;
1550 LOCK(peer.m_block_inv_mutex);
1552 peer.m_blocks_for_headers_relay.push_back(hash);
1569 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
1574 it != mapBlockSource.end() &&
1575 State(it->second.first)) {
1576 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
1586 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
1587 if (it != mapBlockSource.end()) {
1588 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
1591 if (it != mapBlockSource.end())
1592 mapBlockSource.erase(it);
1601 bool PeerManagerImpl::AlreadyHaveTx(
const GenTxid& gtxid)
1610 recentRejects->reset();
1615 if (m_orphanage.HaveTx(gtxid))
return true;
1618 LOCK(m_recent_confirmed_transactions_mutex);
1619 if (m_recent_confirmed_transactions->contains(hash))
return true;
1622 return recentRejects->contains(hash) || m_mempool.
exists(gtxid);
1625 bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
1627 return m_chainman.m_blockman.LookupBlockIndex(block_hash) !=
nullptr;
1630 void PeerManagerImpl::SendPings()
1633 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
1636 void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
1641 void PeerManagerImpl::_RelayTransaction(
const uint256& txid,
const uint256& wtxid)
1647 if (state ==
nullptr)
return;
1648 if (state->m_wtxid_relay) {
1656 void PeerManagerImpl::RelayAddress(
NodeId originator,
1671 uint64_t hashAddr = addr.
GetHash();
1676 unsigned int nRelayNodes = (fReachable || (hasher.
Finalize() & 1)) ? 2 : 1;
1678 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
1679 assert(nRelayNodes <= best.size());
1683 for (
auto& [
id, peer] : m_peer_map) {
1684 if (RelayAddrsWithPeer(*peer) &&
id != originator && IsAddrCompatible(*peer, addr)) {
1686 for (
unsigned int i = 0; i < nRelayNodes; i++) {
1687 if (hashKey > best[i].first) {
1688 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
1689 best[i] = std::make_pair(hashKey, peer.get());
1696 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
1697 PushAddress(*best[i].second, addr, insecure_rand);
1701 void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
1703 std::shared_ptr<const CBlock> a_recent_block;
1704 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
1705 bool fWitnessesPresentInARecentCompactBlock;
1708 a_recent_block = most_recent_block;
1709 a_recent_compact_block = most_recent_compact_block;
1710 fWitnessesPresentInARecentCompactBlock = fWitnessesPresentInMostRecentCompactBlock;
1713 bool need_activate_chain =
false;
1716 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.
hash);
1725 need_activate_chain =
true;
1729 if (need_activate_chain) {
1737 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.
hash);
1741 if (!BlockRequestAllowed(pindex)) {
1742 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
1759 LogPrint(
BCLog::NET,
"Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.
GetId());
1769 std::shared_ptr<const CBlock> pblock;
1770 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
1771 pblock = a_recent_block;
1775 std::vector<uint8_t> block_data;
1777 assert(!
"cannot load block from disk");
1783 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
1785 assert(!
"cannot load block from disk");
1787 pblock = pblockRead;
1795 bool sendMerkleBlock =
false;
1800 sendMerkleBlock =
true;
1804 if (sendMerkleBlock) {
1812 typedef std::pair<unsigned int, uint256> PairType;
1823 bool fPeerWantsWitness =
State(pfrom.
GetId())->fWantsCmpctWitness;
1826 if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
1839 LOCK(peer.m_block_inv_mutex);
1841 if (inv.
hash == peer.m_continuation_block) {
1845 std::vector<CInv> vInv;
1848 peer.m_continuation_block.SetNull();
1853 CTransactionRef PeerManagerImpl::FindTxForGetData(
const CNode& peer,
const GenTxid& gtxid,
const std::chrono::seconds mempool_req,
const std::chrono::seconds now)
1855 auto txinfo = m_mempool.
info(gtxid);
1861 return std::move(txinfo.tx);
1870 if (txinfo.tx)
return std::move(txinfo.tx);
1872 auto mi = mapRelay.find(gtxid.
GetHash());
1873 if (mi != mapRelay.end())
return mi->second;
1880 void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
1884 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
1885 std::vector<CInv> vNotFound;
1888 const std::chrono::seconds now = GetTime<std::chrono::seconds>();
1890 const std::chrono::seconds mempool_req = pfrom.
m_tx_relay !=
nullptr ? pfrom.
m_tx_relay->m_last_mempool_req.load()
1891 : std::chrono::seconds::min();
1896 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
1897 if (interruptMsgProc)
return;
1902 const CInv &inv = *it++;
1916 std::vector<uint256> parent_ids_to_add;
1919 auto txiter = m_mempool.
GetIter(tx->GetHash());
1922 parent_ids_to_add.reserve(parents.size());
1925 parent_ids_to_add.push_back(parent.GetTx().GetHash());
1930 for (
const uint256& parent_txid : parent_ids_to_add) {
1934 State(pfrom.
GetId())->m_recently_announced_invs.insert(parent_txid);
1938 vNotFound.push_back(inv);
1944 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
1945 const CInv &inv = *it++;
1947 ProcessGetBlockData(pfrom, peer, inv);
1953 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
1955 if (!vNotFound.empty()) {
1975 uint32_t nFetchFlags = 0;
1985 for (
size_t i = 0; i < req.
indexes.size(); i++) {
1987 Misbehaving(pfrom.
GetId(), 100,
"getblocktxn with out-of-bounds tx indices");
1998 void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom,
const Peer& peer,
1999 const std::vector<CBlockHeader>& headers,
2000 bool via_compact_block)
2003 size_t nCount = headers.size();
2010 bool received_new_header =
false;
2014 CNodeState *nodestate =
State(pfrom.
GetId());
2024 if (!m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount <
MAX_BLOCKS_TO_ANNOUNCE) {
2025 nodestate->nUnconnectingHeaders++;
2027 LogPrint(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
2029 headers[0].hashPrevBlock.ToString(),
2031 pfrom.
GetId(), nodestate->nUnconnectingHeaders);
2035 UpdateBlockAvailability(pfrom.
GetId(), headers.back().GetHash());
2038 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"%d non-connecting headers", nodestate->nUnconnectingHeaders));
2045 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2046 Misbehaving(pfrom.
GetId(), 20,
"non-continuous headers sequence");
2049 hashLastBlock = header.GetHash();
2054 if (!m_chainman.m_blockman.LookupBlockIndex(hashLastBlock)) {
2055 received_new_header =
true;
2062 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
2069 CNodeState *nodestate =
State(pfrom.
GetId());
2070 if (nodestate->nUnconnectingHeaders > 0) {
2071 LogPrint(
BCLog::NET,
"peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom.
GetId(), nodestate->nUnconnectingHeaders);
2073 nodestate->nUnconnectingHeaders = 0;
2083 nodestate->m_last_block_announcement =
GetTime();
2091 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
2098 std::vector<const CBlockIndex*> vToFetch;
2106 vToFetch.push_back(pindexWalk);
2108 pindexWalk = pindexWalk->
pprev;
2119 std::vector<CInv> vGetData;
2128 BlockRequested(pfrom.
GetId(), *pindex);
2132 if (vGetData.size() > 1) {
2136 if (vGetData.size() > 0) {
2137 if (nodestate->fSupportsDesiredCmpctVersion && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->
pprev->
IsValid(
BLOCK_VALID_CHAIN)) {
2150 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork <
nMinimumChainWork) {
2160 LogPrintf(
"Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.
GetId());
2172 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) {
2174 nodestate->m_chain_sync.m_protect =
true;
2175 ++m_outbound_peers_with_protect_from_disconnect;
2191 void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
2196 while (!orphan_work_set.empty()) {
2198 orphan_work_set.erase(orphan_work_set.begin());
2200 const auto [porphanTx, from_peer] = m_orphanage.GetTx(orphanHash);
2201 if (porphanTx ==
nullptr)
continue;
2208 _RelayTransaction(orphanHash, porphanTx->GetWitnessHash());
2209 m_orphanage.AddChildrenToWorkSet(*porphanTx, orphan_work_set);
2210 m_orphanage.EraseTx(orphanHash);
2212 AddToCompactExtraTransactions(removedTx);
2216 if (state.IsInvalid()) {
2222 MaybePunishNodeForTx(from_peer, state);
2242 recentRejects->insert(porphanTx->GetWitnessHash());
2254 recentRejects->insert(porphanTx->GetHash());
2257 m_orphanage.EraseTx(orphanHash);
2264 bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode& peer,
2266 const uint256& stop_hash, uint32_t max_height_diff,
2270 const bool supported_filter_type =
2273 if (!supported_filter_type) {
2275 peer.
GetId(),
static_cast<uint8_t
>(filter_type));
2282 stop_index = m_chainman.m_blockman.LookupBlockIndex(stop_hash);
2285 if (!stop_index || !BlockRequestAllowed(stop_index)) {
2293 uint32_t stop_height = stop_index->
nHeight;
2294 if (start_height > stop_height) {
2296 "start height %d and stop height %d\n",
2297 peer.
GetId(), start_height, stop_height);
2301 if (stop_height - start_height >= max_height_diff) {
2303 peer.
GetId(), stop_height - start_height + 1, max_height_diff);
2309 if (!filter_index) {
2319 uint8_t filter_type_ser;
2320 uint32_t start_height;
2323 vRecv >> filter_type_ser >> start_height >> stop_hash;
2329 if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
2334 std::vector<BlockFilter> filters;
2336 LogPrint(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
2341 for (
const auto& filter : filters) {
2350 uint8_t filter_type_ser;
2351 uint32_t start_height;
2354 vRecv >> filter_type_ser >> start_height >> stop_hash;
2360 if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
2366 if (start_height > 0) {
2368 stop_index->
GetAncestor(static_cast<int>(start_height - 1));
2370 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
2376 std::vector<uint256> filter_hashes;
2378 LogPrint(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
2394 uint8_t filter_type_ser;
2397 vRecv >> filter_type_ser >> stop_hash;
2403 if (!PrepareBlockFilterRequest(peer, filter_type, 0, stop_hash,
2404 std::numeric_limits<uint32_t>::max(),
2405 stop_index, filter_index)) {
2413 for (
int i = headers.size() - 1; i >= 0; i--) {
2418 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
2432 void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing)
2434 bool new_block{
false};
2435 m_chainman.
ProcessNewBlock(m_chainparams, block, force_processing, &new_block);
2440 mapBlockSource.erase(block->GetHash());
2444 void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
CDataStream& vRecv,
2445 const std::chrono::microseconds time_received,
2446 const std::atomic<bool>& interruptMsgProc)
2450 PeerRef peer = GetPeerRef(pfrom.
GetId());
2451 if (peer ==
nullptr)
return;
2462 uint64_t nNonce = 1;
2463 uint64_t nServiceInt;
2466 std::string cleanSubVer;
2467 int starting_height = -1;
2470 vRecv >> nVersion >> nServiceInt >> nTime >> addrMe;
2494 vRecv >> addrFrom >> nNonce;
2495 if (!vRecv.
empty()) {
2496 std::string strSubVer;
2500 if (!vRecv.
empty()) {
2501 vRecv >> starting_height;
2534 if (greatest_common_version >= 70016) {
2548 pfrom.cleanSubVer = cleanSubVer;
2550 peer->m_starting_height = starting_height;
2572 UpdatePreferredDownload(pfrom,
State(pfrom.
GetId()));
2593 PushAddress(*peer, addr, insecure_rand);
2597 PushAddress(*peer, addr, insecure_rand);
2603 peer->m_getaddr_sent =
true;
2627 std::string remoteAddr;
2631 LogPrint(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s\n",
2633 peer->m_starting_height, addrMe.ToString(), fRelay, pfrom.
GetId(),
2636 int64_t nTimeOffset = nTime -
GetTime();
2641 if (greatest_common_version <= 70012) {
2642 CDataStream finalAlert(
ParseHex(
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"),
SER_NETWORK,
PROTOCOL_VERSION);
2670 LogPrintf(
"New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n",
2671 pfrom.
nVersion.load(), peer->m_starting_height,
2689 bool fAnnounceUsingCMPCTBLOCK =
false;
2690 uint64_t nCMPCTBLOCKVersion = 2;
2693 nCMPCTBLOCKVersion = 1;
2707 bool fAnnounceUsingCMPCTBLOCK =
false;
2708 uint64_t nCMPCTBLOCKVersion = 0;
2709 vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
2713 if (!
State(pfrom.
GetId())->fProvidesHeaderAndIDs) {
2714 State(pfrom.
GetId())->fProvidesHeaderAndIDs =
true;
2715 State(pfrom.
GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2;
2717 if (
State(pfrom.
GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) {
2718 State(pfrom.
GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
2723 if (!
State(pfrom.
GetId())->fSupportsDesiredCmpctVersion) {
2725 State(pfrom.
GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2);
2727 State(pfrom.
GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
2746 m_wtxid_relay_peers++;
2765 peer->m_wants_addrv2 =
true;
2783 std::vector<CAddress> vAddr;
2787 if (!RelayAddrsWithPeer(*peer)) {
2793 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
2798 std::vector<CAddress> vAddrOk;
2800 int64_t nSince = nNow - 10 * 60;
2803 const auto current_time = GetTime<std::chrono::microseconds>();
2806 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
2810 peer->m_addr_token_timestamp = current_time;
2813 uint64_t num_proc = 0;
2814 uint64_t num_rate_limit = 0;
2818 if (interruptMsgProc)
2823 if (peer->m_addr_token_bucket < 1.0) {
2827 peer->m_addr_token_bucket -= 1.0;
2835 if (addr.
nTime <= 100000000 || addr.
nTime > nNow + 10 * 60)
2836 addr.
nTime = nNow - 5 * 24 * 60 * 60;
2837 AddAddressKnown(*peer, addr);
2844 if (addr.
nTime > nSince && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
2846 RelayAddress(pfrom.
GetId(), addr, fReachable);
2850 vAddrOk.push_back(addr);
2852 peer->m_addr_processed += num_proc;
2853 peer->m_addr_rate_limited += num_rate_limit;
2854 LogPrint(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d%s\n",
2861 m_addrman.
Add(vAddrOk, pfrom.
addr, 2 * 60 * 60);
2862 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
2873 std::vector<CInv> vInv;
2877 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"inv message size = %u", vInv.size()));
2883 bool fBlocksOnly = m_ignore_incoming_txs || (pfrom.
m_tx_relay ==
nullptr);
2887 fBlocksOnly =
false;
2892 const auto current_time = GetTime<std::chrono::microseconds>();
2895 for (
CInv& inv : vInv) {
2896 if (interruptMsgProc)
return;
2908 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
2911 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
2918 best_block = &inv.
hash;
2922 const bool fAlreadyHave = AlreadyHaveTx(gtxid);
2931 AddTxAnnouncement(pfrom, gtxid, current_time);
2938 if (best_block !=
nullptr) {
2947 std::vector<CInv> vInv;
2951 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"getdata message size = %u", vInv.size()));
2957 if (vInv.size() > 0) {
2962 LOCK(peer->m_getdata_requests_mutex);
2963 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
2964 ProcessGetData(pfrom, *peer, interruptMsgProc);
2973 vRecv >> locator >> hashStop;
2989 std::shared_ptr<const CBlock> a_recent_block;
2992 a_recent_block = most_recent_block;
3003 const CBlockIndex* pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.
ActiveChain(), locator);
3009 LogPrint(
BCLog::NET,
"getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->
nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), nLimit, pfrom.
GetId());
3026 if (--nLimit <= 0) {
3030 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
3041 std::shared_ptr<const CBlock> recent_block;
3044 if (most_recent_block_hash == req.blockhash)
3045 recent_block = most_recent_block;
3049 SendBlockTransactions(pfrom, *recent_block, req);
3056 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(req.blockhash);
3067 SendBlockTransactions(pfrom, block, req);
3082 inv.hash = req.blockhash;
3083 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
3091 vRecv >> locator >> hashStop;
3101 LogPrint(
BCLog::NET,
"Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom.
GetId());
3105 CNodeState *nodestate =
State(pfrom.
GetId());
3110 pindex = m_chainman.m_blockman.LookupBlockIndex(hashStop);
3115 if (!BlockRequestAllowed(pindex)) {
3116 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
3123 pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.
ActiveChain(), locator);
3129 std::vector<CBlock> vHeaders;
3131 LogPrint(
BCLog::NET,
"getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), pfrom.
GetId());
3134 vHeaders.push_back(pindex->GetBlockHeader());
3135 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
3150 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
3170 const uint256& txid = ptx->GetHash();
3171 const uint256& wtxid = ptx->GetWitnessHash();
3175 CNodeState* nodestate =
State(pfrom.
GetId());
3177 const uint256& hash = nodestate->m_wtxid_relay ? wtxid : txid;
3179 if (nodestate->m_wtxid_relay && txid != wtxid) {
3188 m_txrequest.ReceivedResponse(pfrom.
GetId(), txid);
3189 if (tx.
HasWitness()) m_txrequest.ReceivedResponse(pfrom.
GetId(), wtxid);
3203 if (AlreadyHaveTx(
GenTxid(
true, wtxid))) {
3225 m_txrequest.ForgetTxHash(tx.
GetHash());
3228 m_orphanage.AddChildrenToWorkSet(tx, peer->m_orphan_work_set);
3238 AddToCompactExtraTransactions(removedTx);
3242 ProcessOrphanTx(peer->m_orphan_work_set);
3246 bool fRejectedParents =
false;
3250 std::vector<uint256> unique_parents;
3251 unique_parents.reserve(tx.
vin.size());
3256 std::sort(unique_parents.begin(), unique_parents.end());
3257 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
3258 for (
const uint256& parent_txid : unique_parents) {
3259 if (recentRejects->contains(parent_txid)) {
3260 fRejectedParents =
true;
3264 if (!fRejectedParents) {
3265 const auto current_time = GetTime<std::chrono::microseconds>();
3267 for (
const uint256& parent_txid : unique_parents) {
3273 const GenTxid gtxid{
false, parent_txid};
3275 if (!AlreadyHaveTx(gtxid)) AddTxAnnouncement(pfrom, gtxid, current_time);
3278 if (m_orphanage.AddTx(ptx, pfrom.
GetId())) {
3279 AddToCompactExtraTransactions(ptx);
3283 m_txrequest.ForgetTxHash(tx.
GetHash());
3288 unsigned int nEvicted = m_orphanage.LimitOrphans(nMaxOrphanTx);
3300 recentRejects->insert(tx.
GetHash());
3302 m_txrequest.ForgetTxHash(tx.
GetHash());
3332 recentRejects->insert(tx.
GetHash());
3333 m_txrequest.ForgetTxHash(tx.
GetHash());
3336 AddToCompactExtraTransactions(ptx);
3358 if (state.IsInvalid()) {
3362 MaybePunishNodeForTx(pfrom.
GetId(), state);
3376 vRecv >> cmpctblock;
3378 bool received_new_header =
false;
3383 if (!m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
3390 if (!m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.GetHash())) {
3391 received_new_header =
true;
3399 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
3408 bool fProcessBLOCKTXN =
false;
3413 bool fRevertToHeaderProcessing =
false;
3417 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3418 bool fBlockReconstructed =
false;
3426 CNodeState *nodestate =
State(pfrom.
GetId());
3431 nodestate->m_last_block_announcement =
GetTime();
3434 std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator blockInFlightIt = mapBlocksInFlight.find(pindex->
GetBlockHash());
3435 bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end();
3442 if (fAlreadyInFlight) {
3445 std::vector<CInv> vInv(1);
3453 if (!fAlreadyInFlight && !CanDirectFetch()) {
3467 (fAlreadyInFlight && blockInFlightIt->second.first == pfrom.
GetId())) {
3468 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
3469 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
3470 if (!(*queuedBlockIt)->partialBlock)
3483 Misbehaving(pfrom.
GetId(), 100,
"invalid compact block");
3487 std::vector<CInv> vInv(1);
3494 for (
size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {
3501 txn.
blockhash = cmpctblock.header.GetHash();
3503 fProcessBLOCKTXN =
true;
3515 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
3520 std::vector<CTransactionRef> dummy;
3521 status = tempBlock.FillBlock(*pblock, dummy);
3523 fBlockReconstructed =
true;
3527 if (fAlreadyInFlight) {
3530 std::vector<CInv> vInv(1);
3536 fRevertToHeaderProcessing =
true;
3541 if (fProcessBLOCKTXN) {
3542 return ProcessMessage(pfrom,
NetMsgType::BLOCKTXN, blockTxnMsg, time_received, interruptMsgProc);
3545 if (fRevertToHeaderProcessing) {
3551 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.header},
true);
3554 if (fBlockReconstructed) {
3559 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
3570 ProcessBlock(pfrom, pblock,
true);
3577 RemoveBlockRequest(pblock->GetHash());
3594 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3595 bool fBlockRead =
false;
3599 std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator it = mapBlocksInFlight.find(resp.blockhash);
3600 if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock ||
3601 it->second.first != pfrom.
GetId()) {
3609 RemoveBlockRequest(resp.blockhash);
3610 Misbehaving(pfrom.
GetId(), 100,
"invalid compact block/non-matching block transactions");
3614 std::vector<CInv> invs;
3635 RemoveBlockRequest(resp.blockhash);
3643 mapBlockSource.emplace(resp.blockhash, std::make_pair(pfrom.
GetId(),
false));
3653 ProcessBlock(pfrom, pblock,
true);
3666 std::vector<CBlockHeader> headers;
3671 Misbehaving(pfrom.
GetId(), 20,
strprintf(
"headers message size = %u", nCount));
3674 headers.resize(nCount);
3675 for (
unsigned int n = 0; n < nCount; n++) {
3676 vRecv >> headers[n];
3680 return ProcessHeadersMessage(pfrom, *peer, headers,
false);
3691 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3696 bool forceProcessing =
false;
3697 const uint256 hash(pblock->GetHash());
3702 forceProcessing = IsBlockRequested(hash);
3703 RemoveBlockRequest(hash);
3707 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
3709 ProcessBlock(pfrom, pblock, forceProcessing);
3726 if (peer->m_getaddr_recvd) {
3730 peer->m_getaddr_recvd =
true;
3732 peer->m_addrs_to_send.clear();
3733 std::vector<CAddress> vAddr;
3740 for (
const CAddress &addr : vAddr) {
3741 PushAddress(*peer, addr, insecure_rand);
3795 const auto ping_end = time_received;
3798 bool bPingFinished =
false;
3799 std::string sProblem;
3801 if (nAvail >=
sizeof(nonce)) {
3805 if (peer->m_ping_nonce_sent != 0) {
3806 if (nonce == peer->m_ping_nonce_sent) {
3808 bPingFinished =
true;
3809 const auto ping_time = ping_end - peer->m_ping_start.load();
3810 if (ping_time.count() >= 0) {
3815 sProblem =
"Timing mishap";
3819 sProblem =
"Nonce mismatch";
3822 bPingFinished =
true;
3823 sProblem =
"Nonce zero";
3827 sProblem =
"Unsolicited pong without ping";
3831 bPingFinished =
true;
3832 sProblem =
"Short payload";
3835 if (!(sProblem.empty())) {
3839 peer->m_ping_nonce_sent,
3843 if (bPingFinished) {
3844 peer->m_ping_nonce_sent = 0;
3851 LogPrint(
BCLog::NET,
"filterload received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
3858 if (!filter.IsWithinSizeConstraints())
3861 Misbehaving(pfrom.
GetId(), 100,
"too-large bloom filter");
3874 LogPrint(
BCLog::NET,
"filteradd received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
3878 std::vector<unsigned char> vData;
3895 Misbehaving(pfrom.
GetId(), 100,
"bad filteradd message");
3902 LogPrint(
BCLog::NET,
"filterclear received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
3917 vRecv >> newFeeFilter;
3920 pfrom.
m_tx_relay->minFeeFilter = newFeeFilter;
3928 ProcessGetCFilters(pfrom, vRecv);
3933 ProcessGetCFHeaders(pfrom, vRecv);
3938 ProcessGetCFCheckPt(pfrom, vRecv);
3943 std::vector<CInv> vInv;
3947 for (
CInv &inv : vInv) {
3948 if (inv.IsGenTxMsg()) {
3951 m_txrequest.ReceivedResponse(pfrom.
GetId(), inv.hash);
3963 bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
3966 LOCK(peer.m_misbehavior_mutex);
3969 if (!peer.m_should_discourage)
return false;
3971 peer.m_should_discourage =
false;
3976 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
3982 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
4002 bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
4004 bool fMoreWork =
false;
4006 PeerRef peer = GetPeerRef(pfrom->
GetId());
4007 if (peer ==
nullptr)
return false;
4010 LOCK(peer->m_getdata_requests_mutex);
4011 if (!peer->m_getdata_requests.empty()) {
4012 ProcessGetData(*pfrom, *peer, interruptMsgProc);
4018 if (!peer->m_orphan_work_set.empty()) {
4019 ProcessOrphanTx(peer->m_orphan_work_set);
4029 LOCK(peer->m_getdata_requests_mutex);
4030 if (!peer->m_getdata_requests.empty())
return true;
4035 if (!peer->m_orphan_work_set.empty())
return true;
4041 std::list<CNetMessage> msgs;
4044 if (pfrom->vProcessMsg.empty())
return false;
4046 msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin());
4049 fMoreWork = !pfrom->vProcessMsg.empty();
4058 const std::string& msg_type = msg.m_command;
4061 unsigned int nMessageSize = msg.m_message_size;
4064 ProcessMessage(*pfrom, msg_type, msg.m_recv, msg.m_time, interruptMsgProc);
4065 if (interruptMsgProc)
return false;
4067 LOCK(peer->m_getdata_requests_mutex);
4068 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
4070 }
catch (
const std::exception& e) {
4079 void PeerManagerImpl::ConsiderEviction(
CNode& pto, int64_t time_in_seconds)
4093 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
4094 if (state.m_chain_sync.m_timeout != 0) {
4095 state.m_chain_sync.m_timeout = 0;
4096 state.m_chain_sync.m_work_header =
nullptr;
4097 state.m_chain_sync.m_sent_getheaders =
false;
4099 }
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)) {
4105 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
4106 state.m_chain_sync.m_sent_getheaders =
false;
4107 }
else if (state.m_chain_sync.m_timeout > 0 && time_in_seconds > state.m_chain_sync.m_timeout) {
4111 if (state.m_chain_sync.m_sent_getheaders) {
4113 LogPrintf(
"Disconnecting outbound peer %d for old chain, best known block = %s\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>");
4116 assert(state.m_chain_sync.m_work_header);
4117 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());
4119 state.m_chain_sync.m_sent_getheaders =
true;
4120 constexpr int64_t HEADERS_RESPONSE_TIME = 120;
4126 state.m_chain_sync.m_timeout = time_in_seconds + HEADERS_RESPONSE_TIME;
4132 void PeerManagerImpl::EvictExtraOutboundPeers(int64_t time_in_seconds)
4141 std::pair<NodeId, int64_t> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
4145 if (pnode->
GetId() > youngest_peer.first) {
4146 next_youngest_peer = youngest_peer;
4147 youngest_peer.first = pnode->
GetId();
4151 NodeId to_disconnect = youngest_peer.first;
4152 if (youngest_peer.second > next_youngest_peer.second) {
4155 to_disconnect = next_youngest_peer.first;
4164 CNodeState *node_state =
State(pnode->
GetId());
4165 if (node_state ==
nullptr ||
4171 LogPrint(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
4185 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
4194 if (state ==
nullptr)
return;
4196 if (state->m_chain_sync.m_protect)
return;
4197 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->
GetId() > worst_peer)) {
4198 worst_peer = pnode->
GetId();
4199 oldest_block_announcement = state->m_last_block_announcement;
4202 if (worst_peer != -1) {
4213 LogPrint(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
4233 void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
4237 int64_t time_in_seconds =
GetTime();
4239 EvictExtraOutboundPeers(time_in_seconds);
4241 if (time_in_seconds > m_stale_tip_check_time) {
4245 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);
4253 if (!m_initial_sync_finished && CanDirectFetch()) {
4255 m_initial_sync_finished =
true;
4259 void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
4269 bool pingSend =
false;
4271 if (peer.m_ping_queued) {
4276 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
4283 while (nonce == 0) {
4286 peer.m_ping_queued =
false;
4287 peer.m_ping_start = now;
4289 peer.m_ping_nonce_sent = nonce;
4293 peer.m_ping_nonce_sent = 0;
4299 void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
4302 if (!RelayAddrsWithPeer(peer))
return;
4304 LOCK(peer.m_addr_send_times_mutex);
4307 peer.m_next_local_addr_send < current_time) {
4314 if (peer.m_next_local_addr_send != 0us) {
4315 peer.m_addr_known->reset();
4319 PushAddress(peer, *local_addr, insecure_rand);
4325 if (current_time <= peer.m_next_addr_send)
return;
4337 auto addr_already_known = [&peer](
const CAddress& addr) {
4338 bool ret = peer.m_addr_known->contains(addr.
GetKey());
4339 if (!ret) peer.m_addr_known->insert(addr.
GetKey());
4342 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
4343 peer.m_addrs_to_send.end());
4346 if (peer.m_addrs_to_send.empty())
return;
4348 const char* msg_type;
4350 if (peer.m_wants_addrv2) {
4358 peer.m_addrs_to_send.clear();
4361 if (peer.m_addrs_to_send.capacity() > 40) {
4362 peer.m_addrs_to_send.shrink_to_fit();
4366 void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, std::chrono::microseconds current_time)
4370 if (m_ignore_incoming_txs)
return;
4385 if (pto.
m_tx_relay->lastSentFeeFilter == MAX_FILTER) {
4391 if (current_time > pto.
m_tx_relay->m_next_send_feefilter) {
4392 CAmount filterToSend = g_filter_rounder.round(currentFilter);
4395 if (filterToSend != pto.
m_tx_relay->lastSentFeeFilter) {
4397 pto.
m_tx_relay->lastSentFeeFilter = filterToSend;
4403 else if (current_time + MAX_FEEFILTER_CHANGE_DELAY < pto.m_tx_relay->m_next_send_feefilter &&
4404 (currentFilter < 3 * pto.m_tx_relay->lastSentFeeFilter / 4 || currentFilter > 4 * pto.
m_tx_relay->lastSentFeeFilter / 3)) {
4410 class CompareInvMempoolOrder
4415 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
4418 m_wtxid_relay = use_wtxid;
4421 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
4430 bool PeerManagerImpl::SendMessages(
CNode* pto)
4432 PeerRef peer = GetPeerRef(pto->
GetId());
4433 if (!peer)
return false;
4438 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
4447 const auto current_time = GetTime<std::chrono::microseconds>();
4455 MaybeSendPing(*pto, *peer, current_time);
4460 MaybeSendAddr(*pto, *peer, current_time);
4470 bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->
fClient && !pto->
IsAddrFetchConn());
4474 state.fSyncStarted =
true;
4491 if (pindexStart->
pprev)
4492 pindexStart = pindexStart->
pprev;
4509 LOCK(peer->m_block_inv_mutex);
4510 std::vector<CBlock> vHeaders;
4511 bool fRevertToInv = ((!state.fPreferHeaders &&
4512 (!state.fPreferHeaderAndIDs || peer->m_blocks_for_headers_relay.size() > 1)) ||
4515 ProcessBlockAvailability(pto->
GetId());
4517 if (!fRevertToInv) {
4518 bool fFoundStartingHeader =
false;
4522 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
4523 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
4527 fRevertToInv =
true;
4530 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
4542 fRevertToInv =
true;
4545 pBestIndex = pindex;
4546 if (fFoundStartingHeader) {
4549 }
else if (PeerHasHeader(&state, pindex)) {
4551 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
4554 fFoundStartingHeader =
true;
4559 fRevertToInv =
true;
4564 if (!fRevertToInv && !vHeaders.empty()) {
4565 if (vHeaders.size() == 1 && state.fPreferHeaderAndIDs) {
4569 vHeaders.front().GetHash().ToString(), pto->
GetId());
4573 bool fGotBlockFromCache =
false;
4576 if (most_recent_block_hash == pBestIndex->
GetBlockHash()) {
4577 if (state.fWantsCmpctWitness || !fWitnessesPresentInMostRecentCompactBlock)
4583 fGotBlockFromCache =
true;
4586 if (!fGotBlockFromCache) {
4593 state.pindexBestHeaderSent = pBestIndex;
4594 }
else if (state.fPreferHeaders) {
4595 if (vHeaders.size() > 1) {
4598 vHeaders.front().GetHash().ToString(),
4599 vHeaders.back().GetHash().ToString(), pto->
GetId());
4602 vHeaders.front().GetHash().ToString(), pto->
GetId());
4605 state.pindexBestHeaderSent = pBestIndex;
4607 fRevertToInv =
true;
4613 if (!peer->m_blocks_for_headers_relay.empty()) {
4614 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
4615 const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hashToAnnounce);
4627 if (!PeerHasHeader(&state, pindex)) {
4628 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
4634 peer->m_blocks_for_headers_relay.clear();
4640 std::vector<CInv> vInv;
4642 LOCK(peer->m_block_inv_mutex);
4646 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
4653 peer->m_blocks_for_inv_relay.clear();
4660 if (pto->
m_tx_relay->nNextInvSend < current_time) {
4661 fSendTrickle =
true;
4676 if (fSendTrickle && pto->
m_tx_relay->fSendMempool) {
4677 auto vtxinfo = m_mempool.
infoAll();
4683 for (
const auto& txinfo : vtxinfo) {
4684 const uint256& hash = state.m_wtxid_relay ? txinfo.tx->GetWitnessHash() : txinfo.tx->GetHash();
4686 pto->
m_tx_relay->setInventoryTxToSend.erase(hash);
4688 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
4692 if (!pto->
m_tx_relay->pfilter->IsRelevantAndUpdate(*txinfo.tx))
continue;
4694 pto->
m_tx_relay->filterInventoryKnown.insert(hash);
4696 vInv.push_back(inv);
4702 pto->
m_tx_relay->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time);
4708 std::vector<std::set<uint256>::iterator> vInvTx;
4709 vInvTx.reserve(pto->
m_tx_relay->setInventoryTxToSend.size());
4710 for (std::set<uint256>::iterator it = pto->
m_tx_relay->setInventoryTxToSend.begin(); it != pto->
m_tx_relay->setInventoryTxToSend.end(); it++) {
4711 vInvTx.push_back(it);
4716 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, state.m_wtxid_relay);
4717 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
4720 unsigned int nRelayedTransactions = 0;
4724 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
4725 std::set<uint256>::iterator it = vInvTx.back();
4730 pto->
m_tx_relay->setInventoryTxToSend.erase(it);
4732 if (pto->
m_tx_relay->filterInventoryKnown.contains(hash)) {
4740 auto txid = txinfo.tx->GetHash();
4741 auto wtxid = txinfo.tx->GetWitnessHash();
4743 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
4746 if (pto->
m_tx_relay->pfilter && !pto->
m_tx_relay->pfilter->IsRelevantAndUpdate(*txinfo.tx))
continue;
4748 State(pto->
GetId())->m_recently_announced_invs.insert(hash);
4749 vInv.push_back(inv);
4750 nRelayedTransactions++;
4753 while (!g_relay_expiration.empty() && g_relay_expiration.front().first < current_time)
4755 mapRelay.erase(g_relay_expiration.front().second);
4756 g_relay_expiration.pop_front();
4759 auto ret = mapRelay.emplace(txid, std::move(txinfo.tx));
4764 auto ret2 = mapRelay.emplace(wtxid, ret.first->second);
4773 pto->
m_tx_relay->filterInventoryKnown.insert(hash);
4780 pto->
m_tx_relay->filterInventoryKnown.insert(txid);
4793 LogPrintf(
"Peer=%d is stalling block download, disconnecting\n", pto->
GetId());
4802 if (state.vBlocksInFlight.size() > 0) {
4803 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
4804 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
4806 LogPrintf(
"Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.pindex->GetBlockHash().ToString(), pto->
GetId());
4812 if (state.fSyncStarted && state.m_headers_sync_timeout < std::chrono::microseconds::max()) {
4815 if (current_time > state.m_headers_sync_timeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1)) {
4822 LogPrintf(
"Timeout downloading headers from peer=%d, disconnecting\n", pto->
GetId());
4826 LogPrintf(
"Timeout downloading headers from noban peer=%d, not disconnecting\n", pto->
GetId());
4832 state.fSyncStarted =
false;
4834 state.m_headers_sync_timeout = 0us;
4840 state.m_headers_sync_timeout = std::chrono::microseconds::max();
4846 ConsiderEviction(*pto,
GetTime());
4851 std::vector<CInv> vGetData;
4853 std::vector<const CBlockIndex*> vToDownload;
4859 BlockRequested(pto->
GetId(), *pindex);
4863 if (state.nBlocksInFlight == 0 && staller != -1) {
4864 if (
State(staller)->m_stalling_since == 0us) {
4865 State(staller)->m_stalling_since = current_time;
4874 std::vector<std::pair<NodeId, GenTxid>> expired;
4875 auto requestable = m_txrequest.GetRequestable(pto->
GetId(), current_time, &expired);
4876 for (
const auto& entry : expired) {
4877 LogPrint(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ?
"wtx" :
"tx",
4878 entry.second.GetHash().ToString(), entry.first);
4880 for (
const GenTxid& gtxid : requestable) {
4881 if (!AlreadyHaveTx(gtxid)) {
4893 m_txrequest.ForgetTxHash(gtxid.
GetHash());
4898 if (!vGetData.empty())
4901 MaybeSendFeefilter(*pto, current_time);
std::shared_ptr< const CTransaction > CTransactionRef
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
RecursiveMutex g_cs_orphans
Guards orphan transactions and extra txs for compact blocks.
static constexpr int64_t MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict...
static constexpr std::chrono::microseconds GETDATA_TX_INTERVAL
How long to wait (in microseconds) before downloading a transaction from an additional peer...
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
enum ReadStatus_t ReadStatus
const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected...
virtual void Misbehaving(const NodeId pnode, const int howmuch, const std::string &message)=0
Increment peer's misbehavior score.
static constexpr auto TXID_RELAY_DELAY
How long to delay requesting transactions via txids, if we have wtxid-relaying peers.
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
std::atomic_bool fPauseSend
static const int SERIALIZE_TRANSACTION_NO_WITNESS
A flag that is ORed into the protocol version to designate that a transaction should be (un)serialize...
invalid by consensus rules
const char * BLOCKTXN
Contains a BlockTransactions.
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto UNCONDITIONAL_RELAY_DELAY
How long a transaction has to be in the mempool before it can unconditionally be relayed (even when n...
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
void Discourage(const CNetAddr &net_addr)
const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
ServiceFlags
nServices flags
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
#define LogPrint(category,...)
int64_t GetBlockTime() const
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
std::vector< TxMempoolInfo > infoAll() const
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
uint32_t nStatus
Verification status of this block.
void scheduleEvery(Function f, std::chrono::milliseconds delta)
Repeat f until the scheduler is stopped.
void SetIP(const CNetAddr &ip)
uint64_t m_addr_rate_limited
void WakeMessageHandler()
static std::shared_ptr< const CBlock > most_recent_block GUARDED_BY(cs_most_recent_block)
std::string ToString() const
bool exists(const GenTxid >xid) const
We don't have the previous block the checked one is built on.
Data structure to keep track of, and schedule, transaction downloads from peers.
void PushTxInventory(const uint256 &hash)
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE
Default for -maxmempool, maximum megabytes of mempool memory usage.
static const CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
std::vector< uint16_t > indexes
bool IsOutboundOrBlockRelayConn() const
bool IsMsgFilteredBlk() const
size_t DynamicMemoryUsage() const
const std::optional< std::list< CTransactionRef > > m_replaced_transactions
Mempool transactions replaced by the tx per BIP 125 rules.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Verify that INVENTORY_MAX_RECENT_RELAY is enough to cache everything typically relayed before uncondi...
reverse_range< T > reverse_iterate(T &x)
invalid proof of work or time too old
const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
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.
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ::ChainActive().Tip() will not be pruned.
constexpr auto GetRandMillis
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
transaction was missing some of its inputs
bool IsMsgCmpctBlk() const
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
bool IsFeelerConn() const
TxMempoolInfo info(const uint256 &hash) const
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
bool MoneyRange(const CAmount &nValue)
CBlockHeader GetBlockHeader() const
std::vector< unsigned char > ParseHex(const char *psz)
int Height() const
Return the maximal height in the chain.
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
const uint256 & GetHash() const
unsigned long size() const
const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid...
void SetCommonVersion(int greatest_common_version)
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
void PushMessage(CNode *pnode, CSerializedNetMsg &&msg)
RecursiveMutex cs_vProcessMsg
arith_uint256 nMinimumChainWork
Minimum work we will assume exists on some valid chain.
bool CompareDepthAndScore(const uint256 &hasha, const uint256 &hashb, bool wtxid=false)
void SetServiceFlagsIBDCache(bool state)
Set the current IBD status in order to figure out the desirable service flags.
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set. ...
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
const TxValidationState m_state
CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version ...
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message...
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
violated mempool's fee/size/descendant/RBF/etc limits
static constexpr auto NONPREF_PEER_TX_DELAY
How long to delay requesting transactions from non-preferred peers.
Double ended buffer combining vector and stream-like interfaces.
inputs (covered by txid) failed policy rules
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void SetTryNewOutboundPeer(bool flag)
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
const ResultType m_result_type
uint64_t GetLocalNonce() const
bool SeenLocal(const CService &addr)
vote for a local address
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
transaction spends a coinbase too early, or violates locktime/sequence locks
static constexpr auto RELAY_TX_CACHE_TIME
How long to cache transactions in mapRelay for normal relay.
const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
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.
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.
static const int TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
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.
State
The various states a (txhash,peer) pair can be in.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
initial value. Tx has not yet been rejected
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
bool GetTryNewOutboundPeer() const
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
std::atomic< ServiceFlags > nServices
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain...
const std::vector< CTxIn > vin
void SetAddrLocal(const CService &addrLocalIn)
May not be called more than once.
const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
virtual void BlockConnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
bool DisconnectNode(const std::string &node)
Stochastical (IP) address manager.
int GetExtraBlockRelayCount() const
int64_t CAmount
Amount in satoshis (Can be negative)
static constexpr int ADDRV2_FORMAT
A flag that is ORed into the protocol version to designate that addresses should be serialized in (un...
uint256 GetBlockHash() const
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const
Check whether this block index entry is valid up to the passed validity level.
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
std::chrono::microseconds PoissonNextSendInbound(std::chrono::microseconds now, std::chrono::seconds average_interval)
Attempts to obfuscate tx time through exponentially distributed emitting.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
initial value. Block has not yet been rejected
static constexpr int64_t EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect, in seconds.
ServiceFlags GetLocalServices() const
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends...
std::set< CTxMemPoolEntryRef, CompareIteratorByHash > Parents
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(MakeSpan(std::forward< V >(v))))
Like MakeSpan, but for (const) unsigned char member types only.
uint64_t m_addr_processed
Invalid by a change to consensus rules more recent than SegWit.
bool fPruneMode
True if we're running in -prune mode.
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.
Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
bool Add(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty=0) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Add a single address.
CFeeRate minRelayTxFee
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) ...
CBlockIndex * pindexBestHeader
Best header we've seen so far (used for getheaders queries' starting points).
std::optional< CAddress > GetLocalAddrForPeer(CNode *pnode)
Returns a local address that we should advertise to this peer.
static RecursiveMutex cs_most_recent_block
this block was cached as being invalid and we didn't store the reason why
An input of a transaction.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
void Connected(const CService &addr, int64_t nTime=GetAdjustedTime()) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Outer function for Connected_()
static bool HasAllDesirableServiceFlags(ServiceFlags services)
A shortcut for (services & GetDesirableServiceFlags(services)) == GetDesirableServiceFlags(services)...
const uint256 & GetWitnessHash() const
void SetServices(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(!cs)
void StartExtraBlockRelayPeers()
static constexpr std::chrono::minutes PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message...
const uint256 & GetHash() const
std::string ToString() const
the block failed to meet one of our checkpoints
bool IsPeerAddrLocalGood(CNode *pnode)
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
A combination of a network address (CNetAddr) and a (TCP) port.
Transport protocol agnostic message container.
static constexpr unsigned int INVENTORY_MAX_RECENT_RELAY
The number of most recently announced transactions a peer can request.
int64_t nPowTargetSpacing
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
constexpr int64_t count_microseconds(std::chrono::microseconds t)
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
bool IsProxy(const CNetAddr &addr)
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
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.
static constexpr int64_t CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork, in seconds.
bool IsManualConn() const
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
int GetExtraFullOutboundCount() const
A CService with information about it as peer.
virtual bool IgnoresIncomingTxs()=0
Whether this node ignores txs received over p2p.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
std::vector< unsigned char > GetKey() const
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
bool ExpectServicesFromConn() const
const CMessageHeader::MessageStartChars & MessageStart() const
bool GetNetworkActive() const
static const int DISCOURAGEMENT_THRESHOLD
Threshold for marking a node to be discouraged, e.g.
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter...
std::string ToString() const
std::atomic< bool > m_bip152_highbandwidth_to
std::vector< uint256 > vHave
const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
Parameters that influence chain consensus.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
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.
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
const char * BLOCK
The block message transmits a single serialized block.
std::atomic_bool fDisconnect
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks...
CFeeRate GetMinFee(size_t sizelimit) const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
bool IsMsgWitnessBlk() const
Validation result for a single transaction mempool acceptance.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define Assume(val)
Assume is the identity function.
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB...
unsigned int GetReceiveFloodSize() const
static const int MAX_UNCONNECTING_HEADERS
Maximum number of unconnecting headers announcements before DoS score.
constexpr int64_t count_seconds(std::chrono::seconds t)
Helper to count the seconds of a duration.
std::chrono::microseconds m_ping_wait
bool CheckIncomingNonce(uint64_t nonce)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
bool IsBlockOnlyConn() const
const int64_t nTimeConnected
Unix epoch time at peer connection, in seconds.
Transaction is missing a witness.
bool ProcessNewBlockHeaders(const std::vector< CBlockHeader > &block, BlockValidationState &state, const CChainParams &chainparams, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
std::optional< txiter > GetIter(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given hash, if found.
invalid by consensus rules (excluding any below reasons)
bool IsReachable(enum Network net)
std::atomic_bool fReindex
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::vector< CTransactionRef > vtx
bool ShouldRunInactivityChecks(const CNode &node, std::optional< int64_t > now=std::nullopt) const
Return true if we should disconnect the peer for failing an inactivity check.
const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids"...
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
static constexpr auto BLOCK_STALLING_TIMEOUT
Time during which a peer must stall block download progress before being disconnected.
the block's data didn't match the data committed to by the PoW
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void AddKnownTx(const uint256 &hash)
std::atomic< int64_t > nLastTXTime
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e...
#define LOCKS_EXCLUDED(...)
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
virtual void SendPings()=0
Send ping message to all peers.
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
std::set< uint256 > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
std::vector< std::pair< unsigned int, uint256 > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
The block chain is a tree shaped structure starting with the genesis block at the root...
void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch? Larger windows tolerate larger download speed differences between peer, but increase the potential degree of disordering of blocks on disk (which make reindexing and pruning harder).
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static const int PROTOCOL_VERSION
network protocol versioning
virtual void RelayTransaction(const uint256 &txid, const uint256 &wtxid)=0
Relay transaction to all peers.
bool IsTxAvailable(size_t index) const
static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN
Default number of orphan+recently-replaced txn to keep around for block reconstruction.
A block this one builds on is invalid.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
int64_t GetAdjustedTime()
ServiceFlags GetDesirableServiceFlags(ServiceFlags services)
Gets the set of service flags which are "desirable" for a given peer.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out)
Get a single filter header by block.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network) ...
#define LIMITED_STRING(obj, n)
static uint32_t GetFetchFlags(const CNode &pfrom) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::atomic< int64_t > nTimeOffset
const char * GETDATA
The getdata message requests one or more data objects from another node.
Fee rate in satoshis per kilobyte: CAmount / kB.
static constexpr auto OVERLOADED_PEER_TX_DELAY
How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT).
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
CBlockLocator GetLocator(const CBlockIndex *pindex=nullptr) const
Return a CBlockLocator that refers to a block in this chain (by default the tip). ...
#define AssertLockNotHeld(cs)
bool OutboundTargetReached(bool historicalBlockServingLimit) const
check if the outbound target is reached if param historicalBlockServingLimit is set true...
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
std::atomic< int > nVersion
Invalid by a change to consensus rules more recent than SegWit.
std::string ConnectionTypeAsString() const
bool ReadRawBlockFromDisk(std::vector< uint8_t > &block, const FlatFilePos &pos, const CMessageHeader::MessageStartChars &message_start)
virtual void SetBestHeight(int height)=0
Set the best height.
static size_t RecursiveDynamicUsage(const CScript &script)
const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< uint256, CTransactionRef >> &extra_txn)
std::string ToString() const
CTransactionRef get(const uint256 &hash) const
block timestamp was > 2 hours in the future (or our clock is bad)
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
std::atomic< bool > m_bip152_highbandwidth_from
double CountSecondsDouble(SecondsDouble t)
Helper to count the seconds in any std::chrono::duration type.
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
bool IsAddrFetchConn() const
CChainState & ActiveChainstate() const
The most-work chain.
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
const char * TX
The tx message transmits a single transaction.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
The basic transaction that is broadcasted on the network and contained in blocks. ...
int nHeight
height of the entry in the chain. The genesis block has height 0
Information about a peer.
static std::unique_ptr< PeerManager > make(const CChainParams &chainparams, CConnman &connman, CAddrMan &addrman, BanMan *banman, CScheduler &scheduler, ChainstateManager &chainman, CTxMemPool &pool, bool ignore_incoming_txs)
const Consensus::Params & GetConsensus() const
std::vector< int > vHeightInFlight
void ForEachNode(const NodeFn &func)
Simple class for background tasks that should be run periodically or once "after a while"...
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT
Maximum number of in-flight transaction requests from a peer.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
full block available in blk*.dat
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep)
Determine if a deployment is active for this block.
virtual void InitializeNode(CNode *pnode)=0
Initialize a peer (setup state, queue any initial messages)
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
void Good(const CService &addr, bool test_before_evict=true, int64_t nTime=GetAdjustedTime()) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Mark an entry as accessible.
int64_t GetTime()
Return system time (or mocked time, if set)
std::atomic_bool fImporting
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS
Default for -maxorphantx, maximum number of orphan transactions kept in memory.
int GetCommonVersion() const
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
std::atomic_bool fPauseRecv
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
static const int WTXID_RELAY_VERSION
"wtxidrelay" command for wtxid-based relay starts with this version
bool HasPermission(NetPermissionFlags permission) const
bool IsInboundConn() const
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
std::atomic< int64_t > nLastBlockTime
UNIX epoch time of the last block received from this peer that we had not yet seen (e...
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
uint32_t nTime
Always included in serialization, except in the network format on INIT_PROTO_VERSION.
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos, const Consensus::Params &consensusParams)
Functions for disk access for blocks.
static constexpr int64_t STALE_CHECK_INTERVAL
How frequently to check for stale tips, in seconds.
otherwise didn't meet our local policy rules
A generic txid reference (txid or wtxid).
bool HaveTxsDownloaded() const
Check whether this block's and all previous blocks' transactions have been downloaded (and stored to ...
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
bool GetUseAddrmanOutgoing() const
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
unsigned int nTx
Number of transactions in this block.
void scheduleFromNow(Function f, std::chrono::milliseconds delta)
Call f once after the delta has passed.
CChain & ActiveChain() const
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt)=0
Process protocol messages received from a given node.
const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
bool IsFullOutboundConn() const
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
std::unique_ptr< TxRelay > m_tx_relay
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(pnode -> cs_sendProcessing)=0
Send queued protocol messages to a given node.
Span< A > constexpr MakeSpan(A(&a)[N])
MakeSpan for arrays: