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.
751* @param[in,out] headers The headers to be processed.752* @return True if the passed in headers were successfully processed753* as the continuation of a low-work headers sync in progress;754* false otherwise.755* If false, the passed in headers will be returned back to756* the caller.757* If true, the returned headers may be empty, indicating758* there is no more work for the caller to do; or the headers759* may be populated with entries that have passed anti-DoS760* checks (and therefore may be validated for block index761* acceptance by the caller).762*/763bool IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfrom,764std::vector<CBlockHeader>& headers)765EXCLUSIVE_LOCKS_REQUIRED(peer.m_headers_sync_mutex, !m_headers_presync_mutex, g_msgproc_mutex);766/** Check work on a headers chain to be processed, and if insufficient,767* initiate our anti-DoS headers sync mechanism.768*769* @param[in] peer The peer whose headers we're processing.770* @param[in] pfrom CNode of the peer771* @param[in] chain_start_header Where these headers connect in our index.772* @param[in,out] headers The headers to be processed.773*774* @return True if chain was low work (headers will be empty after775* calling); false otherwise.776*/777bool TryLowWorkHeadersSync(Peer& peer, CNode& pfrom,778const CBlockIndex& chain_start_header,779std::vector<CBlockHeader>& headers)780EXCLUSIVE_LOCKS_REQUIRED(!peer.m_headers_sync_mutex, !m_peer_mutex, !m_headers_presync_mutex, g_msgproc_mutex);782/** Return true if the given header is an ancestor of783* m_chainman.m_best_header or our current tip */784bool IsAncestorOfBestHeaderOrTip(const CBlockIndex* header) EXCLUSIVE_LOCKS_REQUIRED(cs_main);786/** Request further headers from this peer with a given locator.787* We don't issue a getheaders message if we have a recent one outstanding.788* This returns true if a getheaders is actually sent, and false otherwise.789*/790bool MaybeSendGetHeaders(CNode& pfrom, const CBlockLocator& locator, Peer& peer) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);791/** Potentially fetch blocks from this peer upon receipt of a new headers tip */792void HeadersDirectFetchBlocks(CNode& pfrom, const Peer& peer, const CBlockIndex& last_header);793/** Update peer state based on received headers message */794void UpdatePeerStateForReceivedHeaders(CNode& pfrom, const CBlockIndex& last_header, bool received_new_header, bool may_have_more_headers)795EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);797void SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req);799/** Send a message to a peer */800void PushMessage(CNode& node, CSerializedNetMsg&& msg) const { m_connman.PushMessage(&node, std::move(msg)); }801template <typename... Args>802void MakeAndPushMessage(CNode& node, std::string msg_type, Args&&... args) const803{804m_connman.PushMessage(&node, NetMsg::Make(std::move(msg_type), std::forward<Args>(args)...));805}806template <typename... Args>807[[maybe_unused]] void MakeAndPushFeature(CNode& node, std::string_view feature_id, Args&&... args) const808{809if (!Assume(feature_id.size() >= 4 && feature_id.size() <= MAX_FEATUREID_LENGTH)) return;810std::vector<unsigned char> feature_data;811VectorWriter{feature_data, 0, std::forward<Args>(args)...};812if (!Assume(feature_data.size() <= MAX_FEATUREDATA_LENGTH)) return;813MakeAndPushMessage(node, NetMsgType::FEATURE, feature_id, std::move(feature_data));814}816/** Send a version message to a peer */817void PushNodeVersion(CNode& pnode, const Peer& peer);819/** Send a ping message every PING_INTERVAL or if requested via RPC (peer.m_ping_queued is true).820* May mark the peer to be disconnected if a ping has timed out.821* We use mockable time for ping timeouts, so setmocktime may cause pings822* to time out. */823void MaybeSendPing(CNode& node_to, Peer& peer, NodeClock::time_point now);825/** Send `addr` messages on a regular schedule. */826void MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);828/** Send a single `sendheaders` message, after we have completed headers sync with a peer. */829void MaybeSendSendHeaders(CNode& node, Peer& peer) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);831/** Relay (gossip) an address to a few randomly chosen nodes.832*833* @param[in] originator The id of the peer that sent us the address. We don't want to relay it back.834* @param[in] addr Address to relay.835* @param[in] fReachable Whether the address' network is reachable. We relay unreachable836* addresses less.837*/838void RelayAddress(NodeId originator, const CAddress& addr, bool fReachable) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex);840/** Send `feefilter` message. */841void MaybeSendFeefilter(CNode& node, Peer& peer, std::chrono::microseconds current_time) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);843FastRandomContext m_rng GUARDED_BY(NetEventsInterface::g_msgproc_mutex);845/** Copied into short-lived tx INV deduplication sets to avoid generating salts per message. */846const SaltedUint256Hasher m_txhash_hasher;847FeeFilterRounder m_fee_filter_rounder GUARDED_BY(NetEventsInterface::g_msgproc_mutex);849const CChainParams& m_chainparams;850CConnman& m_connman;851AddrMan& m_addrman;852/** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */853BanMan* const m_banman;854ChainstateManager& m_chainman;855CTxMemPool& m_mempool;857/** Synchronizes tx download including TxRequestTracker, rejection filters, and TxOrphanage.858* Lock invariants:859* - A txhash (txid or wtxid) in m_txrequest is not also in m_orphanage.860* - A txhash (txid or wtxid) in m_txrequest is not also in m_lazy_recent_rejects.861* - A txhash (txid or wtxid) in m_txrequest is not also in m_lazy_recent_rejects_reconsiderable.862* - A txhash (txid or wtxid) in m_txrequest is not also in m_lazy_recent_confirmed_transactions.863* - Each data structure's limits hold (m_orphanage max size, m_txrequest per-peer limits, etc).864*/865Mutex m_tx_download_mutex ACQUIRED_BEFORE(m_mempool.cs);866node::TxDownloadManager m_txdownloadman GUARDED_BY(m_tx_download_mutex);868std::unique_ptr<TxReconciliationTracker> m_txreconciliation;870/** The height of the best chain */871std::atomic<int> m_best_height{-1};872/** The time of the best chain tip block */873std::atomic<std::chrono::seconds> m_best_block_time{0s};875/** Next time to check for stale tip */876std::chrono::seconds m_stale_tip_check_time GUARDED_BY(cs_main){0s};878node::Warnings& m_warnings;879TimeOffsets m_outbound_time_offsets{m_warnings};881const Options m_opts;883bool RejectIncomingTxs(const CNode& peer) const;885/** Whether we've completed initial sync yet, for determining when to turn886* on extra block-relay-only peers. */887bool m_initial_sync_finished GUARDED_BY(cs_main){false};889/** Protects m_peer_map. This mutex must not be locked while holding a lock890* on any of the mutexes inside a Peer object. */891mutable Mutex m_peer_mutex;892/**893* Map of all Peer objects, keyed by peer id. This map is protected894* by the m_peer_mutex. Once a shared pointer reference is895* taken, the lock may be released. Individual fields are protected by896* their own locks.897*/898std::map<NodeId, PeerRef> m_peer_map GUARDED_BY(m_peer_mutex);900/** Map maintaining per-node state. */901std::map<NodeId, CNodeState> m_node_states GUARDED_BY(cs_main);903/** Get a pointer to a const CNodeState, used when not mutating the CNodeState object. */904const CNodeState* State(NodeId pnode) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);905/** Get a pointer to a mutable CNodeState. */906CNodeState* State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main);908uint32_t GetFetchFlags(const Peer& peer) const;910std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key GUARDED_BY(g_msgproc_mutex);912/** Number of nodes with fSyncStarted. */913int nSyncStarted GUARDED_BY(cs_main) = 0;915/** Hash of the last block we received via INV */916uint256 m_last_block_inv_triggering_headers_sync GUARDED_BY(g_msgproc_mutex){};918/**919* Sources of received blocks, saved to be able punish them when processing920* happens afterwards.921* Set mapBlockSource[hash].second to false if the node should not be922* punished if the block is invalid.923*/924std::map<uint256, std::pair<NodeId, bool>> mapBlockSource GUARDED_BY(cs_main);926/** Number of peers with wtxid relay. */927std::atomic<int> m_wtxid_relay_peers{0};929/** Number of outbound peers with m_chain_sync.m_protect. */930int m_outbound_peers_with_protect_from_disconnect GUARDED_BY(cs_main) = 0;932/** Number of preferable block download peers. */933int m_num_preferred_download_peers GUARDED_BY(cs_main){0};935/** Stalling timeout for blocks in IBD */936std::atomic<std::chrono::seconds> m_block_stalling_timeout{BLOCK_STALLING_TIMEOUT_DEFAULT};938/**939* For sending `inv`s to inbound peers, we use a single (exponentially940* distributed) timer for all peers with the same network key. If we used a separate timer for each941* peer, a spy node could make multiple inbound connections to us to942* accurately determine when we received a transaction (and potentially943* determine the transaction's origin). Each network key has its own timer944* to make fingerprinting harder. */945std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,946std::chrono::seconds average_interval,947uint64_t network_key) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);950// All of the following cache a recent block, and are protected by m_most_recent_block_mutex951Mutex m_most_recent_block_mutex;952std::shared_ptr<const CBlock> m_most_recent_block GUARDED_BY(m_most_recent_block_mutex);953std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block GUARDED_BY(m_most_recent_block_mutex);954uint256 m_most_recent_block_hash GUARDED_BY(m_most_recent_block_mutex);955std::unique_ptr<const std::map<GenTxid, CTransactionRef>> m_most_recent_block_txs GUARDED_BY(m_most_recent_block_mutex);957// Data about the low-work headers synchronization, aggregated from all peers' HeadersSyncStates.958/** Mutex guarding the other m_headers_presync_* variables. */959Mutex m_headers_presync_mutex;960/** A type to represent statistics about a peer's low-work headers sync.961*962* - The first field is the total verified amount of work in that synchronization.963* - The second is:964* - nullopt: the sync is in REDOWNLOAD phase (phase 2).965* - {height, timestamp}: the sync has the specified tip height and block timestamp (phase 1).966*/967using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;968/** Statistics for all peers in low-work headers sync. */969std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats GUARDED_BY(m_headers_presync_mutex) {};970/** The peer with the most-work entry in m_headers_presync_stats. */971NodeId m_headers_presync_bestpeer GUARDED_BY(m_headers_presync_mutex) {-1};972/** The m_headers_presync_stats improved, and needs signalling. */973std::atomic_bool m_headers_presync_should_signal{false};975/** Height of the highest block announced using BIP 152 high-bandwidth mode. */976int m_highest_fast_announce GUARDED_BY(::cs_main){0};978/** Have we requested this block from a peer */979bool IsBlockRequested(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);981/** Have we requested this block from an outbound peer */982bool IsBlockRequestedFromOutbound(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main, !m_peer_mutex);984/** Remove this block from our tracked requested blocks. Called if:985* - the block has been received from a peer986* - the request for the block has timed out987* If "from_peer" is specified, then only remove the block if it is in988* flight from that peer (to avoid one peer's network traffic from989* affecting another's state).990*/991void RemoveBlockRequest(const uint256& hash, std::optional<NodeId> from_peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);993/* Mark a block as in flight994* Returns false, still setting pit, if the block was already in flight from the same peer995* pit will only be valid as long as the same cs_main lock is being held996*/997bool BlockRequested(NodeId nodeid, const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_main);999bool TipMayBeStale() EXCLUSIVE_LOCKS_REQUIRED(cs_main);