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.
5751// This might be unnecessary if the bloom filter has already rolled5752// over since our last self-announcement, but there is only a small5753// bandwidth cost that we can incur by doing this (which happens5754// once a day on average).5755if (peer.m_next_local_addr_send != 0us) {5756peer.m_addr_known->reset();5757}5758if (std::optional<CService> local_service = GetLocalAddrForPeer(node)) {5759CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};5760if (peer.m_next_local_addr_send == 0us) {5761// Send the initial self-announcement in its own message. This makes sure5762// rate-limiting with limited start-tokens doesn't ignore it if the first5763// message ends up containing multiple addresses.5764if (IsAddrCompatible(peer, local_addr)) {5765std::vector<CAddress> self_announcement{local_addr};5766if (peer.m_wants_addrv2) {5767MakeAndPushMessage(node, NetMsgType::ADDRV2, CAddress::V2_NETWORK(self_announcement));5768} else {5769MakeAndPushMessage(node, NetMsgType::ADDR, CAddress::V1_NETWORK(self_announcement));5770}5771}5772} else {5773// All later self-announcements are sent together with the other addresses.5774PushAddress(peer, local_addr);5775}5776}5777peer.m_next_local_addr_send = current_time + m_rng.rand_exp_duration(AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);5778}5780// We sent an `addr` message to this peer recently. Nothing more to do.5781if (current_time <= peer.m_next_addr_send) return;5783peer.m_next_addr_send = current_time + m_rng.rand_exp_duration(AVG_ADDRESS_BROADCAST_INTERVAL);5785if (!Assume(peer.m_addrs_to_send.size() <= MAX_ADDR_TO_SEND)) {5786// Should be impossible since we always check size before adding to5787// m_addrs_to_send. Recover by trimming the vector.5788peer.m_addrs_to_send.resize(MAX_ADDR_TO_SEND);5789}5791// Remove addr records that the peer already knows about, and add new5792// addrs to the m_addr_known filter on the same pass.5793auto addr_already_known = [&peer](const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex) {5794bool ret = peer.m_addr_known->contains(addr.GetKey());5795if (!ret) peer.m_addr_known->insert(addr.GetKey());5796return ret;5797};5798peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),5799peer.m_addrs_to_send.end());5801// No addr messages to send5802if (peer.m_addrs_to_send.empty()) return;5804if (peer.m_wants_addrv2) {5805MakeAndPushMessage(node, NetMsgType::ADDRV2, CAddress::V2_NETWORK(peer.m_addrs_to_send));5806} else {5807MakeAndPushMessage(node, NetMsgType::ADDR, CAddress::V1_NETWORK(peer.m_addrs_to_send));5808}5809peer.m_addrs_to_send.clear();5811// we only send the big addr message once5812if (peer.m_addrs_to_send.capacity() > 40) {5813peer.m_addrs_to_send.shrink_to_fit();5814}5815}5817void PeerManagerImpl::MaybeSendSendHeaders(CNode& node, Peer& peer)5818{5819// Delay sending SENDHEADERS (BIP 130) until we're done with an5820// initial-headers-sync with this peer. Receiving headers announcements for5821// new blocks while trying to sync their headers chain is problematic,5822// because of the state tracking done.5823if (!peer.m_sent_sendheaders && node.GetCommonVersion() >= SENDHEADERS_VERSION) {5824LOCK(cs_main);5825CNodeState &state = *State(node.GetId());5826if (state.pindexBestKnownBlock != nullptr &&5827state.pindexBestKnownBlock->nChainWork > m_chainman.MinimumChainWork()) {5828// Tell our peer we prefer to receive headers rather than inv's5829// We send this to non-NODE NETWORK peers as well, because even5830// non-NODE NETWORK peers can announce blocks (such as pruning5831// nodes)5832MakeAndPushMessage(node, NetMsgType::SENDHEADERS);5833peer.m_sent_sendheaders = true;5834}5835}5836}5838void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::microseconds current_time)5839{5840if (m_opts.ignore_incoming_txs) return;5841if (pto.GetCommonVersion() < FEEFILTER_VERSION) return;5842// peers with the forcerelay permission should not filter txs to us5843if (pto.HasPermission(NetPermissionFlags::ForceRelay)) return;5844// Don't send feefilter messages to outbound block-relay-only peers since they should never announce5845// transactions to us, regardless of feefilter state.5846if (pto.IsBlockOnlyConn()) return;5848CAmount currentFilter = m_mempool.GetMinFee().GetFeePerK();5850if (m_chainman.IsInitialBlockDownload()) {5851// Received tx-inv messages are discarded when the active5852// chainstate is in IBD, so tell the peer to not send them.5853currentFilter = MAX_MONEY;5854} else {5855static const CAmount MAX_FILTER{m_fee_filter_rounder.round(MAX_MONEY)};5856if (peer.m_fee_filter_sent == MAX_FILTER) {5857// Send the current filter if we sent MAX_FILTER previously5858// and made it out of IBD.5859peer.m_next_send_feefilter = 0us;5860}5861}5862if (current_time > peer.m_next_send_feefilter) {5863CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);5864// We always have a fee filter of at least the min relay fee5865filterToSend = std::max(filterToSend, m_mempool.m_opts.min_relay_feerate.GetFeePerK());5866if (filterToSend != peer.m_fee_filter_sent) {5867MakeAndPushMessage(pto, NetMsgType::FEEFILTER, filterToSend);5868peer.m_fee_filter_sent = filterToSend;5869}5870peer.m_next_send_feefilter = current_time + m_rng.rand_exp_duration(AVG_FEEFILTER_BROADCAST_INTERVAL);5871}5872// If the fee filter has changed substantially and it's still more than MAX_FEEFILTER_CHANGE_DELAY5873// until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY.5874else if (current_time + MAX_FEEFILTER_CHANGE_DELAY < peer.m_next_send_feefilter &&5875(currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {5876peer.m_next_send_feefilter = current_time + m_rng.randrange<std::chrono::microseconds>(MAX_FEEFILTER_CHANGE_DELAY);5877}5878}5880bool PeerManagerImpl::RejectIncomingTxs(const CNode& peer) const5881{5882// block-relay-only peers may never send txs to us5883if (peer.IsBlockOnlyConn()) return true;5884if (peer.IsFeelerConn()) return true;5885// In -blocksonly mode, peers need the 'relay' permission to send txs to us5886if (m_opts.ignore_incoming_txs && !peer.HasPermission(NetPermissionFlags::Relay)) return true;5887return false;5888}5890void PeerManagerImpl::ProcessPong(CNode& pfrom, Peer& peer, const NodeClock::time_point ping_end, DataStream& vRecv)5891{5892uint64_t nonce = 0;5893const size_t nAvail{vRecv.size()};5894bool bPingFinished = false;5895std::string sProblem;5897if (nAvail >= sizeof(nonce)) {5898vRecv >> nonce;5900// Only process pong message if there is an outstanding ping (old ping without nonce should never pong)5901if (peer.m_ping_nonce_sent != 0) {5902if (nonce == peer.m_ping_nonce_sent) {5903// Matching pong received, this ping is no longer outstanding5904bPingFinished = true;5905const auto ping_time = ping_end - peer.m_ping_start.load();5906if (ping_time.count() >= 0) {5907// Let connman know about this successful ping-pong5908pfrom.PongReceived(ping_time);5909if (pfrom.IsPrivateBroadcastConn()) {5910m_tx_for_private_broadcast.NodeConfirmedReception(pfrom.GetId());5911LogDebug(BCLog::PRIVBROADCAST, "Got a PONG (the transaction will probably reach the network), marking for disconnect, %s",5912pfrom.LogPeer());5913pfrom.fDisconnect = true;5914}5915} else {5916// This should never happen5917sProblem = "Timing mishap";5918}5919} else {5920// Nonce mismatches are normal when pings are overlapping5921sProblem = "Nonce mismatch";5922if (nonce == 0) {5923// This is most likely a bug in another implementation somewhere; cancel this ping5924bPingFinished = true;5925sProblem = "Nonce zero";5926}5927}5928} else {5929sProblem = "Unsolicited pong without ping";5930}5931} else {5932// This is most likely a bug in another implementation somewhere; cancel this ping5933bPingFinished = true;5934sProblem = "Short payload";5935}5937if (!(sProblem.empty())) {5938LogDebug(BCLog::NET, "pong peer=%d: %s, %x expected, %x received, %u bytes\n",5939pfrom.GetId(),5940sProblem,5941peer.m_ping_nonce_sent,5942nonce,5943nAvail);5944}5945if (bPingFinished) {5946peer.m_ping_nonce_sent = 0;5947}5948}5950bool PeerManagerImpl::SetupAddressRelay(const CNode& node, Peer& peer)5951{5952// We don't participate in addr relay with outbound block-relay-only5953// connections to prevent providing adversaries with the additional5954// information of addr traffic to infer the link.5955if (node.IsBlockOnlyConn()) return false;5957// We don't participate in addr relay with feeler connections because5958// they are disconnected shortly after the handshake completes,5959// before the node will receive the addr response.5960if (node.IsFeelerConn()) return false;5962if (!peer.m_addr_relay_enabled.exchange(true)) {5963// During version message processing (non-block-relay-only outbound peers)5964// or on first addr-related message we have received (inbound peers), initialize5965// m_addr_known.5966peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);5967}5969return true;5970}5972void PeerManagerImpl::ProcessAddrs(std::string_view msg_type, CNode& pfrom, Peer& peer, std::vector<CAddress>&& vAddr, const std::atomic<bool>& interruptMsgProc)5973{5974AssertLockNotHeld(m_peer_mutex);5975AssertLockHeld(g_msgproc_mutex);5977if (!SetupAddressRelay(pfrom, peer)) {5978LogDebug(BCLog::NET, "ignoring %s message from %s peer=%d\n", msg_type, pfrom.ConnectionTypeAsString(), pfrom.GetId());5979return;5980}5982if (vAddr.size() > MAX_ADDR_TO_SEND)5983{5984Misbehaving(peer, strprintf("%s message size = %u", msg_type, vAddr.size()));5985return;5986}5988// Store the new addresses5989std::vector<CAddress> vAddrOk;5991// Update/increment addr rate limiting bucket.5992const auto current_time{NodeClock::now()};5993if (peer.m_addr_token_bucket < MAX_ADDR_PROCESSING_TOKEN_BUCKET) {5994// Don't increment bucket if it's already full5995const auto time_diff{current_time - peer.m_addr_token_timestamp};5996const double increment{std::max(Ticks<SecondsDouble>(time_diff), 0.0) * MAX_ADDR_RATE_PER_SECOND};5997peer.m_addr_token_bucket = std::min<double>(peer.m_addr_token_bucket + increment, MAX_ADDR_PROCESSING_TOKEN_BUCKET);5998}5999peer.m_addr_token_timestamp = current_time;