109 "Max protocol message length must be greater than largest "
110 "possible INV message");
164 std::chrono::seconds(2),
165 std::chrono::seconds(2),
166 std::chrono::seconds(60),
173 std::chrono::seconds(2),
174 std::chrono::seconds(2),
175 std::chrono::seconds(60),
267 std::chrono::seconds{1},
268 "INVENTORY_RELAY_MAX too low");
319 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
357 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
360 Mutex m_misbehavior_mutex;
368 Mutex m_block_inv_mutex;
380 std::vector<BlockHash>
392 std::atomic<int> m_starting_height{-1};
395 std::atomic<uint64_t> m_ping_nonce_sent{0};
397 std::atomic<std::chrono::microseconds> m_ping_start{0
us};
399 std::atomic<bool> m_ping_queued{
false};
422 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
427 std::unique_ptr<CBloomFilter>
443 GUARDED_BY(m_tx_inventory_mutex){50000, 0.000001};
457 std::atomic<std::chrono::seconds> m_last_mempool_req{0s};
462 std::chrono::microseconds
463 m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
469 std::atomic<Amount> m_fee_filter_received{
Amount::zero()};
477 LOCK(m_tx_relay_mutex);
479 m_tx_relay = std::make_unique<Peer::TxRelay>();
493 std::set<avalanche::ProofId>
497 GUARDED_BY(m_proof_inventory_mutex){10000, 0.000001};
504 std::chrono::microseconds m_next_inv_send_time{0};
508 std::atomic<std::chrono::seconds> lastSharedProofsUpdate{0s};
509 std::atomic<bool> compactproofs_requested{
false};
516 const std::unique_ptr<ProofRelay> m_proof_relay;
521 std::vector<CAddress>
533 std::unique_ptr<CRollingBloomFilter>
551 std::atomic_bool m_addr_relay_enabled{
false};
555 mutable Mutex m_addr_send_times_mutex;
557 std::chrono::microseconds
560 std::chrono::microseconds
566 std::atomic_bool m_wants_addrv2{
false};
570 mutable Mutex m_addr_token_bucket_mutex;
577 std::chrono::microseconds
581 std::atomic<uint64_t> m_addr_rate_limited{0};
586 std::atomic<uint64_t> m_addr_processed{0};
596 Mutex m_getdata_requests_mutex;
605 Mutex m_headers_sync_mutex;
610 std::unique_ptr<HeadersSyncState>
615 std::atomic<bool> m_sent_sendheaders{
false};
638 mutable Mutex m_tx_relay_mutex;
644using PeerRef = std::shared_ptr<Peer>;
662 bool fSyncStarted{
false};
665 std::chrono::microseconds m_stalling_since{0
us};
666 std::list<QueuedBlock> vBlocksInFlight;
669 std::chrono::microseconds m_downloading_since{0
us};
671 bool fPreferredDownload{
false};
676 bool m_requested_hb_cmpctblocks{
false};
678 bool m_provides_cmpctblocks{
false};
706 struct ChainSyncTimeoutState {
709 std::chrono::seconds m_timeout{0s};
713 bool m_sent_getheaders{
false};
716 bool m_protect{
false};
719 ChainSyncTimeoutState m_chain_sync;
722 int64_t m_last_block_announcement{0};
725 const bool m_is_inbound;
751 const std::shared_ptr<const CBlock> &
pblock)
override
760 !m_headers_presync_mutex);
764 !m_recent_confirmed_transactions_mutex,
765 !m_most_recent_block_mutex, !cs_proofrequest,
766 !m_headers_presync_mutex, g_msgproc_mutex);
769 !m_recent_confirmed_transactions_mutex,
770 !m_most_recent_block_mutex, !cs_proofrequest,
776 std::optional<std::string>
787 void SetBestHeight(
int height)
override { m_best_height = height; };
794 const std::chrono::microseconds time_received,
797 !m_recent_confirmed_transactions_mutex,
798 !m_most_recent_block_mutex, !cs_proofrequest,
799 !m_headers_presync_mutex, g_msgproc_mutex);
870 const std::string &message =
"")
880 const
std::
string &message = "")
913 struct PackageToValidate {
915 const std::vector<NodeId> m_senders;
923 Assume(m_txns.size() == 2);
925 "parent %s (sender=%d) + child %s (sender=%d)",
926 m_txns.front()->GetId().ToString(), m_senders.front(),
927 m_txns.back()->GetId().ToString(), m_senders.back());
987 std::vector<CBlockHeader> &&
headers,
1009 const std::vector<CBlockHeader> &
headers)
1034 std::vector<CBlockHeader> &
headers)
1036 !m_headers_presync_mutex, g_msgproc_mutex);
1052 std::vector<CBlockHeader> &
headers)
1054 !m_headers_presync_mutex, g_msgproc_mutex);
1115 std::chrono::microseconds now);
1164 Mutex cs_proofrequest;
1169 std::atomic<int> m_best_height{-1};
1172 std::chrono::seconds m_stale_tip_check_time{0s};
1174 const Options m_opts;
1182 bool m_initial_sync_finished{
false};
1188 mutable Mutex m_peer_mutex;
1209 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0
us};
1224 std::map<BlockHash, std::pair<NodeId, bool>>
1234 std::atomic<std::chrono::seconds> m_block_stalling_timeout{
1250 !m_recent_confirmed_transactions_mutex);
1314 mutable Mutex m_recent_confirmed_transactions_mutex;
1316 GUARDED_BY(m_recent_confirmed_transactions_mutex){24'000, 0.000'001};
1325 std::chrono::microseconds
1331 mutable Mutex m_most_recent_block_mutex;
1332 std::shared_ptr<const CBlock>
1334 std::shared_ptr<const CBlockHeaderAndShortTxIDs>
1341 Mutex m_headers_presync_mutex;
1352 using HeadersPresyncStats =
1353 std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
1355 std::map<NodeId, HeadersPresyncStats>
1360 std::atomic_bool m_headers_presync_should_signal{
false};
1395 std::list<QueuedBlock>::iterator **
pit =
nullptr)
1424 const std::chrono::seconds now)
1431 peer.m_getdata_requests_mutex,
1437 const std::shared_ptr<const CBlock> &block,
1441 typedef std::map<TxId, CTransactionRef> MapRelay;
1448 std::deque<std::pair<std::chrono::microseconds, MapRelay::iterator>>
1476 std::vector<std::pair<TxHash, CTransactionRef>>
1583 !m_recent_confirmed_transactions_mutex);
1614 bool isPreferredDownloadPeer(const
CNode &
pfrom);
1617const CNodeState *PeerManagerImpl::State(
NodeId pnode) const
1629 return const_cast<CNodeState *
>(std::as_const(*this).State(
pnode));
1641void PeerManagerImpl::AddAddressKnown(Peer &peer,
const CAddress &addr) {
1642 assert(peer.m_addr_known);
1643 peer.m_addr_known->insert(addr.
GetKey());
1646void PeerManagerImpl::PushAddress(Peer &peer,
const CAddress &addr) {
1650 assert(peer.m_addr_known);
1651 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) &&
1653 if (peer.m_addrs_to_send.size() >= m_opts.max_addr_to_send) {
1654 peer.m_addrs_to_send[
m_rng.randrange(peer.m_addrs_to_send.size())] =
1657 peer.m_addrs_to_send.push_back(addr);
1669 tx_relay->m_tx_inventory_known_filter.insert(txid);
1673 if (peer.m_proof_relay !=
nullptr) {
1674 LOCK(peer.m_proof_relay->m_proof_inventory_mutex);
1675 peer.m_proof_relay->m_proof_inventory_known_filter.insert(proofid);
1679bool PeerManagerImpl::isPreferredDownloadPeer(
const CNode &
pfrom) {
1681 const CNodeState *state = State(
pfrom.GetId());
1682 return state && state->fPreferredDownload;
1698std::chrono::microseconds
1699PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1701 if (m_next_inv_to_inbounds.load() < now) {
1708 return m_next_inv_to_inbounds;
1711bool PeerManagerImpl::IsBlockRequested(
const BlockHash &hash) {
1715bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const BlockHash &hash) {
1728void PeerManagerImpl::RemoveBlockRequest(
const BlockHash &hash,
1749 if (state.vBlocksInFlight.begin() ==
list_it) {
1752 state.m_downloading_since =
1753 std::max(state.m_downloading_since,
1756 state.vBlocksInFlight.erase(
list_it);
1758 if (state.vBlocksInFlight.empty()) {
1762 state.m_stalling_since = 0
us;
1768bool PeerManagerImpl::BlockRequested(
const Config &config,
NodeId nodeid,
1770 std::list<QueuedBlock>::iterator **
pit) {
1773 CNodeState *state = State(nodeid);
1774 assert(state !=
nullptr);
1781 if (
range.first->second.first == nodeid) {
1783 *
pit = &
range.first->second.second;
1792 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(
1793 state->vBlocksInFlight.end(),
1794 {&block, std::unique_ptr<PartiallyDownloadedBlock>(
1795 pit ? new PartiallyDownloadedBlock(config, &m_mempool)
1797 if (state->vBlocksInFlight.size() == 1) {
1804 std::make_pair(hash, std::make_pair(nodeid, it)));
1813void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid) {
1819 if (m_opts.ignore_incoming_txs) {
1828 if (!
nodestate->m_provides_cmpctblocks) {
1834 if (*it == nodeid) {
1839 CNodeState *state = State(*it);
1840 if (state !=
nullptr && !state->m_is_inbound) {
1867 m_connman.PushMessage(
1868 pnodeStop, CNetMsgMaker(pnodeStop->GetCommonVersion())
1869 .Make(NetMsgType::SENDCMPCT,
1871 CMPCTBLOCKS_VERSION));
1874 pnodeStop->m_bip152_highbandwidth_to = false;
1885 pfrom->m_bip152_highbandwidth_to =
true;
1891bool PeerManagerImpl::TipMayBeStale() {
1894 if (m_last_tip_update.load() == 0s) {
1897 return m_last_tip_update.load() <
1904bool PeerManagerImpl::CanDirectFetch() {
1912 if (state->pindexBestKnownBlock &&
1913 pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight)) {
1916 if (state->pindexBestHeaderSent &&
1917 pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight)) {
1923void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1924 CNodeState *state = State(nodeid);
1925 assert(state !=
nullptr);
1927 if (!state->hashLastUnknownBlock.IsNull()) {
1931 if (state->pindexBestKnownBlock ==
nullptr ||
1932 pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1933 state->pindexBestKnownBlock = pindex;
1935 state->hashLastUnknownBlock.SetNull();
1940void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
1942 CNodeState *state = State(nodeid);
1943 assert(state !=
nullptr);
1950 if (state->pindexBestKnownBlock ==
nullptr ||
1951 pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1952 state->pindexBestKnownBlock = pindex;
1957 state->hashLastUnknownBlock = hash;
1961void PeerManagerImpl::FindNextBlocksToDownload(
1969 CNodeState *state = State(nodeid);
1970 assert(state !=
nullptr);
1975 if (state->pindexBestKnownBlock ==
nullptr ||
1976 state->pindexBestKnownBlock->nChainWork <
1978 state->pindexBestKnownBlock->nChainWork <
1984 if (state->pindexLastCommonBlock ==
nullptr) {
1987 state->pindexLastCommonBlock =
1989 .
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight,
1996 state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1997 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock) {
2001 std::vector<const CBlockIndex *>
vToFetch;
2010 std::min<int>(state->pindexBestKnownBlock->nHeight,
nWindowEnd + 1);
2020 pindexWalk = state->pindexBestKnownBlock->GetAncestor(
2023 for (
unsigned int i =
nToFetch - 1; i > 0; i--) {
2037 if (pindex->nStatus.hasData() ||
2040 state->pindexLastCommonBlock = pindex;
2069template <
class InvId>
2073 return !
node.HasPermission(
2086template <
class InvId>
2087static std::chrono::microseconds
2092 auto delay = std::chrono::microseconds{0};
2137 "send version message: version %d, blocks=%d, them=%s, "
2138 "txrelay=%d, peer=%d\n",
2143 "send version message: version %d, blocks=%d, "
2144 "txrelay=%d, peer=%d\n",
2149void PeerManagerImpl::AddTxAnnouncement(
2166void PeerManagerImpl::AddProofAnnouncement(
2182void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node,
2185 CNodeState *state = State(
node);
2191void PeerManagerImpl::InitializeNode(
const Config &config,
CNode &
node,
2197 std::piecewise_construct,
2198 std::forward_as_tuple(nodeid),
2199 std::forward_as_tuple(
node.IsInboundConn()));
2213 if (!
node.IsInboundConn()) {
2218void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler &scheduler) {
2223 if (m_mempool.
exists(txid)) {
2224 RelayTransaction(txid);
2243 if (!pm.isBoundToPeer(*it)) {
2244 pm.removeUnbroadcastProof(*it);
2245 it = unbroadcasted_proofids.erase(it);
2257 RelayProof(proofid);
2269void PeerManagerImpl::UpdateAvalancheStatistics()
const {
2284 pm.updateAvailabilityScores(
2288 score =
pavanode->getAvailabilityScore();
2296void PeerManagerImpl::AvalanchePeriodicNetworking(
CScheduler &scheduler)
const {
2312 return pm.shouldRequestMoreNodes();
2317 if (
pnode->m_avalanche_enabled) {
2318 avanode_ids.push_back(pnode->GetId());
2322 if (peer ==
nullptr) {
2326 if (peer->m_proof_relay &&
2327 now > (peer->m_proof_relay->lastSharedProofsUpdate.load() +
2329 peer->m_proof_relay->sharedProofs = {};
2345 m_connman.PushMessage(
2346 pavanode, CNetMsgMaker(pavanode->GetCommonVersion())
2347 .Make(NetMsgType::GETAVAADDR));
2348 PeerRef peer = GetPeerRef(avanodeId);
2349 WITH_LOCK(peer->m_addr_token_bucket_mutex,
2350 peer->m_addr_token_bucket +=
2351 m_opts.max_addr_to_send);
2381 if (peer->m_proof_relay) {
2386 peer->m_proof_relay->compactproofs_requested =
true;
2401void PeerManagerImpl::FinalizeNode(
const Config &config,
const CNode &
node) {
2415 return peer->m_misbehavior_score);
2419 CNodeState *state = State(nodeid);
2420 assert(state !=
nullptr);
2422 if (state->fSyncStarted) {
2426 for (
const QueuedBlock &entry : state->vBlocksInFlight) {
2446 state->m_chain_sync.m_protect;
2459 return orphanage.Size();
2465 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
2472 LOCK(m_headers_presync_mutex);
2484 return it !=
m_peer_map.end() ? it->second :
nullptr;
2492 ret = std::move(it->second);
2498bool PeerManagerImpl::GetNodeStateStats(
NodeId nodeid,
2502 const CNodeState *state = State(nodeid);
2503 if (state ==
nullptr) {
2507 ? state->pindexBestKnownBlock->nHeight
2510 ? state->pindexLastCommonBlock->nHeight
2512 for (
const QueuedBlock &queue : state->vBlocksInFlight) {
2520 if (peer ==
nullptr) {
2533 if ((0 != peer->m_ping_nonce_sent) &&
2534 (0 != peer->m_ping_start.load().count())) {
2539 if (
auto tx_relay = peer->GetTxRelay()) {
2553 LOCK(peer->m_headers_sync_mutex);
2554 if (peer->m_headers_sync) {
2562void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef &tx) {
2563 if (m_opts.max_extra_txs <= 0) {
2572 std::make_pair(tx->GetHash(), tx);
2576void PeerManagerImpl::Misbehaving(Peer &peer,
int howmuch,
2577 const std::string &message) {
2580 LOCK(peer.m_misbehavior_mutex);
2582 peer.m_misbehavior_score +=
howmuch;
2583 const int score_now{peer.m_misbehavior_score};
2586 message.empty() ?
"" : (
": " + message);
2587 std::string warning;
2591 warning =
" DISCOURAGE THRESHOLD EXCEEDED";
2592 peer.m_should_discourage =
true;
2599bool PeerManagerImpl::MaybePunishNodeForBlock(
NodeId nodeid,
2602 const std::string &message) {
2657 if (message !=
"") {
2663bool PeerManagerImpl::MaybePunishNodeForTx(
NodeId nodeid,
2665 const std::string &message) {
2691 if (message !=
"") {
2697bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex *pindex) {
2703 (m_chainman.m_best_header !=
nullptr) &&
2704 (m_chainman.m_best_header->GetBlockTime() - pindex->
GetBlockTime() <
2707 *m_chainman.m_best_header, *pindex, *m_chainman.m_best_header,
2711std::optional<std::string>
2715 return "Loading blocks ...";
2721 CNodeState *state = State(
peer_id);
2722 if (state ==
nullptr) {
2723 return "Peer does not exist";
2731 return "Already requested from this peer";
2740 const CNetMsgMaker msgMaker(node->GetCommonVersion());
2741 this->m_connman.PushMessage(
2742 node, msgMaker.Make(NetMsgType::GETDATA, invs));
2745 return "Node not fully connected";
2750 return std::nullopt;
2753std::unique_ptr<PeerManager>
2757 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman,
2766 :
m_rng{opts.deterministic_rng},
2768 m_chainparams(chainman.GetParams()), m_connman(connman),
2769 m_addrman(addrman), m_banman(banman), m_chainman(chainman),
2770 m_mempool(pool), m_avalanche(
avalanche), m_opts{opts} {}
2772void PeerManagerImpl::StartScheduledTasks(
CScheduler &scheduler) {
2779 "peer eviction timer should be less than stale tip check timer");
2782 this->CheckForStaleTipAndEvictPeers();
2812void PeerManagerImpl::BlockConnected(
2823 LOCK(m_recent_confirmed_transactions_mutex);
2841 std::max(std::chrono::duration_cast<std::chrono::seconds>(
2852void PeerManagerImpl::BlockDisconnected(
2853 const std::shared_ptr<const CBlock> &block,
const CBlockIndex *pindex) {
2862 LOCK(m_recent_confirmed_transactions_mutex);
2870void PeerManagerImpl::NewPoWValidBlock(
2872 std::shared_ptr<const CBlockHeaderAndShortTxIDs>
pcmpctblock =
2873 std::make_shared<const CBlockHeaderAndShortTxIDs>(*
pblock);
2884 const std::shared_future<CSerializedNetMsg>
lazy_ser{
2885 std::async(std::launch::deferred, [&] {
2890 LOCK(m_most_recent_block_mutex);
2902 pnode->fDisconnect) {
2906 CNodeState &state = *State(
pnode->GetId());
2910 if (state.m_requested_hb_cmpctblocks &&
2914 "%s sending header-and-ids %s to peer=%d\n",
2915 "PeerManager::NewPoWValidBlock",
2916 hashBlock.ToString(),
pnode->GetId());
2920 state.pindexBestHeaderSent = pindex;
2941 std::vector<BlockHash>
vHashes;
2956 Peer &peer = *it.second;
2957 LOCK(peer.m_block_inv_mutex);
2959 peer.m_blocks_for_headers_relay.push_back(hash);
2971void PeerManagerImpl::BlockChecked(
const CBlock &block,
2976 std::map<BlockHash, std::pair<NodeId, bool>>::iterator it =
2982 State(it->second.first)) {
2984 !it->second.second);
3010bool PeerManagerImpl::AlreadyHaveTx(
const TxId &txid,
3025 return orphanage.HaveTx(txid);
3031 return conflicting.HaveTx(txid);
3042 LOCK(m_recent_confirmed_transactions_mutex);
3051bool PeerManagerImpl::AlreadyHaveBlock(
const BlockHash &block_hash) {
3056 if (!
Assume(m_avalanche)) {
3061 if (localProof && localProof->getId() == proofid) {
3066 return pm.exists(proofid) ||
pm.isInvalid(proofid);
3070void PeerManagerImpl::SendPings() {
3073 it.second->m_ping_queued =
true;
3077void PeerManagerImpl::RelayTransaction(
const TxId &txid) {
3080 Peer &peer = *it.second;
3091 if (
tx_relay->m_next_inv_send_time == 0s) {
3095 if (!
tx_relay->m_tx_inventory_known_filter.contains(txid)) {
3096 tx_relay->m_tx_inventory_to_send.insert(txid);
3104 Peer &peer = *it.second;
3106 if (!peer.m_proof_relay) {
3109 LOCK(peer.m_proof_relay->m_proof_inventory_mutex);
3110 if (!peer.m_proof_relay->m_proof_inventory_known_filter.contains(
3112 peer.m_proof_relay->m_proof_inventory_to_send.insert(proofid);
3148 std::array<std::pair<uint64_t, Peer *>, 2>
best{
3149 {{0,
nullptr}, {0,
nullptr}}};
3155 if (peer->m_addr_relay_enabled &&
id !=
originator &&
3161 best.begin() + i + 1);
3169 for (
unsigned int i = 0; i <
nRelayNodes &&
best[i].first != 0; i++) {
3174void PeerManagerImpl::ProcessGetBlockData(
const Config &config,
CNode &
pfrom,
3175 Peer &peer,
const CInv &
inv) {
3181 LOCK(m_most_recent_block_mutex);
3220 "%s: ignoring request from peer=%i for old "
3221 "block that isn't in the main chain\n",
3229 (((m_chainman.m_best_header !=
nullptr) &&
3230 (m_chainman.m_best_header->GetBlockTime() - pindex->
GetBlockTime() >
3232 inv.IsMsgFilteredBlk()) &&
3236 "historical block serving limit reached, disconnect peer=%d\n",
3238 pfrom.fDisconnect =
true;
3251 "Ignore block request below NODE_NETWORK_LIMITED "
3252 "threshold, disconnect peer=%d\n",
3257 pfrom.fDisconnect =
true;
3262 if (!pindex->nStatus.hasData()) {
3265 std::shared_ptr<const CBlock>
pblock;
3270 std::shared_ptr<CBlock>
pblockRead = std::make_shared<CBlock>();
3272 assert(!
"cannot load block from disk");
3276 if (
inv.IsMsgBlk()) {
3279 }
else if (
inv.IsMsgFilteredBlk()) {
3282 if (
auto tx_relay = peer.GetTxRelay()) {
3301 typedef std::pair<size_t, uint256>
PairType;
3310 }
else if (
inv.IsMsgCmpctBlk()) {
3338 LOCK(peer.m_block_inv_mutex);
3341 if (hash == peer.m_continuation_block) {
3345 std::vector<CInv>
vInv;
3349 peer.m_continuation_block =
BlockHash();
3355PeerManagerImpl::FindTxForGetData(
const Peer &peer,
const TxId &txid,
3357 const std::chrono::seconds now) {
3365 return std::move(
txinfo.tx);
3373 if (
Assume(peer.GetTxRelay())
3374 ->m_recently_announced_invs.contains(txid)) {
3377 return std::move(
txinfo.tx);
3393PeerManagerImpl::FindProofForGetData(
const Peer &peer,
3395 const std::chrono::seconds now) {
3429 if (peer.m_proof_relay->m_recently_announced_proofs.contains(proofid)) {
3436void PeerManagerImpl::ProcessGetData(
3443 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
3450 ?
tx_relay->m_last_mempool_req.load()
3451 : std::chrono::seconds::min();
3456 while (it != peer.m_getdata_requests.end()) {
3462 if (
pfrom.fPauseSend) {
3468 if (it->IsMsgProof()) {
3480 pm.removeUnbroadcastProof(proofid);
3490 if (it->IsMsgTx()) {
3510 auto txiter = m_mempool.
GetIter(tx->GetId());
3514 (*pentry)->GetMemPoolParentsConst();
3516 for (
const auto &parent :
parents) {
3517 if (parent.get()->GetTime() >
3520 parent.get()->GetTx().GetId());
3529 return !
tx_relay->m_tx_inventory_known_filter
3548 if (it != peer.m_getdata_requests.end() && !
pfrom.fPauseSend) {
3550 if (
inv.IsGenBlkMsg()) {
3557 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
3577void PeerManagerImpl::SendBlockTransactions(
3581 for (
size_t i = 0; i < req.
indices.size(); i++) {
3583 Misbehaving(peer, 100,
"getblocktxn with out-of-bounds tx indices");
3595bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader> &
headers,
3600 Misbehaving(peer, 100,
"header with invalid proof of work");
3606 Misbehaving(peer, 20,
"non-continuous headers sequence");
3638void PeerManagerImpl::HandleFewUnconnectingHeaders(
3642 peer.m_num_unconnecting_headers_msgs++;
3649 "received header %s: missing prev block %s, sending getheaders "
3650 "(%d) to end (peer=%d, m_num_unconnecting_headers_msgs=%d)\n",
3653 pfrom.GetId(), peer.m_num_unconnecting_headers_msgs);
3664 if (peer.m_num_unconnecting_headers_msgs %
3669 peer.m_num_unconnecting_headers_msgs));
3673bool PeerManagerImpl::CheckHeadersAreContinuous(
3674 const std::vector<CBlockHeader> &
headers)
const {
3685bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(
3687 if (peer.m_headers_sync) {
3688 auto result = peer.m_headers_sync->ProcessNextHeaders(
3690 if (result.request_more) {
3691 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
3706 "more getheaders (from %s) to peer=%d\n",
3710 "error sending next getheaders (from %s) to "
3711 "continue sync with peer=%d\n",
3718 peer.m_headers_sync.reset(
nullptr);
3723 LOCK(m_headers_presync_mutex);
3727 HeadersPresyncStats stats;
3728 stats.first = peer.m_headers_sync->GetPresyncWork();
3729 if (peer.m_headers_sync->GetState() ==
3731 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
3732 peer.m_headers_sync->GetPresyncTime()};
3736 LOCK(m_headers_presync_mutex);
3746 const HeadersPresyncStats *
stat_best{
nullptr};
3765 m_headers_presync_should_signal =
true;
3769 if (result.success) {
3772 headers.swap(result.pow_validated_headers);
3775 return result.success;
3783bool PeerManagerImpl::TryLowWorkHeadersSync(
3785 std::vector<CBlockHeader> &
headers) {
3810 LOCK(peer.m_headers_sync_mutex);
3811 peer.m_headers_sync.reset(
3821 "Ignoring low-work chain (height=%u) from peer=%d\n",
3834bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex *header) {
3835 return header !=
nullptr &&
3836 ((m_chainman.m_best_header !=
nullptr &&
3838 m_chainman.m_best_header->GetAncestor(header->
nHeight)) ||
3842bool PeerManagerImpl::MaybeSendGetHeaders(
CNode &
pfrom,
3867void PeerManagerImpl::HeadersDirectFetchBlocks(
const Config &config,
3877 std::vector<const CBlockIndex *>
vToFetch;
3902 if (
nodestate->vBlocksInFlight.size() >=
3914 "Downloading blocks toward %s (%d) via headers "
3920 if (!m_opts.ignore_incoming_txs &&
3940void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
3943 if (peer.m_num_unconnecting_headers_msgs > 0) {
3946 "peer=%d: resetting m_num_unconnecting_headers_msgs (%d -> 0)\n",
3947 pfrom.GetId(), peer.m_num_unconnecting_headers_msgs);
3949 peer.m_num_unconnecting_headers_msgs = 0;
3973 nodestate->pindexBestKnownBlock->nChainWork <
3983 if (
pfrom.IsOutboundOrBlockRelayConn()) {
3984 LogPrintf(
"Disconnecting outbound peer %d -- headers "
3985 "chain has insufficient work\n",
3987 pfrom.fDisconnect =
true;
3998 if (!
pfrom.fDisconnect &&
pfrom.IsFullOutboundConn() &&
3999 nodestate->pindexBestKnownBlock !=
nullptr) {
4002 nodestate->pindexBestKnownBlock->nChainWork >=
4007 nodestate->m_chain_sync.m_protect =
true;
4013void PeerManagerImpl::ProcessHeadersMessage(
const Config &config,
CNode &
pfrom,
4015 std::vector<CBlockHeader> &&
headers,
4025 LOCK(peer.m_headers_sync_mutex);
4026 if (peer.m_headers_sync) {
4027 peer.m_headers_sync.reset(
nullptr);
4028 LOCK(m_headers_presync_mutex);
4058 LOCK(peer.m_headers_sync_mutex);
4143 "invalid header received");
4156 "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
4169void PeerManagerImpl::ProcessInvalidTx(
NodeId nodeid,
4177 const TxId &txid =
ptx->GetId();
4212 return orphanage.EraseTx(txid);
4237 "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n",
4238 nodeid, tx->GetId().ToString(), m_mempool.
size(),
4241 RelayTransaction(tx->GetId());
4244void PeerManagerImpl::ProcessPackageResult(
4251 const auto &
package = package_to_validate.m_txns;
4304std::optional<PeerManagerImpl::PackageToValidate>
4328 return PeerManagerImpl::PackageToValidate{
ptx,
child, nodeid,
4344 return orphanage.GetChildrenFromDifferentPeer(
ptx, nodeid);
4364 return PeerManagerImpl::PackageToValidate{
ptx,
child_tx, nodeid,
4368 return std::nullopt;
4371bool PeerManagerImpl::ProcessOrphanTx(
const Config &config, Peer &peer) {
4377 return orphanage.GetTxToReconsider(peer.m_id);
4393 " invalid orphan tx %s from peer=%d. %s\n",
4411bool PeerManagerImpl::PrepareBlockFilterRequest(
4420 "peer %d requested unsupported block filter type: %d\n",
4422 node.fDisconnect =
true;
4435 node.fDisconnect =
true;
4444 "peer %d sent invalid getcfilters/getcfheaders with "
4446 "start height %d and stop height %d\n",
4448 node.fDisconnect =
true;
4453 "peer %d requested too many cfilters/cfheaders: %d / %d\n",
4455 node.fDisconnect =
true;
4460 if (!filter_index) {
4469void PeerManagerImpl::ProcessGetCFilters(
CNode &
node, Peer &peer,
4488 std::vector<BlockFilter>
filters;
4491 "Failed to find block filter in index: filter_type=%s, "
4492 "start_height=%d, stop_hash=%s\n",
4498 for (
const auto &filter :
filters) {
4505void PeerManagerImpl::ProcessGetCFHeaders(
CNode &
node, Peer &peer,
4530 "Failed to find block filter header in index: "
4531 "filter_type=%s, block_hash=%s\n",
4542 "Failed to find block filter hashes in index: filter_type=%s, "
4543 "start_height=%d, stop_hash=%s\n",
4556void PeerManagerImpl::ProcessGetCFCheckPt(
CNode &
node, Peer &peer,
4570 std::numeric_limits<uint32_t>::max(),
4579 for (
int i =
headers.size() - 1; i >= 0; i--) {
4585 "Failed to find block filter header in index: "
4586 "filter_type=%s, block_hash=%s\n",
4611PeerManagerImpl::GetAvalancheVoteForBlock(
const BlockHash &hash)
const {
4622 if (pindex->nStatus.isInvalid()) {
4627 if (pindex->nStatus.isOnParkedChain()) {
4645 if (!pindex->nStatus.hasData()) {
4654uint32_t PeerManagerImpl::GetAvalancheVoteForTx(
const TxId &
id)
const {
4656 if (m_mempool.
exists(
id) ||
4657 WITH_LOCK(m_recent_confirmed_transactions_mutex,
4664 return conflicting.HaveTx(id);
4676 return orphanage.HaveTx(id);
4695 if (
pm.isInvalid(
id)) {
4700 if (
pm.isBoundToPeer(
id)) {
4705 if (!
pm.exists(
id)) {
4710 if (
pm.isImmature(
id)) {
4715 if (
pm.isInConflictingPool(
id)) {
4727 const std::shared_ptr<const CBlock> &block,
4746void PeerManagerImpl::ProcessMessage(
4748 CDataStream &vRecv,
const std::chrono::microseconds time_received,
4756 if (peer ==
nullptr) {
4762 "Avalanche is not initialized, ignoring %s message\n",
4769 if (
pfrom.nVersion != 0) {
4770 Misbehaving(*peer, 1,
"redundant version message");
4779 std::string cleanSubVer;
4791 if (!
pfrom.IsInboundConn()) {
4794 if (
pfrom.ExpectServicesFromConn() &&
4797 "peer=%d does not offer the expected services "
4798 "(%08x offered, %08x expected); disconnecting\n",
4799 pfrom.GetId(), nServices,
4801 pfrom.fDisconnect =
true;
4805 if (
pfrom.IsAvalancheOutboundConnection() &&
4809 "peer=%d does not offer the avalanche service; disconnecting\n",
4811 pfrom.fDisconnect =
true;
4818 "peer=%d using obsolete version %i; disconnecting\n",
4819 pfrom.GetId(), nVersion);
4820 pfrom.fDisconnect =
true;
4824 if (!vRecv.
empty()) {
4833 if (!vRecv.
empty()) {
4834 std::string strSubVer;
4838 if (!vRecv.
empty()) {
4841 if (!vRecv.
empty()) {
4844 if (!vRecv.
empty()) {
4849 LogPrintf(
"connected to self at %s, disconnecting\n",
4850 pfrom.addr.ToString());
4851 pfrom.fDisconnect =
true;
4855 if (
pfrom.IsInboundConn() &&
addrMe.IsRoutable()) {
4861 if (
pfrom.IsInboundConn()) {
4869 pfrom.nVersion = nVersion;
4878 pfrom.m_has_all_wanted_services =
4880 peer->m_their_services = nServices;
4884 pfrom.cleanSubVer = cleanSubVer;
4893 if (!
pfrom.IsBlockOnlyConn() && !
pfrom.IsFeelerConn() &&
4895 auto *
const tx_relay = peer->SetTxRelay();
4902 pfrom.m_relays_txs =
true;
4906 pfrom.nRemoteHostNonce = nNonce;
4912 CNodeState *state = State(
pfrom.GetId());
4913 state->fPreferredDownload =
4914 (!
pfrom.IsInboundConn() ||
4924 if (!
pfrom.IsInboundConn()) {
4937 peer->m_getaddr_sent =
true;
4941 WITH_LOCK(peer->m_addr_token_bucket_mutex,
4942 peer->m_addr_token_bucket += m_opts.max_addr_to_send);
4945 if (!
pfrom.IsInboundConn()) {
4969 "receive version message: [%s] %s: version %d, blocks=%d, "
4970 "us=%s, txrelay=%d, peer=%d%s\n",
4971 pfrom.addr.ToString(), cleanSubVer,
pfrom.nVersion,
4977 pfrom.nTimeOffset = nTimeOffset;
4982 "Ignoring invalid timestamp in version message");
4983 }
else if (!
pfrom.IsInboundConn()) {
4990 if (
pfrom.IsFeelerConn()) {
4992 "feeler connection completed peer=%d; disconnecting\n",
4994 pfrom.fDisconnect =
true;
4999 if (
pfrom.nVersion == 0) {
5001 Misbehaving(*peer, 10,
"non-version message before version handshake");
5009 if (
pfrom.fSuccessfullyConnected) {
5011 "ignoring redundant verack message from peer=%d\n",
5016 if (!
pfrom.IsInboundConn()) {
5018 "New outbound peer connected: version: %d, blocks=%d, "
5020 pfrom.nVersion.load(), peer->m_starting_height,
pfrom.GetId(),
5046 peer->m_proof_relay->m_recently_announced_proofs.insert(
5047 localProof->getId());
5052 if (
auto tx_relay = peer->GetTxRelay()) {
5061 return tx_relay->m_tx_inventory_to_send.empty() &&
5062 tx_relay->m_next_inv_send_time == 0s));
5065 pfrom.fSuccessfullyConnected =
true;
5069 if (!
pfrom.fSuccessfullyConnected) {
5071 Misbehaving(*peer, 10,
"non-verack message before version handshake");
5085 std::vector<CAddress> vAddr;
5095 if (vAddr.size() > m_opts.max_addr_to_send) {
5103 std::vector<CAddress>
vAddrOk;
5109 LOCK(peer->m_addr_token_bucket_mutex);
5116 peer->m_addr_token_bucket =
5117 std::min<double>(peer->m_addr_token_bucket +
increment,
5134 LOCK(peer->m_addr_token_bucket_mutex);
5136 if (peer->m_addr_token_bucket < 1.0) {
5142 peer->m_addr_token_bucket -= 1.0;
5177 peer->m_addr_processed +=
num_proc;
5180 "Received addr: %u addresses (%u processed, %u rate-limited) "
5185 if (vAddr.size() < 1000) {
5186 peer->m_getaddr_sent =
false;
5191 if (
pfrom.IsAddrFetchConn() && vAddr.size() > 1) {
5193 "addrfetch connection completed peer=%d; disconnecting\n",
5195 pfrom.fDisconnect =
true;
5201 peer->m_wants_addrv2 =
true;
5206 peer->m_prefers_headers =
true;
5221 nodestate->m_provides_cmpctblocks =
true;
5231 std::vector<CInv>
vInv;
5254 if (
inv.IsMsgStakeContender()) {
5260 if (
inv.IsMsgBlk()) {
5281 if (
inv.IsMsgProof()) {
5294 LOCK(cs_proofrequest);
5301 if (
inv.IsMsgTx()) {
5311 "transaction (%s) inv sent in violation of "
5312 "protocol, disconnecting peer=%d\n",
5314 pfrom.fDisconnect =
true;
5317 .IsInitialBlockDownload()) {
5325 "Unknown inv type \"%s\" received from peer=%d\n",
5342 if (state.fSyncStarted ||
5343 (!peer->m_inv_triggered_getheaders_before_sync &&
5348 m_chainman.m_best_header->nHeight,
5351 if (!state.fSyncStarted) {
5352 peer->m_inv_triggered_getheaders_before_sync =
true;
5365 std::vector<CInv>
vInv;
5376 if (
vInv.size() > 0) {
5382 LOCK(peer->m_getdata_requests_mutex);
5383 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(),
5398 "getblocks locator size %lld > %d, disconnect peer=%d\n",
5400 pfrom.fDisconnect =
true;
5414 LOCK(m_most_recent_block_mutex);
5437 (pindex ? pindex->
nHeight : -1),
5440 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex)) {
5453 (!pindex->nStatus.hasData() ||
5458 " getblocks stopping, pruned or too old block at %d %s\n",
5463 peer->m_block_inv_mutex,
5464 peer->m_blocks_for_inv_relay.push_back(pindex->
GetBlockHash()));
5471 peer->m_continuation_block = pindex->GetBlockHash();
5485 LOCK(m_most_recent_block_mutex);
5501 if (!pindex || !pindex->nStatus.hasData()) {
5504 "Peer %d sent us a getblocktxn for a block we don't have\n",
5529 "Peer %d sent us a getblocktxn for a block > %i deep\n",
5534 WITH_LOCK(peer->m_getdata_requests_mutex,
5535 peer->m_getdata_requests.push_back(
inv));
5548 "getheaders locator size %lld > %d, disconnect peer=%d\n",
5550 pfrom.fDisconnect =
true;
5557 "Ignoring getheaders from peer=%d while importing/reindexing\n",
5571 if (m_chainman.
ActiveTip() ==
nullptr ||
5576 "Ignoring getheaders from peer=%d because active chain "
5577 "has too little work; sending empty response\n",
5582 std::vector<CBlock>()));
5597 "%s: ignoring request from peer=%i for old block "
5598 "header that isn't in the main chain\n",
5616 (pindex ? pindex->
nHeight : -1),
5619 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex)) {
5648 "transaction sent in violation of protocol peer=%d\n",
5650 pfrom.fDisconnect =
true;
5682 "Not relaying non-mempool transaction %s from "
5683 "forcerelay peer=%d\n",
5686 LogPrintf(
"Force relaying tx %s from peer=%d\n",
5688 RelayTransaction(tx.