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) {
3059 if (localProof && localProof->getId() == proofid) {
3064 return pm.exists(proofid) ||
pm.isInvalid(proofid);
3068void PeerManagerImpl::SendPings() {
3071 it.second->m_ping_queued =
true;
3075void PeerManagerImpl::RelayTransaction(
const TxId &txid) {
3078 Peer &peer = *it.second;
3089 if (
tx_relay->m_next_inv_send_time == 0s) {
3093 if (!
tx_relay->m_tx_inventory_known_filter.contains(txid)) {
3094 tx_relay->m_tx_inventory_to_send.insert(txid);
3102 Peer &peer = *it.second;
3104 if (!peer.m_proof_relay) {
3107 LOCK(peer.m_proof_relay->m_proof_inventory_mutex);
3108 if (!peer.m_proof_relay->m_proof_inventory_known_filter.contains(
3110 peer.m_proof_relay->m_proof_inventory_to_send.insert(proofid);
3146 std::array<std::pair<uint64_t, Peer *>, 2>
best{
3147 {{0,
nullptr}, {0,
nullptr}}};
3153 if (peer->m_addr_relay_enabled &&
id !=
originator &&
3159 best.begin() + i + 1);
3167 for (
unsigned int i = 0; i <
nRelayNodes &&
best[i].first != 0; i++) {
3172void PeerManagerImpl::ProcessGetBlockData(
const Config &config,
CNode &
pfrom,
3173 Peer &peer,
const CInv &
inv) {
3179 LOCK(m_most_recent_block_mutex);
3218 "%s: ignoring request from peer=%i for old "
3219 "block that isn't in the main chain\n",
3227 (((m_chainman.m_best_header !=
nullptr) &&
3228 (m_chainman.m_best_header->GetBlockTime() - pindex->
GetBlockTime() >
3230 inv.IsMsgFilteredBlk()) &&
3234 "historical block serving limit reached, disconnect peer=%d\n",
3236 pfrom.fDisconnect =
true;
3249 "Ignore block request below NODE_NETWORK_LIMITED "
3250 "threshold, disconnect peer=%d\n",
3255 pfrom.fDisconnect =
true;
3260 if (!pindex->nStatus.hasData()) {
3263 std::shared_ptr<const CBlock>
pblock;
3268 std::shared_ptr<CBlock>
pblockRead = std::make_shared<CBlock>();
3270 assert(!
"cannot load block from disk");
3274 if (
inv.IsMsgBlk()) {
3277 }
else if (
inv.IsMsgFilteredBlk()) {
3280 if (
auto tx_relay = peer.GetTxRelay()) {
3299 typedef std::pair<size_t, uint256>
PairType;
3308 }
else if (
inv.IsMsgCmpctBlk()) {
3336 LOCK(peer.m_block_inv_mutex);
3339 if (hash == peer.m_continuation_block) {
3343 std::vector<CInv>
vInv;
3347 peer.m_continuation_block =
BlockHash();
3353PeerManagerImpl::FindTxForGetData(
const Peer &peer,
const TxId &txid,
3355 const std::chrono::seconds now) {
3363 return std::move(
txinfo.tx);
3371 if (
Assume(peer.GetTxRelay())
3372 ->m_recently_announced_invs.contains(txid)) {
3375 return std::move(
txinfo.tx);
3391PeerManagerImpl::FindProofForGetData(
const Peer &peer,
3393 const std::chrono::seconds now) {
3427 if (peer.m_proof_relay->m_recently_announced_proofs.contains(proofid)) {
3434void PeerManagerImpl::ProcessGetData(
3441 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
3448 ?
tx_relay->m_last_mempool_req.load()
3449 : std::chrono::seconds::min();
3454 while (it != peer.m_getdata_requests.end()) {
3460 if (
pfrom.fPauseSend) {
3466 if (it->IsMsgStakeContender()) {
3473 if (it->IsMsgProof()) {
3485 pm.removeUnbroadcastProof(proofid);
3495 if (it->IsMsgTx()) {
3515 auto txiter = m_mempool.
GetIter(tx->GetId());
3519 (*pentry)->GetMemPoolParentsConst();
3521 for (
const auto &parent :
parents) {
3522 if (parent.get()->GetTime() >
3525 parent.get()->GetTx().GetId());
3534 return !
tx_relay->m_tx_inventory_known_filter
3553 if (it != peer.m_getdata_requests.end() && !
pfrom.fPauseSend) {
3555 if (
inv.IsGenBlkMsg()) {
3562 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
3582void PeerManagerImpl::SendBlockTransactions(
3586 for (
size_t i = 0; i < req.
indices.size(); i++) {
3588 Misbehaving(peer, 100,
"getblocktxn with out-of-bounds tx indices");
3600bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader> &
headers,
3605 Misbehaving(peer, 100,
"header with invalid proof of work");
3611 Misbehaving(peer, 20,
"non-continuous headers sequence");
3643void PeerManagerImpl::HandleFewUnconnectingHeaders(
3647 peer.m_num_unconnecting_headers_msgs++;
3654 "received header %s: missing prev block %s, sending getheaders "
3655 "(%d) to end (peer=%d, m_num_unconnecting_headers_msgs=%d)\n",
3658 pfrom.GetId(), peer.m_num_unconnecting_headers_msgs);
3669 if (peer.m_num_unconnecting_headers_msgs %
3674 peer.m_num_unconnecting_headers_msgs));
3678bool PeerManagerImpl::CheckHeadersAreContinuous(
3679 const std::vector<CBlockHeader> &
headers)
const {
3690bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(
3692 if (peer.m_headers_sync) {
3693 auto result = peer.m_headers_sync->ProcessNextHeaders(
3695 if (result.request_more) {
3696 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
3711 "more getheaders (from %s) to peer=%d\n",
3715 "error sending next getheaders (from %s) to "
3716 "continue sync with peer=%d\n",
3723 peer.m_headers_sync.reset(
nullptr);
3728 LOCK(m_headers_presync_mutex);
3732 HeadersPresyncStats stats;
3733 stats.first = peer.m_headers_sync->GetPresyncWork();
3734 if (peer.m_headers_sync->GetState() ==
3736 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
3737 peer.m_headers_sync->GetPresyncTime()};
3741 LOCK(m_headers_presync_mutex);
3751 const HeadersPresyncStats *
stat_best{
nullptr};
3770 m_headers_presync_should_signal =
true;
3774 if (result.success) {
3777 headers.swap(result.pow_validated_headers);
3780 return result.success;
3788bool PeerManagerImpl::TryLowWorkHeadersSync(
3790 std::vector<CBlockHeader> &
headers) {
3815 LOCK(peer.m_headers_sync_mutex);
3816 peer.m_headers_sync.reset(
3826 "Ignoring low-work chain (height=%u) from peer=%d\n",
3839bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex *header) {
3840 return header !=
nullptr &&
3841 ((m_chainman.m_best_header !=
nullptr &&
3843 m_chainman.m_best_header->GetAncestor(header->
nHeight)) ||
3847bool PeerManagerImpl::MaybeSendGetHeaders(
CNode &
pfrom,
3872void PeerManagerImpl::HeadersDirectFetchBlocks(
const Config &config,
3882 std::vector<const CBlockIndex *>
vToFetch;
3907 if (
nodestate->vBlocksInFlight.size() >=
3919 "Downloading blocks toward %s (%d) via headers "
3925 if (!m_opts.ignore_incoming_txs &&
3945void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
3948 if (peer.m_num_unconnecting_headers_msgs > 0) {
3951 "peer=%d: resetting m_num_unconnecting_headers_msgs (%d -> 0)\n",
3952 pfrom.GetId(), peer.m_num_unconnecting_headers_msgs);
3954 peer.m_num_unconnecting_headers_msgs = 0;
3978 nodestate->pindexBestKnownBlock->nChainWork <
3988 if (
pfrom.IsOutboundOrBlockRelayConn()) {
3989 LogPrintf(
"Disconnecting outbound peer %d -- headers "
3990 "chain has insufficient work\n",
3992 pfrom.fDisconnect =
true;
4003 if (!
pfrom.fDisconnect &&
pfrom.IsFullOutboundConn() &&
4004 nodestate->pindexBestKnownBlock !=
nullptr) {
4007 nodestate->pindexBestKnownBlock->nChainWork >=
4012 nodestate->m_chain_sync.m_protect =
true;
4018void PeerManagerImpl::ProcessHeadersMessage(
const Config &config,
CNode &
pfrom,
4020 std::vector<CBlockHeader> &&
headers,
4030 LOCK(peer.m_headers_sync_mutex);
4031 if (peer.m_headers_sync) {
4032 peer.m_headers_sync.reset(
nullptr);
4033 LOCK(m_headers_presync_mutex);
4063 LOCK(peer.m_headers_sync_mutex);
4148 "invalid header received");
4161 "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
4174void PeerManagerImpl::ProcessInvalidTx(
NodeId nodeid,
4182 const TxId &txid =
ptx->GetId();
4217 return orphanage.EraseTx(txid);
4242 "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n",
4243 nodeid, tx->GetId().ToString(), m_mempool.
size(),
4246 RelayTransaction(tx->GetId());
4249void PeerManagerImpl::ProcessPackageResult(
4256 const auto &
package = package_to_validate.m_txns;
4309std::optional<PeerManagerImpl::PackageToValidate>
4333 return PeerManagerImpl::PackageToValidate{
ptx,
child, nodeid,
4349 return orphanage.GetChildrenFromDifferentPeer(
ptx, nodeid);
4369 return PeerManagerImpl::PackageToValidate{
ptx,
child_tx, nodeid,
4373 return std::nullopt;
4376bool PeerManagerImpl::ProcessOrphanTx(
const Config &config, Peer &peer) {
4382 return orphanage.GetTxToReconsider(peer.m_id);
4398 " invalid orphan tx %s from peer=%d. %s\n",
4416bool PeerManagerImpl::PrepareBlockFilterRequest(
4425 "peer %d requested unsupported block filter type: %d\n",
4427 node.fDisconnect =
true;
4440 node.fDisconnect =
true;
4449 "peer %d sent invalid getcfilters/getcfheaders with "
4451 "start height %d and stop height %d\n",
4453 node.fDisconnect =
true;
4458 "peer %d requested too many cfilters/cfheaders: %d / %d\n",
4460 node.fDisconnect =
true;
4465 if (!filter_index) {
4474void PeerManagerImpl::ProcessGetCFilters(
CNode &
node, Peer &peer,
4493 std::vector<BlockFilter>
filters;
4496 "Failed to find block filter in index: filter_type=%s, "
4497 "start_height=%d, stop_hash=%s\n",
4503 for (
const auto &filter :
filters) {
4510void PeerManagerImpl::ProcessGetCFHeaders(
CNode &
node, Peer &peer,
4535 "Failed to find block filter header in index: "
4536 "filter_type=%s, block_hash=%s\n",
4547 "Failed to find block filter hashes in index: filter_type=%s, "
4548 "start_height=%d, stop_hash=%s\n",
4561void PeerManagerImpl::ProcessGetCFCheckPt(
CNode &
node, Peer &peer,
4575 std::numeric_limits<uint32_t>::max(),
4584 for (
int i =
headers.size() - 1; i >= 0; i--) {
4590 "Failed to find block filter header in index: "
4591 "filter_type=%s, block_hash=%s\n",
4616PeerManagerImpl::GetAvalancheVoteForBlock(
const BlockHash &hash)
const {
4627 if (pindex->nStatus.isInvalid()) {
4632 if (pindex->nStatus.isOnParkedChain()) {
4650 if (!pindex->nStatus.hasData()) {
4659uint32_t PeerManagerImpl::GetAvalancheVoteForTx(
const TxId &
id)
const {
4661 if (m_mempool.
exists(
id) ||
4662 WITH_LOCK(m_recent_confirmed_transactions_mutex,
4669 return conflicting.HaveTx(id);
4681 return orphanage.HaveTx(id);
4700 if (
pm.isInvalid(
id)) {
4705 if (
pm.isBoundToPeer(
id)) {
4710 if (!
pm.exists(
id)) {
4715 if (
pm.isImmature(
id)) {
4720 if (
pm.isInConflictingPool(
id)) {
4732 const std::shared_ptr<const CBlock> &block,
4751void PeerManagerImpl::ProcessMessage(
4753 CDataStream &vRecv,
const std::chrono::microseconds time_received,
4761 if (peer ==
nullptr) {
4767 "Avalanche is not initialized, ignoring %s message\n",
4774 if (
pfrom.nVersion != 0) {
4775 Misbehaving(*peer, 1,
"redundant version message");
4784 std::string cleanSubVer;
4796 if (!
pfrom.IsInboundConn()) {
4799 if (
pfrom.ExpectServicesFromConn() &&
4802 "peer=%d does not offer the expected services "
4803 "(%08x offered, %08x expected); disconnecting\n",
4804 pfrom.GetId(), nServices,
4806 pfrom.fDisconnect =
true;
4810 if (
pfrom.IsAvalancheOutboundConnection() &&
4814 "peer=%d does not offer the avalanche service; disconnecting\n",
4816 pfrom.fDisconnect =
true;
4823 "peer=%d using obsolete version %i; disconnecting\n",
4824 pfrom.GetId(), nVersion);
4825 pfrom.fDisconnect =
true;
4829 if (!vRecv.
empty()) {
4838 if (!vRecv.
empty()) {
4839 std::string strSubVer;
4843 if (!vRecv.
empty()) {
4846 if (!vRecv.
empty()) {
4849 if (!vRecv.
empty()) {
4854 LogPrintf(
"connected to self at %s, disconnecting\n",
4855 pfrom.addr.ToString());
4856 pfrom.fDisconnect =
true;
4860 if (
pfrom.IsInboundConn() &&
addrMe.IsRoutable()) {
4866 if (
pfrom.IsInboundConn()) {
4874 pfrom.nVersion = nVersion;
4883 pfrom.m_has_all_wanted_services =
4885 peer->m_their_services = nServices;
4889 pfrom.cleanSubVer = cleanSubVer;
4898 if (!
pfrom.IsBlockOnlyConn() && !
pfrom.IsFeelerConn() &&
4900 auto *
const tx_relay = peer->SetTxRelay();
4907 pfrom.m_relays_txs =
true;
4911 pfrom.nRemoteHostNonce = nNonce;
4917 CNodeState *state = State(
pfrom.GetId());
4918 state->fPreferredDownload =
4919 (!
pfrom.IsInboundConn() ||
4929 if (!
pfrom.IsInboundConn()) {
4942 peer->m_getaddr_sent =
true;
4946 WITH_LOCK(peer->m_addr_token_bucket_mutex,
4947 peer->m_addr_token_bucket += m_opts.max_addr_to_send);
4950 if (!
pfrom.IsInboundConn()) {
4974 "receive version message: [%s] %s: version %d, blocks=%d, "
4975 "us=%s, txrelay=%d, peer=%d%s\n",
4976 pfrom.addr.ToString(), cleanSubVer,
pfrom.nVersion,
4982 pfrom.nTimeOffset = nTimeOffset;
4987 "Ignoring invalid timestamp in version message");
4988 }
else if (!
pfrom.IsInboundConn()) {
4995 if (
pfrom.IsFeelerConn()) {
4997 "feeler connection completed peer=%d; disconnecting\n",
4999 pfrom.fDisconnect =
true;
5004 if (
pfrom.nVersion == 0) {
5006 Misbehaving(*peer, 10,
"non-version message before version handshake");
5014 if (
pfrom.fSuccessfullyConnected) {
5016 "ignoring redundant verack message from peer=%d\n",
5021 if (!
pfrom.IsInboundConn()) {
5023 "New outbound peer connected: version: %d, blocks=%d, "
5025 pfrom.nVersion.load(), peer->m_starting_height,
pfrom.GetId(),
5051 peer->m_proof_relay->m_recently_announced_proofs.insert(
5052 localProof->getId());
5057 if (
auto tx_relay = peer->GetTxRelay()) {
5066 return tx_relay->m_tx_inventory_to_send.empty() &&
5067 tx_relay->m_next_inv_send_time == 0s));
5070 pfrom.fSuccessfullyConnected =
true;
5074 if (!
pfrom.fSuccessfullyConnected) {
5076 Misbehaving(*peer, 10,
"non-verack message before version handshake");
5090 std::vector<CAddress> vAddr;
5100 if (vAddr.size() > m_opts.max_addr_to_send) {
5108 std::vector<CAddress>
vAddrOk;
5114 LOCK(peer->m_addr_token_bucket_mutex);
5121 peer->m_addr_token_bucket =
5122 std::min<double>(peer->m_addr_token_bucket +
increment,
5139 LOCK(peer->m_addr_token_bucket_mutex);
5141 if (peer->m_addr_token_bucket < 1.0) {
5147 peer->m_addr_token_bucket -= 1.0;
5182 peer->m_addr_processed +=
num_proc;
5185 "Received addr: %u addresses (%u processed, %u rate-limited) "
5190 if (vAddr.size() < 1000) {
5191 peer->m_getaddr_sent =
false;
5196 if (
pfrom.IsAddrFetchConn() && vAddr.size() > 1) {
5198 "addrfetch connection completed peer=%d; disconnecting\n",
5200 pfrom.fDisconnect =
true;
5206 peer->m_wants_addrv2 =
true;
5211 peer->m_prefers_headers =
true;
5226 nodestate->m_provides_cmpctblocks =
true;
5236 std::vector<CInv>
vInv;
5259 if (
inv.IsMsgStakeContender()) {
5265 if (
inv.IsMsgBlk()) {
5286 if (
inv.IsMsgProof()) {
5296 LOCK(cs_proofrequest);
5303 if (
inv.IsMsgTx()) {
5313 "transaction (%s) inv sent in violation of "
5314 "protocol, disconnecting peer=%d\n",
5316 pfrom.fDisconnect =
true;
5319 .IsInitialBlockDownload()) {
5327 "Unknown inv type \"%s\" received from peer=%d\n",
5344 if (state.fSyncStarted ||
5345 (!peer->m_inv_triggered_getheaders_before_sync &&
5350 m_chainman.m_best_header->nHeight,
5353 if (!state.fSyncStarted) {
5354 peer->m_inv_triggered_getheaders_before_sync =
true;
5367 std::vector<CInv>
vInv;
5378 if (
vInv.size() > 0) {
5384 LOCK(peer->m_getdata_requests_mutex);
5385 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(),
5400 "getblocks locator size %lld > %d, disconnect peer=%d\n",
5402 pfrom.fDisconnect =
true;
5416 LOCK(m_most_recent_block_mutex);
5439 (pindex ? pindex->
nHeight : -1),
5442 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex)) {
5455 (!pindex->nStatus.hasData() ||
5460 " getblocks stopping, pruned or too old block at %d %s\n",
5465 peer->m_block_inv_mutex,
5466 peer->m_blocks_for_inv_relay.push_back(pindex->
GetBlockHash()));
5473 peer->m_continuation_block = pindex->GetBlockHash();
5487 LOCK(m_most_recent_block_mutex);
5503 if (!pindex || !pindex->nStatus.hasData()) {
5506 "Peer %d sent us a getblocktxn for a block we don't have\n",
5531 "Peer %d sent us a getblocktxn for a block > %i deep\n",
5536 WITH_LOCK(peer->m_getdata_requests_mutex,
5537 peer->m_getdata_requests.push_back(
inv));
5550 "getheaders locator size %lld > %d, disconnect peer=%d\n",
5552 pfrom.fDisconnect =
true;
5559 "Ignoring getheaders from peer=%d while importing/reindexing\n",
5573 if (m_chainman.
ActiveTip() ==
nullptr ||
5578 "Ignoring getheaders from peer=%d because active chain "
5579 "has too little work; sending empty response\n",
5584 std::vector<CBlock>()));
5599 "%s: ignoring request from peer=%i for old block "
5600 "header that isn't in the main chain\n",
5618 (pindex ? pindex->
nHeight : -1),
5621 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex)) {
5650 "transaction sent in violation of protocol peer=%d\n",
5652 pfrom.fDisconnect =
true;
5684 "Not relaying non-mempool transaction %s from "
5685 "forcerelay peer=%d\n",
5688 LogPrintf(
"Force relaying tx %s from peer=%d\n",
5690 RelayTransaction(tx.
GetId());
5702 "found tx %s in reconsiderable rejects, looking for "
5703 "child in orphanage\n",
5712 "package evaluation for %s: %s (%s)\n",
5715 ?
"package accepted"
5716 :
"package rejected",
5818 if (orphanage.AddTx(ptx,
5820 AddToCompactExtraTransactions(ptx);
5823 m_opts.max_orphan_txs,
m_rng);
5826 "orphanage overflow, removed %u tx\n",
5836 "not keeping orphan with rejected parents %s\n",
5855 "tx %s failed but reconsiderable, looking for child in "
5864 "package evaluation for %s: %s (%s)\n",
5867 ?
"package accepted"
5868 :
"package rejected",
5888 m_opts.max_conflicting_txs,
m_rng);
5894 "conflicting pool overflow, removed %u tx\n",
5911 "Unexpected cmpctblock message received from peer %d\n",
5919 }
catch (std::ios_base::failure &
e) {
5921 Misbehaving(*peer, 100,
"cmpctblock-bad-indexes");
5948 "Ignoring low-work compact block from peer %d\n",
5967 "invalid header via cmpctblock");
5986 std::shared_ptr<CBlock>
pblock = std::make_shared<CBlock>();
6005 if (pindex->nStatus.hasData()) {
6040 std::vector<CInv>
vInv(1);
6064 if (!(*queuedBlockIt)->partialBlock) {
6066 ->partialBlock.reset(
6073 "we were already syncing!\n");
6079 *(*queuedBlockIt)->partialBlock;
6093 std::vector<CInv>
vInv(1);
6108 for (
size_t i = 0; i <
cmpctblock.BlockTxCount(); i++) {
6127 }
else if (
pfrom.m_bip152_highbandwidth_to &&
6128 (!
pfrom.IsInboundConn() ||
6160 std::vector<CTransactionRef> dummy;
6171 std::vector<CInv>
vInv(1);
6206 std::make_pair(
pfrom.GetId(),
false));
6236 "Unexpected blocktxn message received from peer %d\n",
6244 std::shared_ptr<CBlock>
pblock = std::make_shared<CBlock>();
6271 "Peer %d sent us block transactions for block "
6272 "we weren't expecting\n",
6286 "invalid compact block/non-matching block transactions");
6291 std::vector<CInv> invs;
6299 "Peer %d sent us a compact block but it failed to "
6300 "reconstruct, waiting on first download to complete\n",
6333 std::make_pair(
pfrom.GetId(),
false));
6354 "Unexpected headers message received from peer %d\n",
6361 peer->m_last_getheaders_timestamp = {};
6363 std::vector<CBlockHeader>
headers;
6370 strprintf(
"too-many-headers: headers message size = %u",
6375 for (
unsigned int n = 0; n <
nCount; n++) {
6387 if (m_headers_presync_should_signal.exchange(
false)) {
6388 HeadersPresyncStats stats;
6390 LOCK(m_headers_presync_mutex);
6399 stats.first, stats.second->first, stats.second->second);
6410 "Unexpected block message received from peer %d\n",
6415 std::shared_ptr<CBlock>
pblock = std::make_shared<CBlock>();
6461 if (
pfrom.m_avalanche_pubkey.has_value()) {
6464 "Ignoring avahello from peer %d: already in our node set\n",
6470 vRecv >> delegation;
6477 if (!delegation.
verify(state, pubkey)) {
6481 pfrom.m_avalanche_pubkey = std::move(pubkey);
6492 if (!(*
pfrom.m_avalanche_pubkey)
6494 Misbehaving(*peer, 100,
"invalid-avahello-signature");
6503 LOCK(cs_proofrequest);
6504 AddProofAnnouncement(
pfrom, proofid,
6512 return pm.addNode(
pfrom.GetId(), proofid);
6516 pfrom.m_avalanche_enabled =
true;
6521 if (!
pfrom.IsInboundConn()) {
6524 WITH_LOCK(peer->m_addr_token_bucket_mutex,
6525 peer->m_addr_token_bucket += m_opts.max_addr_to_send);
6527 if (peer->m_proof_relay &&
6531 peer->m_proof_relay->compactproofs_requested =
true;
6545 pfrom.m_last_poll = now;
6548 last_poll + std::chrono::milliseconds(m_opts.avalanche_cooldown)) {
6550 "Ignoring repeated avapoll from peer %d: cooldown not "
6569 std::vector<avalanche::Vote> votes;
6572 for (
unsigned int n = 0; n <
nCount; n++) {
6581 votes.emplace_back(
vote,
inv.hash);
6588 if (m_opts.avalanche_preconsensus) {
6602 if (m_opts.avalanche_staking_preconsensus) {
6609 "poll inv type %d unknown from peer=%d\n",
6614 votes.emplace_back(
vote,
inv.hash);
6640 if (!
pfrom.m_avalanche_pubkey.has_value() ||
6641 !(*
pfrom.m_avalanche_pubkey)
6643 Misbehaving(*peer, 100,
"invalid-ava-response-signature");
6650 std::vector<avalanche::VoteItemUpdate> updates;
6666 pfrom.m_avalanche_message_fault_counter++;
6667 pfrom.m_avalanche_last_message_fault = now;
6672 if (
pfrom.m_avalanche_message_fault_counter > 12) {
6679 if (now > (
pfrom.m_avalanche_last_message_fault.load() + 1
h)) {
6680 pfrom.m_avalanche_message_fault_counter = 0;
6726 for (
const auto &u : updates) {
6731 if (
auto pitem = std::get_if<const avalanche::ProofRef>(&item)) {
6740 switch (u.getStatus()) {
6744 pm.setInvalid(proofid);
6756 return pm.rejectProof(proofid,
6760 "ERROR: Failed to reject proof: %s\n",
6766 m_opts.avalanche_peer_replacement_cooldown);
6772 avalanche::PeerManager::
6773 RegistrationMode::FORCE_ACCEPT);
6776 [&](const avalanche::Peer &peer) {
6777 pm.updateNextPossibleConflictTime(
6779 nextCooldownTimePoint);
6780 if (u.getStatus() ==
6781 avalanche::VoteStatus::
6783 pm.setFinalized(peer.peerid);
6791 "ERROR: Failed to accept proof: %s\n",
6806 std::make_shared<CBlock>();
6809 assert(!
"cannot load block from disk");
6816 if (
auto pitem = std::get_if<const CBlockIndex *>(&item)) {
6823 switch (u.getStatus()) {
6828 LogPrintf(
"ERROR: Database error: %s\n",
6837 LogPrintf(
"ERROR: Database error: %s\n",
6858 if (m_opts.avalanche_preconsensus) {
6867 pindex, *m_avalanche);
6877 if (!m_opts.avalanche_preconsensus) {
6881 if (
auto pitem = std::get_if<const CTransactionRef>(&item)) {
6885 const TxId &txid = tx->GetId();
6888 switch (u.getStatus()) {
6895 if (m_mempool.
exists(txid)) {
6947 return conflicting.HaveTx(txid);
6950 std::vector<CTransactionRef>
6952 for (
const auto &
txin : tx->vin) {
6975 mempool_conflicting_txs[0],
6984 auto it = m_mempool.
GetIter(txid);
6985 if (!it.has_value()) {
6988 "Error: finalized tx (%s) is not in the "
7001 std::vector<CTransactionRef>
7025 state,
nullptr, m_avalanche)) {
7049 if (peer->m_proof_relay ==
nullptr) {
7053 peer->m_proof_relay->lastSharedProofsUpdate =
7056 peer->m_proof_relay->sharedProofs =
7058 return pm.getShareableProofsSnapshot();
7062 peer->m_proof_relay->sharedProofs);
7073 if (peer->m_proof_relay ==
nullptr) {
7078 if (!peer->m_proof_relay->compactproofs_requested) {
7082 peer->m_proof_relay->compactproofs_requested =
false;
7087 }
catch (std::ios_base::failure &
e) {
7184 return pfrom.m_avalanche_pubkey.has_value())) {
7188 pm.saveRemoteProof(proofid, nodeid, present);
7197 if (peer->m_proof_relay ==
nullptr) {
7206 peer->m_proof_relay->sharedProofs.forEachLeaf([&](
const auto &proof) {
7221 peer->m_proof_relay->sharedProofs = {};
7232 if (!
pfrom.IsInboundConn()) {
7234 "Ignoring \"getaddr\" from %s connection. peer=%d\n",
7235 pfrom.ConnectionTypeAsString(),
pfrom.GetId());
7245 if (peer->m_getaddr_recvd) {
7250 peer->m_getaddr_recvd =
true;
7252 peer->m_addrs_to_send.clear();
7253 std::vector<CAddress> vAddr;
7262 for (
const CAddress &addr : vAddr) {
7270 if (now <
pfrom.m_nextGetAvaAddr) {
7281 "Ignoring getavaaddr message from %s peer=%d\n",
7282 pfrom.ConnectionTypeAsString(),
pfrom.GetId());
7304 if (!
pnode->m_avalanche_enabled ||
7305 pnode->getAvailabilityScore() < 0.) {
7310 if (
avaNodes.size() > m_opts.max_addr_to_send) {
7315 peer->m_addrs_to_send.clear();
7328 "mempool request with bloom filters disabled, "
7329 "disconnect peer=%d\n",
7331 pfrom.fDisconnect =
true;
7340 "mempool request with bandwidth limit reached, "
7341 "disconnect peer=%d\n",
7343 pfrom.fDisconnect =
true;
7348 if (
auto tx_relay = peer->GetTxRelay()) {
7380 const auto ping_end = time_received;
7386 if (nAvail >=
sizeof(nonce)) {
7391 if (peer->m_ping_nonce_sent != 0) {
7392 if (nonce == peer->m_ping_nonce_sent) {
7415 sProblem =
"Unsolicited pong without ping";
7426 "pong peer=%d: %s, %x expected, %x received, %u bytes\n",
7431 peer->m_ping_nonce_sent = 0;
7439 "filterload received despite not offering bloom services "
7440 "from peer=%d; disconnecting\n",
7442 pfrom.fDisconnect =
true;
7450 Misbehaving(*peer, 100,
"too-large bloom filter");
7451 }
else if (
auto tx_relay = peer->GetTxRelay()) {
7457 pfrom.m_bloom_filter_loaded =
true;
7465 "filteradd received despite not offering bloom services "
7466 "from peer=%d; disconnecting\n",
7468 pfrom.fDisconnect =
true;
7471 std::vector<uint8_t> vData;
7480 }
else if (
auto tx_relay = peer->GetTxRelay()) {
7483 tx_relay->m_bloom_filter->insert(vData);
7499 "filterclear received despite not offering bloom services "
7500 "from peer=%d; disconnecting\n",
7502 pfrom.fDisconnect =
true;
7505 auto tx_relay = peer->GetTxRelay();
7512 tx_relay->m_bloom_filter =
nullptr;
7515 pfrom.m_bloom_filter_loaded =
false;
7516 pfrom.m_relays_txs =
true;
7524 if (
auto tx_relay = peer->GetTxRelay()) {
7549 std::vector<CInv>
vInv;
7556 if (
inv.IsMsgTx()) {
7564 if (
inv.IsMsgProof()) {
7565 LOCK(cs_proofrequest);
7580bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode &
pnode, Peer &peer) {
7582 LOCK(peer.m_misbehavior_mutex);
7585 if (!peer.m_should_discourage) {
7589 peer.m_should_discourage =
false;
7595 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
7599 if (
pnode.IsManualConn()) {
7601 LogPrintf(
"Warning: not punishing manually connected peer %d!\n",
7606 if (
pnode.addr.IsLocal()) {
7610 "Warning: disconnecting but not discouraging %s peer %d!\n",
7611 pnode.m_inbound_onion ?
"inbound onion" :
"local", peer.m_id);
7612 pnode.fDisconnect =
true;
7642 if (peer ==
nullptr) {
7647 LOCK(peer->m_getdata_requests_mutex);
7648 if (!peer->m_getdata_requests.empty()) {
7655 if (
pfrom->fDisconnect) {
7666 LOCK(peer->m_getdata_requests_mutex);
7667 if (!peer->m_getdata_requests.empty()) {
7673 if (
pfrom->fPauseSend) {
7677 std::list<CNetMessage> msgs;
7680 if (
pfrom->vProcessMsg.empty()) {
7684 msgs.splice(msgs.begin(),
pfrom->vProcessMsg,
7685 pfrom->vProcessMsg.begin());
7686 pfrom->nProcessQueueSize -= msgs.front().m_raw_message_size;
7694 pfrom->ConnectionTypeAsString().c_str(), msg.
m_type.c_str(),
7695 msg.m_recv.size(), msg.m_recv.
data());
7697 if (m_opts.capture_messages) {
7702 msg.SetVersion(
pfrom->GetCommonVersion());
7705 if (!msg.m_valid_netmagic) {
7707 "PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n",
7716 pfrom->fDisconnect =
true;
7721 if (!msg.m_valid_header) {
7729 if (!msg.m_valid_checksum) {
7741 ProcessMessage(config, *
pfrom, msg.
m_type, vRecv, msg.m_time,
7748 LOCK(peer->m_getdata_requests_mutex);
7749 if (!peer->m_getdata_requests.empty()) {
7758 return orphanage.HaveTxToReconsider(peer->m_id);
7762 }
catch (
const std::exception &
e) {
7765 e.what(),
typeid(
e).name());
7774void PeerManagerImpl::ConsiderEviction(
CNode &
pto, Peer &peer,
7778 CNodeState &state = *State(
pto.GetId());
7781 if (!state.m_chain_sync.m_protect &&
pto.IsOutboundOrBlockRelayConn() &&
7782 state.fSyncStarted) {
7789 if (state.pindexBestKnownBlock !=
nullptr &&
7790 state.pindexBestKnownBlock->nChainWork >=
7792 if (state.m_chain_sync.m_timeout != 0s) {
7793 state.m_chain_sync.m_timeout = 0s;
7794 state.m_chain_sync.m_work_header =
nullptr;
7795 state.m_chain_sync.m_sent_getheaders =
false;
7797 }
else if (state.m_chain_sync.m_timeout == 0s ||
7798 (state.m_chain_sync.m_work_header !=
nullptr &&
7799 state.pindexBestKnownBlock !=
nullptr &&
7800 state.pindexBestKnownBlock->nChainWork >=
7801 state.m_chain_sync.m_work_header->nChainWork)) {
7807 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
7808 state.m_chain_sync.m_sent_getheaders =
false;
7809 }
else if (state.m_chain_sync.m_timeout > 0s &&
7815 if (state.m_chain_sync.m_sent_getheaders) {
7818 "Disconnecting outbound peer %d for old chain, best known "
7821 state.pindexBestKnownBlock !=
nullptr
7822 ? state.pindexBestKnownBlock->GetBlockHash().ToString()
7824 pto.fDisconnect =
true;
7826 assert(state.m_chain_sync.m_work_header);
7836 "sending getheaders to outbound peer=%d to verify chain "
7837 "work (current best known block:%s, benchmark blockhash: "
7840 state.pindexBestKnownBlock !=
nullptr
7841 ? state.pindexBestKnownBlock->GetBlockHash().ToString()
7843 state.m_chain_sync.m_work_header->GetBlockHash()
7845 state.m_chain_sync.m_sent_getheaders =
true;
7852 state.m_chain_sync.m_timeout =
7859void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now) {
7868 std::pair<NodeId, std::chrono::seconds>
youngest_peer{-1, 0},
7872 if (!
pnode->IsBlockOnlyConn() ||
pnode->fDisconnect) {
7876 next_youngest_peer = youngest_peer;
7877 youngest_peer.first = pnode->GetId();
7878 youngest_peer.second = pnode->m_last_block_time;
7902 pnode->fDisconnect =
true;
7904 "disconnecting extra block-relay-only peer=%d "
7905 "(last block received at time %d)\n",
7912 "keeping block-relay-only peer=%d chosen for eviction "
7913 "(connect time: %d, blocks_in_flight: %d)\n",
7939 if (!
pnode->IsFullOutboundConn() ||
pnode->fDisconnect) {
7942 CNodeState *state = State(
pnode->GetId());
7943 if (state ==
nullptr) {
7948 if (state->m_chain_sync.m_protect) {
7963 bool disconnected = m_connman.
ForNode(
7971 CNodeState &state = *State(
pnode->GetId());
7973 state.vBlocksInFlight.empty()) {
7975 "disconnecting extra outbound peer=%d (last block "
7976 "announcement received at time %d)\n",
7978 pnode->fDisconnect =
true;
7982 "keeping outbound peer=%d chosen for eviction "
7983 "(connect time: %d, blocks_in_flight: %d)\n",
7985 state.vBlocksInFlight.size());
8000void PeerManagerImpl::CheckForStaleTipAndEvictPeers() {
8007 if (now > m_stale_tip_check_time) {
8013 LogPrintf(
"Potential stale tip detected, will try using extra "
8014 "outbound peer (last tip update: %d seconds ago)\n",
8025 m_initial_sync_finished =
true;
8029void PeerManagerImpl::MaybeSendPing(
CNode &
node_to, Peer &peer,
8030 std::chrono::microseconds now) {
8032 node_to, std::chrono::duration_cast<std::chrono::seconds>(now)) &&
8033 peer.m_ping_nonce_sent &&
8047 if (peer.m_ping_queued) {
8052 if (peer.m_ping_nonce_sent == 0 &&
8062 }
while (nonce == 0);
8063 peer.m_ping_queued =
false;
8064 peer.m_ping_start = now;
8066 peer.m_ping_nonce_sent = nonce;
8072 peer.m_ping_nonce_sent = 0;
8078void PeerManagerImpl::MaybeSendAddr(
CNode &
node, Peer &peer,
8081 if (!peer.m_addr_relay_enabled) {
8085 LOCK(peer.m_addr_send_times_mutex);
8094 if (peer.m_next_local_addr_send != 0
us) {
8095 peer.m_addr_known->reset();
8111 peer.m_next_addr_send =
8114 const size_t max_addr_to_send = m_opts.max_addr_to_send;
8115 if (!
Assume(peer.m_addrs_to_send.size() <= max_addr_to_send)) {
8118 peer.m_addrs_to_send.resize(max_addr_to_send);
8126 bool ret = peer.m_addr_known->contains(addr.
GetKey());
8128 peer.m_addr_known->insert(addr.
GetKey());
8132 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(),
8133 peer.m_addrs_to_send.end(),
8135 peer.m_addrs_to_send.end());
8138 if (peer.m_addrs_to_send.empty()) {
8144 if (peer.m_wants_addrv2) {
8154 peer.m_addrs_to_send.clear();
8157 if (peer.m_addrs_to_send.capacity() > 40) {
8158 peer.m_addrs_to_send.shrink_to_fit();
8162void PeerManagerImpl::MaybeSendSendHeaders(
CNode &
node, Peer &peer) {
8167 if (!peer.m_sent_sendheaders &&
8170 CNodeState &state = *State(
node.GetId());
8171 if (state.pindexBestKnownBlock !=
nullptr &&
8172 state.pindexBestKnownBlock->nChainWork >
8180 peer.m_sent_sendheaders =
true;
8185void PeerManagerImpl::MaybeSendFeefilter(
8187 if (m_opts.ignore_incoming_txs) {
8200 if (
pto.IsBlockOnlyConn()) {
8215 peer.m_next_send_feefilter = 0
us;
8229 peer.m_next_send_feefilter =
8236 peer.m_next_send_feefilter &&
8239 peer.m_next_send_feefilter =
8246class CompareInvMempoolOrder {
8252 bool operator()(std::set<TxId>::iterator
a, std::set<TxId>::iterator
b) {
8262bool PeerManagerImpl::RejectIncomingTxs(
const CNode &peer)
const {
8271 if (m_opts.ignore_incoming_txs &&
8278bool PeerManagerImpl::SetupAddressRelay(
const CNode &
node, Peer &peer) {
8282 if (
node.IsBlockOnlyConn()) {
8286 if (!peer.m_addr_relay_enabled.exchange(
true)) {
8290 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
8296bool PeerManagerImpl::SendMessages(
const Config &config,
CNode *
pto) {
8313 if (!
pto->fSuccessfullyConnected ||
pto->fDisconnect) {
8323 if (
pto->IsAddrFetchConn() &&
8326 "addrfetch connection timeout; disconnecting peer=%d\n",
8328 pto->fDisconnect =
true;
8335 if (
pto->fDisconnect) {
8348 CNodeState &state = *State(
pto->GetId());
8351 if (m_chainman.m_best_header ==
nullptr) {
8358 if (state.fPreferredDownload) {
8397 "initial getheaders (%d) to peer=%d (startheight:%d)\n",
8399 peer->m_starting_height);
8401 state.fSyncStarted =
true;
8402 peer->m_headers_sync_timeout =
8407 std::chrono::microseconds{
8411 m_chainman.m_best_header->Time()) /
8428 LOCK(peer->m_block_inv_mutex);
8431 ((!peer->m_prefers_headers &&
8432 (!state.m_requested_hb_cmpctblocks ||
8433 peer->m_blocks_for_headers_relay.size() > 1)) ||
8434 peer->m_blocks_for_headers_relay.size() >
8476 }
else if (pindex->
pprev ==
nullptr ||
8491 if (
vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
8496 "%s sending header-and-ids %s to peer=%d\n",
8502 LOCK(m_most_recent_block_mutex);
8524 }
else if (peer->m_prefers_headers) {
8527 "%s: %u headers, range (%s, %s), to peer=%d\n",
8529 vHeaders.front().GetHash().ToString(),
8530 vHeaders.back().GetHash().ToString(),
8534 "%s: sending header %s to peer=%d\n",
__func__,
8535 vHeaders.front().GetHash().ToString(),
8549 if (!peer->m_blocks_for_headers_relay.empty()) {
8551 peer->m_blocks_for_headers_relay.back();
8562 "Announcing block %s not on main chain (tip=%s)\n",
8574 "%s: sending inv peer=%d hash=%s\n",
__func__,
8579 peer->m_blocks_for_headers_relay.clear();
8586 std::vector<CInv>
vInv;
8588 vInv.emplace_back(type, hash);
8600 LOCK(peer->m_block_inv_mutex);
8602 vInv.reserve(std::max<size_t>(peer->m_blocks_for_inv_relay.size(),
8611 peer->m_blocks_for_inv_relay.clear();
8615 [&](std::chrono::microseconds &next) ->
bool {
8620 if (
pto->IsInboundConn()) {
8634 if (peer->m_proof_relay !=
nullptr) {
8635 LOCK(peer->m_proof_relay->m_proof_inventory_mutex);
8638 peer->m_proof_relay->m_next_inv_send_time)) {
8640 peer->m_proof_relay->m_proof_inventory_to_send.begin();
8642 peer->m_proof_relay->m_proof_inventory_to_send.end()) {
8645 it = peer->m_proof_relay->m_proof_inventory_to_send.erase(
8648 if (peer->m_proof_relay->m_proof_inventory_known_filter
8649 .contains(proofid)) {
8653 peer->m_proof_relay->m_proof_inventory_known_filter.insert(
8656 peer->m_proof_relay->m_recently_announced_proofs.insert(
8662 if (
auto tx_relay = peer->GetTxRelay()) {
8673 tx_relay->m_tx_inventory_to_send.clear();
8682 tx_relay->m_fee_filter_received.load()};
8688 tx_relay->m_tx_inventory_to_send.erase(txid);
8695 !
tx_relay->m_bloom_filter->IsRelevantAndUpdate(
8699 tx_relay->m_tx_inventory_known_filter.insert(txid);
8705 std::chrono::duration_cast<std::chrono::seconds>(
8712 std::vector<std::set<TxId>::iterator>
vInvTx;
8714 for (std::set<TxId>::iterator it =
8715 tx_relay->m_tx_inventory_to_send.begin();
8716 it !=
tx_relay->m_tx_inventory_to_send.end(); it++) {
8720 tx_relay->m_fee_filter_received.load()};
8733 while (!
vInvTx.empty() &&
8740 std::set<TxId>::iterator it =
vInvTx.back();
8742 const TxId txid = *it;
8744 tx_relay->m_tx_inventory_to_send.erase(it);
8746 if (
tx_relay->m_tx_inventory_known_filter.contains(txid)) {
8760 !
tx_relay->m_bloom_filter->IsRelevantAndUpdate(
8765 tx_relay->m_recently_announced_invs.insert(txid);
8778 std::make_pair(txid, std::move(
txinfo.tx)));
8784 tx_relay->m_tx_inventory_known_filter.insert(txid);
8790 if (!
vInv.empty()) {
8797 CNodeState &state = *State(
pto->GetId());
8801 if (state.m_stalling_since.count() &&
8807 LogPrintf(
"Peer=%d is stalling block download, disconnecting\n",
8809 pto->fDisconnect =
true;
8815 m_block_stalling_timeout.compare_exchange_strong(
8819 "Increased stalling timeout temporarily to %d seconds\n",
8831 if (state.vBlocksInFlight.size() > 0) {
8832 QueuedBlock &
queuedBlock = state.vBlocksInFlight.front();
8836 state.m_downloading_since +
8837 std::chrono::seconds{consensusParams.nPowTargetSpacing} *
8841 LogPrintf(
"Timeout downloading block %s from peer=%d, "
8845 pto->fDisconnect =
true;
8851 if (state.fSyncStarted &&
8852 peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
8858 state.fPreferredDownload >=
8867 LogPrintf(
"Timeout downloading headers from peer=%d, "
8870 pto->fDisconnect =
true;
8873 LogPrintf(
"Timeout downloading headers from noban "
8874 "peer=%d, not disconnecting\n",
8880 state.fSyncStarted =
false;
8882 peer->m_headers_sync_timeout = 0
us;
8888 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
8905 CNodeState &state = *State(
pto->GetId());
8915 state.vBlocksInFlight.size(),
8924 if (state.vBlocksInFlight.empty() &&
staller != -1) {
8925 if (State(
staller)->m_stalling_since == 0
us) {
8949 LOCK(cs_proofrequest);
8950 std::vector<std::pair<NodeId, avalanche::ProofId>>
expired;
8953 for (
const auto &entry :
expired) {
8955 "timeout of inflight proof %s from peer=%d\n",
8956 entry.second.ToString(), entry.first);
8962 pto->GetId(), proofid,
8979 std::vector<std::pair<NodeId, TxId>>
expired;
8982 for (
const auto &entry :
expired) {
8984 entry.second.ToString(), entry.first);
9013bool PeerManagerImpl::ReceivedAvalancheProof(
CNode &
node, Peer &peer,
9015 assert(proof !=
nullptr);
9031 return node.m_avalanche_pubkey.has_value());
9034 const NodeId nodeid) ->
bool {
9038 return pm.saveRemoteProof(proofid, nodeid,
true);
9046 LOCK(cs_proofrequest);
9061 return pm.registerProof(proof, state);
9064 RelayProof(proofid);
9069 nodeid, proofid.ToString());
9091 "Not polling the avalanche proof (%s): peer=%d, proofid %s\n",
9092 state.
IsValid() ?
"not-worth-polling"
9093 : state.GetRejectReason(),
9099 if (
isStaker && m_opts.avalanche_staking_preconsensus) {
bool MoneyRange(const Amount nValue)
static constexpr Amount MAX_MONEY
No amount larger than this (in satoshi) is valid.
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
@ CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ SCRIPTS
Scripts & signatures ok.
@ TREE
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
arith_uint256 GetBlockProof(const CBlockIndex &block)
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
void Good(const CService &addr, bool test_before_evict=true, NodeSeconds time=Now< NodeSeconds >())
Mark an entry as accessible, possibly moving it from "new" to "tried".
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
void Discourage(const CNetAddr &net_addr)
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool 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.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< uint32_t > indices
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
NodeSeconds nTime
Always included in serialization, except in the network format on INIT_PROTO_VERSION.
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool IsValid(enum BlockValidity nUpTo=BlockValidity::TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveTxsDownloaded() const
Check whether this block's and all previous blocks' transactions have been downloaded (and stored to ...
int64_t GetBlockTime() const
unsigned int nTx
Number of transactions in this block.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
BlockHash GetBlockHash() const
int nHeight
height of the entry in the chain. The genesis block has height 0
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const CBlock & GenesisBlock() const
const Consensus::Params & GetConsensus() const
void ForEachNode(const NodeFn &func)
bool OutboundTargetReached(bool historicalBlockServingLimit) const
check if the outbound target is reached.
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool GetTryNewOutboundPeer() const
void SetTryNewOutboundPeer(bool flag)
unsigned int GetReceiveFloodSize() const
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
void StartExtraBlockRelayPeers()
bool DisconnectNode(const std::string &node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network) const
Return all or many randomly selected addresses, optionally by network.
bool CheckIncomingNonce(uint64_t nonce)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
void PushMessage(CNode *pnode, CSerializedNetMsg &&msg)
bool GetUseAddrmanOutgoing() const
Double ended buffer combining vector and stream-like interfaces.
const_iterator begin() const
Fee rate in satoshis per kilobyte: Amount / kB.
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Reads data from an underlying stream, while hashing the read data.
Inv(ventory) message data.
Used to create a Merkle proof (usually from a subset of transactions), which consists of a block head...
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
CSerializedNetMsg Make(int nFlags, std::string msg_type, Args &&...args) const
Information about a peer.
bool IsFeelerConn() const
bool HasPermission(NetPermissionFlags permission) const
bool IsBlockOnlyConn() const
An encapsulated public key.
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Predicate p, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat p until it return false.
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
A combination of a network address (CNetAddr) and a (TCP) port.
std::vector< uint8_t > GetKey() const
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxIn > vin
An input of a transaction.
std::set< std::reference_wrapper< const CTxMemPoolEntryRef >, CompareIteratorById > Parents
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs)
void RemoveUnbroadcastTx(const TxId &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
CFeeRate GetMinFee() const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
bool CompareTopologically(const TxId &txida, const TxId &txidb) const
TxMempoolInfo info(const TxId &txid) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
bool setAvalancheFinalized(const CTxMemPoolEntryRef &tx) EXCLUSIVE_LOCKS_REQUIRED(cs)
CTransactionRef GetConflictTx(const COutPoint &prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Get the transaction in the pool that spends the same prevout.
bool exists(const TxId &txid) const
std::set< TxId > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
auto withOrphanage(Callable &&func) const EXCLUSIVE_LOCKS_REQUIRED(!cs_orphanage)
const CFeeRate m_min_relay_feerate
auto withConflicting(Callable &&func) const EXCLUSIVE_LOCKS_REQUIRED(!cs_conflicting)
void removeForFinalizedBlock(const std::vector< CTransactionRef > &vtx) EXCLUSIVE_LOCKS_REQUIRED(cs)
unsigned long size() const
std::optional< txiter > GetIter(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given txid, if found.
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void BlockConnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block, avalanche::Processor *const avalanche=nullptr) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
SnapshotCompletionResult MaybeCompleteSnapshotValidation(std::function< void(bilingual_str)> shutdown_fnc=[](bilingual_str msg) { AbortNode(msg.original, msg);}) EXCLUSIVE_LOCKS_REQUIRED(Chainstate & ActiveChainstate() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
bool ProcessNewBlockHeaders(const std::vector< CBlockHeader > &block, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr, const std::optional< CCheckpointData > &test_checkpoints=std::nullopt) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
const arith_uint256 & MinimumChainWork() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
Check to see if caches are out of balance and if so, call ResizeCoinsCaches() as needed.
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
virtual uint64_t GetMaxBlockSize() const =0
A writer stream (for serialization) that computes a 256-bit hash.
Interface for message handling.
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
virtual bool ProcessMessages(const Config &config, CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual bool SendMessages(const Config &config, CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void InitializeNode(const Config &config, CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state, queue any initial messages)
virtual void FinalizeNode(const Config &config, const CNode &node)=0
Handle removal of a peer (clear state)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< TxHash, CTransactionRef > > &extra_txn)
bool IsTxAvailable(size_t index) const
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
virtual std::optional< std::string > FetchBlock(const Config &config, NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual void SendPings()=0
Send ping message to all peers.
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, avalanche::Processor *const avalanche, Options opts)
virtual void ProcessMessage(const Config &config, CNode &pfrom, const std::string &msg_type, CDataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
virtual bool IgnoresIncomingTxs()=0
Whether this node ignores txs received over p2p.
virtual void UnitTestMisbehaving(const NodeId peer_id, const int howmuch)=0
Public for unit testing.
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests....
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
std::string GetRejectReason() const
std::string ToString() const
256-bit unsigned big integer.
ProofId getProofId() const
bool verify(DelegationState &state, CPubKey &auth) const
const DelegationId & getId() const
const LimitedProofId & getLimitedProofId() const
void sendResponse(CNode *pfrom, Response response) const
bool addToReconcile(const AnyVoteItem &item) EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
int64_t getAvaproofsNodeCounter() const
bool registerVotes(NodeId nodeid, const Response &response, std::vector< VoteItemUpdate > &updates, int &banscore, std::string &error) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
bool sendHello(CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
Send a avahello message.
bool isQuorumEstablished() LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
const bool m_preConsensus
ProofRef getLocalProof() const
void addStakeContender(const ProofRef &proof) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Track votes on stake contenders.
bool reconcileOrFinalize(const ProofRef &proof) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Wrapper around the addToReconcile for proofs that adds back the finalization flag to the peer if it i...
void sendDelayedAvahello() EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
auto withPeerManager(Callable &&func) const EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
int getStakeContenderStatus(const StakeContenderId &contenderId) const EXCLUSIVE_LOCKS_REQUIRED(!cs_stakeContenderCache
void avaproofsSent(NodeId nodeid) LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
std::vector< uint32_t > indices
std::string ToString() const
std::string GetHex() const
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool LoadingBlocks() const
bool IsPruneMode() const
Whether running in -prune mode.
static const uint256 ZERO
@ BLOCK_CHECKPOINT
the block failed to meet one of our checkpoints
@ BLOCK_HEADER_LOW_WORK
the block header may be on a too-little-work chain
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ BLOCK_RESULT_UNSET
initial value. Block has not yet been rejected
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_CHILD_BEFORE_PARENT
This tx outputs are already spent in the mempool.
@ TX_MEMPOOL_POLICY
violated mempool's fee/size/descendant/etc limits
@ TX_PACKAGE_RECONSIDERABLE
fails some policy, but might be acceptable if submitted in a (different) package
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_PREMATURE_SPEND
transaction spends a coinbase too early, or violates locktime/sequence locks
@ TX_DUPLICATE
Tx already in mempool or in the chain.
@ TX_INPUTS_NOT_STANDARD
inputs failed policy rules
@ TX_CONFLICT
Tx conflicts with a finalized tx, i.e.
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
@ TX_AVALANCHE_RECONSIDERABLE
fails some policy, but might be reconsidered by avalanche voting
@ TX_NO_MEMPOOL
this node does not have a mempool so can't validate the transaction
@ TX_RESULT_UNSET
initial value. Tx has not yet been rejected
@ TX_CONSENSUS
invalid by consensus rules
static size_t RecursiveDynamicUsage(const CScript &script)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
std::array< uint8_t, CPubKey::SCHNORR_SIZE > SchnorrSig
a Schnorr signature
bool error(const char *fmt, const Args &...args)
#define LogPrint(category,...)
const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
const char * AVAPROOFSREQ
Request for missing avalanche proofs after an avaproofs message has been processed.
const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
const char * BLOCK
The block message transmits a single serialized block.
const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
const char * AVAPROOFS
The avaproofs message the proof short ids of all the valid proofs that we know.
const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
const char * GETAVAPROOFS
The getavaproofs message requests an avaproofs message that provides the proof short ids of all the v...
const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
const char * GETAVAADDR
The getavaaddr message requests an addr message from the receiving node, containing IP addresses of t...
const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
const char * TX
The tx message transmits a single transaction.
const char * AVAHELLO
Contains a delegation and a signature.
const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
const char * AVARESPONSE
Contains an avalanche::Response.
const char * GETDATA
The getdata message requests one or more data objects from another node.
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
const char * BLOCKTXN
Contains a BlockTransactions.
const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
const char * AVAPOLL
Contains an avalanche::Poll.
const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
const char * AVAPROOF
Contains an avalanche::Proof.
const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
ShortIdProcessor< PrefilledProof, ShortIdProcessorPrefilledProofAdapter, ProofRefCompare > ProofShortIdProcessor
std::variant< const ProofRef, const CBlockIndex *, const CTransactionRef > AnyVoteItem
RCUPtr< const Proof > ProofRef
Implement std::hash so RCUPtr can be used as a key for maps or sets.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::function< void(const CAddress &addr, const std::string &msg_type, Span< const uint8_t > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
std::string ConnectionTypeAsString(ConnectionType conn_type)
Convert ConnectionType enum to a string value.
std::string userAgent(const Config &config)
bool IsReachable(enum Network net)
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
@ BypassProofRequestLimits
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto GETAVAADDR_INTERVAL
Minimum time between 2 successives getavaaddr messages from the same peer.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Verify that INVENTORY_MAX_RECENT_RELAY is enough to cache everything typically relayed before uncondi...
static constexpr unsigned int INVENTORY_BROADCAST_MAX_PER_MB
Maximum number of inventory items to send per transmission.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static uint32_t getAvalancheVoteForProof(const avalanche::Processor &avalanche, const avalanche::ProofId &id)
Decide a response for an Avalanche poll about the given proof.
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static const int MAX_NUM_UNCONNECTING_HEADERS_MSGS
Maximum number of unconnecting headers announcements before DoS score.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto RELAY_TX_CACHE_TIME
How long to cache transactions in mapRelay for normal relay.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
bool IsAvalancheMessageType(const std::string &msg_type)
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/behind headers chain.
static std::chrono::microseconds ComputeRequestTime(const CNode &node, const InvRequestTracker< InvId > &requestTracker, const DataRequestParameters &requestParams, std::chrono::microseconds current_time, bool preferred)
Compute the request time for this announcement, current time plus delays for:
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr DataRequestParameters TX_REQUEST_PARAMS
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto AVALANCHE_AVAPROOFS_TIMEOUT
If no proof was requested from a compact proof message after this timeout expired,...
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr unsigned int INVENTORY_MAX_RECENT_RELAY
The number of most recently announced transactions a peer can request.
static constexpr auto UNCONDITIONAL_RELAY_DELAY
How long a transaction has to be in the mempool before it can unconditionally be relayed (even when n...
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static constexpr DataRequestParameters PROOF_REQUEST_PARAMS
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static bool TooManyAnnouncements(const CNode &node, const InvRequestTracker< InvId > &requestTracker, const DataRequestParameters &requestParams)
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
static const int DISCOURAGEMENT_THRESHOLD
Threshold for marking a node to be discouraged, e.g.
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
static constexpr int ADDRV2_FORMAT
A flag that is ORed into the protocol version to designate that addresses should be serialized in (un...
bool IsProxy(const CNetAddr &addr)
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
uint256 GetPackageHash(const Package &package)
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
static constexpr Amount DEFAULT_MIN_RELAY_TX_FEE_PER_KB(1000 *SATOSHI)
Default for -minrelaytxfee, minimum relay fee for transactions.
std::shared_ptr< const CTransaction > CTransactionRef
static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
void SetServiceFlagsIBDCache(bool state)
Set the current IBD status in order to figure out the desirable service flags.
ServiceFlags GetDesirableServiceFlags(ServiceFlags services)
Gets the set of service flags which are "desirable" for a given peer.
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH
Maximum length of incoming protocol messages (Currently 2MB).
static bool HasAllDesirableServiceFlags(ServiceFlags services)
A shortcut for (services & GetDesirableServiceFlags(services)) == GetDesirableServiceFlags(services),...
@ MSG_AVA_STAKE_CONTENDER
@ MSG_CMPCT_BLOCK
Defined in BIP152.
ServiceFlags
nServices flags.
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval)
Return a timestamp in the future sampled from an exponential distribution (https://en....
constexpr auto GetRandMillis
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
reverse_range< T > reverse_iterate(T &x)
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
static std::string ToString(const CService &ip)
void Unserialize(Stream &, char)=delete
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the Span constructor, but for (const) uint8_t member types only.
static const double AVALANCHE_STATISTICS_DECAY_FACTOR
Pre-computed decay factor for the avalanche statistics computation.
static constexpr std::chrono::minutes AVALANCHE_STATISTICS_REFRESH_PERIOD
Refresh period for the avalanche statistics computation.
static constexpr Amount zero() noexcept
A BlockHash is a unqiue identifier for a block.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::chrono::microseconds m_ping_wait
Amount m_fee_filter_received
std::vector< int > vHeightInFlight
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
std::vector< uint8_t > data
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
const std::chrono::seconds overloaded_peer_delay
How long to delay requesting data from overloaded peers (see max_peer_request_in_flight).
const size_t max_peer_announcements
Maximum number of inventories to consider for requesting, per peer.
const std::chrono::seconds nonpref_peer_delay
How long to delay requesting data from non-preferred peers.
const NetPermissionFlags bypass_request_limits_permissions
Permission flags a peer requires to bypass the request limits tracking limits and delay penalty.
const std::chrono::microseconds getdata_interval
How long to wait (in microseconds) before a data request from an additional peer.
const size_t max_peer_request_in_flight
Maximum number of in-flight data requests from a peer.
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const TxValidationState m_state
Contains information about why the transaction failed.
@ MEMPOOL_ENTRY
Valid, transaction was already in the mempool.
@ VALID
Fully validated, valid.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
Validation result for package mempool acceptance.
This is a radix tree storing values identified by a unique key.
A TxId is the identifier of a transaction.
std::chrono::seconds registration_time
const ProofId & getProofId() const
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define AssertLockHeld(cs)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
#define NO_THREAD_SAFETY_ANALYSIS
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
constexpr int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
double CountSecondsDouble(SecondsDouble t)
Helper to count the seconds in any std::chrono::duration type.
NodeClock::time_point GetAdjustedTime()
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
#define TRACE6(context, event, a, b, c, d, e, f)
@ AVALANCHE
Removed by avalanche vote.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
arith_uint256 CalculateHeadersWork(const std::vector< CBlockHeader > &headers)
Return the sum of the work on a given set of headers.
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept)
Validate (and maybe submit) a package to the mempool.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...
CMainSignals & GetMainSignals()
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.