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.
5001}5002}5003} // cs_main5005if (fProcessBLOCKTXN) {5006BlockTransactions txn;5007txn.blockhash = blockhash;5008return ProcessCompactBlockTxns(pfrom, peer, txn);5009}5011if (fRevertToHeaderProcessing) {5012// Headers received from HB compact block peers are permitted to be5013// relayed before full validation (see BIP 152), so we don't want to disconnect5014// the peer if the header turns out to be for an invalid block.5015// Note that if a peer tries to build on an invalid chain, that5016// will be detected and the peer will be disconnected/discouraged.5017return ProcessHeadersMessage(pfrom, peer, {cmpctblock.header}, /*via_compact_block=*/true);5018}5020if (fBlockReconstructed) {5021// If we got here, we were able to optimistically reconstruct a5022// block that is in flight from some other peer.5023{5024LOCK(cs_main);5025mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.GetId(), false));5026}5027// Setting force_processing to true means that we bypass some of5028// our anti-DoS protections in AcceptBlock, which filters5029// unrequested blocks that might be trying to waste our resources5030// (eg disk space). Because we only try to reconstruct blocks when5031// we're close to caught up (via the CanDirectFetch() requirement5032// above, combined with the behavior of not requesting blocks until5033// we have a chain with at least the minimum chain work), and we ignore5034// compact blocks with less work than our tip, it is safe to treat5035// reconstructed compact blocks as having been requested.5036ProcessBlock(pfrom, pblock, /*force_processing=*/true, /*min_pow_checked=*/true);5037LOCK(cs_main); // hold cs_main for CBlockIndex::IsValid()5038if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS)) {5039// Clear download state for this block, which is in5040// process from some other peer. We do this after calling5041// ProcessNewBlock so that a malleated cmpctblock announcement5042// can't be used to interfere with block relay.5043RemoveBlockRequest(pblock->GetHash(), std::nullopt);5044}5045}5046return;5047}5049if (msg_type == NetMsgType::BLOCKTXN)5050{5051// Ignore blocktxn received while importing5052if (m_chainman.m_blockman.LoadingBlocks()) {5053LogDebug(BCLog::NET, "Unexpected blocktxn message received from peer %d\n", pfrom.GetId());5054return;5055}5057BlockTransactions resp;5058vRecv >> resp;5060return ProcessCompactBlockTxns(pfrom, peer, resp);5061}5063if (msg_type == NetMsgType::HEADERS)5064{5065// Ignore headers received while importing5066if (m_chainman.m_blockman.LoadingBlocks()) {5067LogDebug(BCLog::NET, "Unexpected headers message received from peer %d\n", pfrom.GetId());5068return;5069}5071std::vector<CBlockHeader> headers;5073// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.5074unsigned int nCount = ReadCompactSize(vRecv);5075if (nCount > m_opts.max_headers_result) {5076Misbehaving(peer, strprintf("headers message size = %u", nCount));5077return;5078}5079headers.resize(nCount);5080for (unsigned int n = 0; n < nCount; n++) {5081vRecv >> headers[n];5082ReadCompactSize(vRecv); // ignore tx count; assume it is 0.5083}5085ProcessHeadersMessage(pfrom, peer, std::move(headers), /*via_compact_block=*/false);5087// Check if the headers presync progress needs to be reported to validation.5088// This needs to be done without holding the m_headers_presync_mutex lock.5089if (m_headers_presync_should_signal.exchange(false)) {5090HeadersPresyncStats stats;5091{5092LOCK(m_headers_presync_mutex);5093auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);5094if (it != m_headers_presync_stats.end()) stats = it->second;5095}5096if (stats.second) {5097m_chainman.ReportHeadersPresync(stats.second->first, stats.second->second);5098}5099}5101return;5102}5104if (msg_type == NetMsgType::BLOCK)5105{5106// Ignore block received while importing5107if (m_chainman.m_blockman.LoadingBlocks()) {5108LogDebug(BCLog::NET, "Unexpected block message received from peer %d\n", pfrom.GetId());5109return;5110}5112std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();5113vRecv >> TX_WITH_WITNESS(*pblock);5115LogDebug(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom.GetId());5117const CBlockIndex* prev_block{WITH_LOCK(m_chainman.GetMutex(), return m_chainman.m_blockman.LookupBlockIndex(pblock->hashPrevBlock))};5119// Check for possible mutation if it connects to something we know so we can check for DEPLOYMENT_SEGWIT being active5120if (prev_block && IsBlockMutated(/*block=*/*pblock,5121/*check_witness_root=*/DeploymentActiveAfter(prev_block, m_chainman, Consensus::DEPLOYMENT_SEGWIT))) {5122LogDebug(BCLog::NET, "Received mutated block from peer=%d\n", peer.m_id);5123Misbehaving(peer, "mutated block");5124WITH_LOCK(cs_main, RemoveBlockRequest(pblock->GetHash(), peer.m_id));5125return;5126}5128bool forceProcessing = false;5129const uint256 hash(pblock->GetHash());5130bool min_pow_checked = false;5131{5132LOCK(cs_main);5133// Always process the block if we requested it, since we may5134// need it even when it's not a candidate for a new best tip.5135forceProcessing = IsBlockRequested(hash);5136RemoveBlockRequest(hash, pfrom.GetId());5137// mapBlockSource is only used for punishing peers and setting5138// which peers send us compact blocks, so the race between here and5139// cs_main in ProcessNewBlock is fine.5140mapBlockSource.emplace(hash, std::make_pair(pfrom.GetId(), true));5142// Check claimed work on this block against our anti-dos thresholds.5143if (prev_block && prev_block->nChainWork + GetBlockProof(*pblock) >= GetAntiDoSWorkThreshold()) {5144min_pow_checked = true;5145}5146}5147ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);5148return;5149}5151if (msg_type == NetMsgType::GETADDR) {5152// This asymmetric behavior for inbound and outbound connections was introduced5153// to prevent a fingerprinting attack: an attacker can send specific fake addresses5154// to users' AddrMan and later request them by sending getaddr messages.5155// Making nodes which are behind NAT and can only make outgoing connections ignore5156// the getaddr message mitigates the attack.5157if (!pfrom.IsInboundConn()) {5158LogDebug(BCLog::NET, "Ignoring \"getaddr\" from %s connection. peer=%d\n", pfrom.ConnectionTypeAsString(), pfrom.GetId());5159return;5160}5162// Since this must be an inbound connection, SetupAddressRelay will5163// never fail.5164Assume(SetupAddressRelay(pfrom, peer));5166// Only send one GetAddr response per connection to reduce resource waste5167// and discourage addr stamping of INV announcements.5168if (peer.m_getaddr_recvd) {5169LogDebug(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n", pfrom.GetId());5170return;5171}5172peer.m_getaddr_recvd = true;5174peer.m_addrs_to_send.clear();5175std::vector<CAddress> vAddr;5176if (pfrom.HasPermission(NetPermissionFlags::Addr)) {5177vAddr = m_connman.GetAddressesUnsafe(MAX_ADDR_TO_SEND, MAX_PCT_ADDR_TO_SEND, /*network=*/std::nullopt);5178} else {5179vAddr = m_connman.GetAddresses(pfrom, MAX_ADDR_TO_SEND, MAX_PCT_ADDR_TO_SEND);5180}5181for (const CAddress &addr : vAddr) {5182PushAddress(peer, addr);5183}5184return;5185}5187if (msg_type == NetMsgType::MEMPOOL) {5188// Only process received mempool messages if we advertise NODE_BLOOM5189// or if the peer has mempool permissions.5190if (!(peer.m_our_services & NODE_BLOOM) && !pfrom.HasPermission(NetPermissionFlags::Mempool))5191{5192if (!pfrom.HasPermission(NetPermissionFlags::NoBan))5193{5194LogDebug(BCLog::NET, "mempool request with bloom filters disabled, %s", pfrom.DisconnectMsg());5195pfrom.fDisconnect = true;5196}5197return;5198}5200if (m_connman.OutboundTargetReached(false) && !pfrom.HasPermission(NetPermissionFlags::Mempool))5201{5202if (!pfrom.HasPermission(NetPermissionFlags::NoBan))5203{5204LogDebug(BCLog::NET, "mempool request with bandwidth limit reached, %s", pfrom.DisconnectMsg());5205pfrom.fDisconnect = true;5206}5207return;5208}5210if (auto tx_relay = peer.GetTxRelay(); tx_relay != nullptr) {5211LOCK(tx_relay->m_tx_inventory_mutex);5212tx_relay->m_send_mempool = true;5213}5214return;5215}5217if (msg_type == NetMsgType::PING) {5218if (pfrom.GetCommonVersion() > BIP0031_VERSION) {5219uint64_t nonce = 0;5220vRecv >> nonce;5221// Echo the message back with the nonce. This allows for two useful features:5222//5223// 1) A remote node can quickly check if the connection is operational5224// 2) Remote nodes can measure the latency of the network thread. If this node5225// is overloaded it won't respond to pings quickly and the remote node can5226// avoid sending us more work, like chain download requests.5227//5228// The nonce stops the remote getting confused between different pings: without5229// it, if the remote node sends a ping once per second and this node takes 55230// seconds to respond to each, the 5th ping the remote sends would appear to5231// return very quickly.5232MakeAndPushMessage(pfrom, NetMsgType::PONG, nonce);5233}5234return;5235}5237if (msg_type == NetMsgType::PONG) {5238ProcessPong(pfrom, peer, /*ping_end=*/time_received, vRecv);5239return;5240}5242if (msg_type == NetMsgType::FILTERLOAD) {5243if (!(peer.m_our_services & NODE_BLOOM)) {5244LogDebug(BCLog::NET, "filterload received despite not offering bloom services, %s", pfrom.DisconnectMsg());5245pfrom.fDisconnect = true;5246return;5247}5248CBloomFilter filter;5249vRecv >> filter;