Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
501};503struct InvToSendBucket {504const double count_floor{0};505std::vector<Wtxid> backlog;506util::TokenBucket<NodeClock> size_bucket;507util::TokenBucket<NodeClock> count_bucket;509/* Initialization rationale:510*511* Count bucket: Fills at rate*mult, total/initial capacity of 30s with mult=1512* Size bucket: Fills at 12MB every 600s, times mult so expected to be 6 times513* the rate at which blocks can confirm transactions, but at least 3 times that in514* the worst case. High limit to avoid triggering even with large spikes, but a515* modest initial value to ensure that frequent node restarts don't raise the limit516* too much.517* Count floor: In order to avoid sorting the global backlog too often, we ensure518* that we always remove at least an average INV message's number of transactions519* each time we do work. (Or 50kB if the size bucket is the limiting factor)520*/522static constexpr double SIZE_INIT{12'000'000}; // 12 MB initially523static constexpr double SIZE_CAP{50'000'000}; // 50 MB maximum524static constexpr double SIZE_REFILL{20'000}; // 20kB/s = 12MB/600s526static constexpr double INBOUND_COUNT_SECONDS{30}; // cap/initial at 30s/mult worth of txs528InvToSendBucket(unsigned int rate, double mult)529: count_floor{-1.0 * rate * count_seconds(INBOUND_INVENTORY_BROADCAST_INTERVAL)},530size_bucket(/*rate=*/SIZE_REFILL * mult, /*value=*/SIZE_INIT, /*cap=*/SIZE_CAP),531count_bucket(/*rate=*/rate * mult, /*value=*/rate * INBOUND_COUNT_SECONDS, /*cap=*/rate * INBOUND_COUNT_SECONDS)532{533}535bool avail() const536{537return !backlog.empty() && size_bucket.value() > 0 && count_bucket.value() > 0;538}540void increment(NodeClock::time_point now)541{542size_bucket.increment(now);543count_bucket.increment(now);544}546std::vector<Wtxid> TakeForProcessing(CTxMemPool& mempool) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);548bool decrement(double size)549{550bool size_ok = size_bucket.decrement(size, /*floor=*/-50e3);551bool count_ok = count_bucket.decrement(1, /*floor=*/count_floor);552return size_ok && count_ok;553}555PeerManagerInfo::InvBucketInfo info() const556{557return {558.backlog_count = backlog.size(),559.count_bucket = count_bucket.value(),560.size_bucket = size_bucket.value(),561};562}563};565class PeerManagerImpl final : public PeerManager566{567public:568PeerManagerImpl(CConnman& connman, AddrMan& addrman,569BanMan* banman, ChainstateManager& chainman,570CTxMemPool& pool, node::Warnings& warnings, Options opts);572/** Overridden from CValidationInterface. */573void ActiveTipChange(const CBlockIndex& new_tip, bool) override574EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);575void BlockConnected(const ChainstateRole& role, const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override576EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);577void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex) override578EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);579void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override580EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);581void BlockChecked(const std::shared_ptr<const CBlock>& block, const BlockValidationState& state) override582EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);583void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) override584EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex);586/** Implement NetEventsInterface */587void InitializeNode(const CNode& node, ServiceFlags our_services) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_tx_download_mutex);588void FinalizeNode(const CNode& node) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex, !m_tx_download_mutex);589bool HasAllDesirableServiceFlags(ServiceFlags services) const override;590bool ProcessMessages(CNode& node, std::atomic<bool>& interrupt) override591EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex, !m_inv_to_send_mutex);592bool SendMessages(CNode& node) override593EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, g_msgproc_mutex, !m_tx_download_mutex, !m_inv_to_send_mutex);595/** Implement PeerManager */596void StartScheduledTasks(CScheduler& scheduler) override;597void CheckForStaleTipAndEvictPeers() override;598util::Expected<void, std::string> FetchBlock(NodeId peer_id, const CBlockIndex& block_index) override599EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);600bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);601std::vector<node::TxOrphanage::OrphanInfo> GetOrphanTransactions() override EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);602PeerManagerInfo GetInfo() const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_inv_to_send_mutex);603std::vector<PrivateBroadcast::TxBroadcastInfo> GetPrivateBroadcastInfo() const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);604std::vector<CTransactionRef> AbortPrivateBroadcast(const uint256& id) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);605void SendPings() override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);606void InitiateTxBroadcastToAll(const Wtxid& wtxid) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_inv_to_send_mutex);607node::TransactionError InitiateTxBroadcastPrivate(const CTransactionRef& tx) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);608void SetBestBlock(int height, std::chrono::seconds time) override609{610m_best_height = height;611m_best_block_time = time;612};613void UnitTestMisbehaving(NodeId peer_id) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex) { Misbehaving(*Assert(GetPeerRef(peer_id)), ""); };614void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds) override;615ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const override;617private:618void ProcessMessage(Peer& peer, CNode& pfrom, const std::string& msg_type, DataStream& vRecv, NodeClock::time_point time_received,619const std::atomic<bool>& interruptMsgProc)620EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex, !m_tx_download_mutex, !m_inv_to_send_mutex);622/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */623void ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_msgproc_mutex);625/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */626void EvictExtraOutboundPeers(NodeClock::time_point now) EXCLUSIVE_LOCKS_REQUIRED(cs_main);628/** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */629void ReattemptInitialBroadcast(CScheduler& scheduler) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_inv_to_send_mutex);631/** Rebroadcast stale private transactions (already broadcast but not received back from the network). */632void ReattemptPrivateBroadcast(CScheduler& scheduler);634/** Get a shared pointer to the Peer object.635* May return an empty shared_ptr if the Peer object can't be found. */636PeerRef GetPeerRef(NodeId id) const EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);638/** Get a shared pointer to the Peer object and remove it from m_peer_map.639* May return an empty shared_ptr if the Peer object can't be found. */640PeerRef RemovePeer(NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);642/// Get all existing peers in m_peer_map.643std::vector<PeerRef> GetAllPeers() const EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);645/** Mark a peer as misbehaving, which will cause it to be disconnected and its646* address discouraged. */647void Misbehaving(Peer& peer, const std::string& message);649/**650* Potentially mark a node discouraged based on the contents of a BlockValidationState object651*652* @param[in] via_compact_block this bool is passed in because net_processing should653* punish peers differently depending on whether the data was provided in a compact654* block message or not. If the compact block had a valid header, but contained invalid655* txs, the peer should not be punished. See BIP 152.656*/657void MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,658bool via_compact_block, const std::string& message = "")659EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);661/** Maybe disconnect a peer and discourage future connections from its address.662*663* @param[in] pnode The node to check.664* @param[in] peer The peer object to check.665* @return True if the peer was marked for disconnection in this function666*/667bool MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer);669/** If an inbound peer wants tx relay and we are at capacity for those, attempt to670* evict a tx-relaying inbound peer - possibly node itself, unless it is protected.671* Only if no peer can be evicted, disconnect node.672*673* @param[in] node The node that wants to relay txs to us.674* @param[in] msg_type The message that triggered this check, for logging.675* @param[in] protect_peer Peer that is exempt from being evicted.676* @return True if the node was disconnected because no eviction candidate677* was found. If false is returned, a non-protected node may still have678* been marked for disconnection via regular eviction.679*/680bool MaybeDisconnectForTxRelayCapacity(CNode& node, const std::string& msg_type,681std::optional<NodeId> protect_peer = std::nullopt);683/** Handle a transaction whose result was not MempoolAcceptResult::ResultType::VALID.684* @param[in] first_time_failure Whether we should consider inserting into vExtraTxnForCompact, adding685* a new orphan to resolve, or looking for a package to submit.686* Set to true for transactions just received over p2p.687* Set to false if the tx has already been rejected before,688* e.g. is already in the orphanage, to avoid adding duplicate entries.689* Updates m_txrequest, m_lazy_recent_rejects, m_lazy_recent_rejects_reconsiderable, m_orphanage, and vExtraTxnForCompact.690*691* @returns a PackageToValidate if this transaction has a reconsiderable failure and an eligible package was found,692* or std::nullopt otherwise.693*/694std::optional<node::PackageToValidate> ProcessInvalidTx(NodeId nodeid, const CTransactionRef& tx, const TxValidationState& result,695bool first_time_failure)696EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, m_tx_download_mutex);698/** Handle a transaction whose result was MempoolAcceptResult::ResultType::VALID.699* Updates m_txrequest, m_orphanage, and vExtraTxnForCompact. Also queues the tx for relay. */700void ProcessValidTx(NodeId nodeid, const CTransactionRef& tx, const std::list<CTransactionRef>& replaced_transactions)701EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, m_tx_download_mutex, !m_inv_to_send_mutex);703/** Handle the results of package validation: calls ProcessValidTx and ProcessInvalidTx for704* individual transactions, and caches rejection for the package as a group.705*/706void ProcessPackageResult(const node::PackageToValidate& package_to_validate, const PackageMempoolAcceptResult& package_result)707EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, m_tx_download_mutex, !m_inv_to_send_mutex);709/**710* Reconsider orphan transactions after a parent has been accepted to the mempool.711*712* @peer[in] peer The peer whose orphan transactions we will reconsider. Generally only713* one orphan will be reconsidered on each call of this function. If an714* accepted orphan has orphaned children, those will need to be715* reconsidered, creating more work, possibly for other peers.716* @return True if meaningful work was done (an orphan was accepted/rejected).717* If no meaningful work was done, then the work set for this peer718* will be empty.719*/720bool ProcessOrphanTx(Peer& peer)721EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, !m_tx_download_mutex, !m_inv_to_send_mutex);723/** Process a single headers message from a peer.724*725* @param[in] pfrom CNode of the peer726* @param[in] peer The peer sending us the headers727* @param[in] headers The headers received. Note that this may be modified within ProcessHeadersMessage.728* @param[in] via_compact_block Whether this header came in via compact block handling.729*/730void ProcessHeadersMessage(CNode& pfrom, Peer& peer,731std::vector<CBlockHeader>&& headers,732bool via_compact_block)733EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex, g_msgproc_mutex);734/** Various helpers for headers processing, invoked by ProcessHeadersMessage() */735/** Return true if headers are continuous and have valid proof-of-work (DoS points assigned on failure) */736bool CheckHeadersPoW(const std::vector<CBlockHeader>& headers, Peer& peer);737/** Calculate an anti-DoS work threshold for headers chains */738arith_uint256 GetAntiDoSWorkThreshold();739/** Deal with state tracking and headers sync for peers that send740* non-connecting headers (this can happen due to BIP 130 headers741* announcements for blocks interacting with the 2hr (MAX_FUTURE_BLOCK_TIME) rule). */742void HandleUnconnectingHeaders(CNode& pfrom, Peer& peer, const std::vector<CBlockHeader>& headers) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);743/** Return true if the headers connect to each other, false otherwise */744bool CheckHeadersAreContinuous(const std::vector<CBlockHeader>& headers) const;745/** Try to continue a low-work headers sync that has already begun.746* Assumes the caller has already verified the headers connect, and has747* checked that each header satisfies the proof-of-work target included in748* the header.749* @param[in] peer The peer we're syncing with.750* @param[in] pfrom CNode of the peer