Inside Bitcoin
Opening the selected file…
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.
3751std::vector<CInv> invs;3752invs.emplace_back(MSG_BLOCK | GetFetchFlags(peer), block_transactions.blockhash);3753MakeAndPushMessage(pfrom, NetMsgType::GETDATA, invs);3754} else {3755RemoveBlockRequest(block_transactions.blockhash, pfrom.GetId());3756LogDebug(BCLog::NET, "Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.GetId());3757return;3758}3759} else {3760// Block is okay for further processing3761RemoveBlockRequest(block_transactions.blockhash, pfrom.GetId()); // it is now an empty pointer3762fBlockRead = true;3763// mapBlockSource is used for potentially punishing peers and3764// updating which peers send us compact blocks, so the race3765// between here and cs_main in ProcessNewBlock is fine.3766// BIP 152 permits peers to relay compact blocks after validating3767// the header only; we should not punish peers if the block turns3768// out to be invalid.3769mapBlockSource.emplace(block_transactions.blockhash, std::make_pair(pfrom.GetId(), false));3770}3771} // Don't hold cs_main when we call into ProcessNewBlock3772if (fBlockRead) {3773// Since we requested this block (it was in mapBlocksInFlight), force it to be processed,3774// even if it would not be a candidate for new tip (missing previous block, chain not long enough, etc)3775// This bypasses some anti-DoS logic in AcceptBlock (eg to prevent3776// disk-space attacks), but this should be safe due to the3777// protections in the compact block handler -- see related comment3778// in compact block optimistic reconstruction handling.3779ProcessBlock(pfrom, pblock, /*force_processing=*/true, /*min_pow_checked=*/true);3780}3781return;3782}3784void PeerManagerImpl::LogBlockHeader(const CBlockIndex& index, const CNode& peer, bool via_compact_block) {3785// To prevent log spam, this function should only be called after it was determined that a3786// header is both new and valid.3787//3788// These messages are valuable for detecting potential selfish mining behavior;3789// if multiple displacing headers are seen near simultaneously across many3790// nodes in the network, this might be an indication of selfish mining.3791// In addition it can be used to identify peers which send us a header, but3792// don't followup with a complete and valid (compact) block.3793// Having this log by default when not in IBD ensures broad availability of3794// this data in case investigation is merited.3795const auto msg = strprintf(3796"Saw new %sheader hash=%s height=%d %s",3797via_compact_block ? "cmpctblock " : "",3798index.GetBlockHash().ToString(),3799index.nHeight,3800peer.LogPeer()3801);3802if (m_chainman.IsInitialBlockDownload()) {3803LogDebug(BCLog::VALIDATION, "%s", msg);3804} else {3805LogInfo("%s", msg);3806}3807}3809void PeerManagerImpl::PushPrivateBroadcastTx(CNode& node)3810{3811Assume(node.IsPrivateBroadcastConn());3813const auto opt_tx{m_tx_for_private_broadcast.PickTxForSend(node.GetId(), CService{node.addr})};3814if (!opt_tx) {3815LogDebug(BCLog::PRIVBROADCAST, "Disconnecting: no more transactions for private broadcast (connected in vain), %s", node.LogPeer());3816node.fDisconnect = true;3817return;3818}3819const CTransactionRef& tx{*opt_tx};3821LogDebug(BCLog::PRIVBROADCAST, "P2P handshake completed, sending INV for txid=%s%s, %s",3822tx->GetHash().ToString(), tx->HasWitness() ? strprintf(", wtxid=%s", tx->GetWitnessHash().ToString()) : "",3823node.LogPeer());3825MakeAndPushMessage(node, NetMsgType::INV, std::vector<CInv>{{CInv{MSG_TX, tx->GetHash().ToUint256()}}});3826}3828void PeerManagerImpl::ProcessMessage(Peer& peer, CNode& pfrom, const std::string& msg_type, DataStream& vRecv,3829const NodeClock::time_point time_received,3830const std::atomic<bool>& interruptMsgProc)3831{3832AssertLockHeld(g_msgproc_mutex);3834LogDebug(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom.GetId());3837if (msg_type == NetMsgType::VERSION) {3838if (pfrom.nVersion != 0) {3839LogDebug(BCLog::NET, "redundant version message from peer=%d\n", pfrom.GetId());3840return;3841}3843int64_t nTime;3844CService addrMe;3845uint64_t nNonce = 1;3846ServiceFlags nServices;3847int nVersion;3848std::string cleanSubVer;3849int starting_height = -1;3850bool fRelay = true;3852vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;3853if (nTime < 0) {3854nTime = 0;3855}3856vRecv.ignore(8); // Ignore the addrMe service bits sent by the peer3857vRecv >> CNetAddr::V1(addrMe);3858if (!pfrom.IsInboundConn() && !pfrom.IsPrivateBroadcastConn())3859{3860// Overwrites potentially existing services. In contrast to this,3861// unvalidated services received via gossip relay in ADDR/ADDRV23862// messages are only ever added but cannot replace existing ones.3863m_addrman.SetServices(pfrom.addr, nServices);3864}3865if (pfrom.ExpectServicesFromConn() && !HasAllDesirableServiceFlags(nServices))3866{3867LogDebug(BCLog::NET, "peer does not offer the expected services (%08x offered, %08x expected), %s",3868nServices,3869GetDesirableServiceFlags(nServices),3870pfrom.DisconnectMsg());3871pfrom.fDisconnect = true;3872return;3873}3875if (nVersion < MIN_PEER_PROTO_VERSION) {3876// disconnect from peers older than this proto version3877LogDebug(BCLog::NET, "peer using obsolete version %i, %s", nVersion, pfrom.DisconnectMsg());3878pfrom.fDisconnect = true;3879return;3880}3882if (!vRecv.empty()) {3883// The version message includes information about the sending node which we don't use:3884// - 8 bytes (service bits)3885// - 16 bytes (ipv6 address)3886// - 2 bytes (port)3887vRecv.ignore(26);3888vRecv >> nNonce;3889}3890if (!vRecv.empty()) {3891std::string strSubVer;3892vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH);3893cleanSubVer = SanitizeString(strSubVer);3894}3895if (!vRecv.empty()) {3896vRecv >> starting_height;3897}3898if (!vRecv.empty())3899vRecv >> fRelay;3900// Disconnect if we connected to ourself3901if (pfrom.IsInboundConn() && !m_connman.CheckIncomingNonce(nNonce))3902{3903LogInfo("connected to self at %s, disconnecting\n", pfrom.addr.ToStringAddrPort());3904pfrom.fDisconnect = true;3905return;3906}3908if (pfrom.IsInboundConn() && addrMe.IsRoutable())3909{3910SeenLocal(addrMe);3911}3913// Inbound peers send us their version message when they connect.3914// We send our version message in response.3915if (pfrom.IsInboundConn()) {3916PushNodeVersion(pfrom, peer);3917}3919// Change version3920const int greatest_common_version = std::min(nVersion, pfrom.AdvertisedVersion());3921pfrom.SetCommonVersion(greatest_common_version);3922pfrom.nVersion = nVersion;3924pfrom.m_has_all_wanted_services = HasAllDesirableServiceFlags(nServices);3925peer.m_their_services = nServices;3926pfrom.SetAddrLocal(addrMe);3927{3928LOCK(pfrom.m_subver_mutex);3929pfrom.cleanSubVer = cleanSubVer;3930}3932// Only initialize the Peer::TxRelay m_relay_txs data structure if:3933// - this isn't an outbound block-relay-only connection, and3934// - this isn't an outbound feeler connection, and3935// - fRelay=true (the peer wishes to receive transaction announcements)3936// or we're offering NODE_BLOOM to this peer. NODE_BLOOM means that3937// the peer may turn on transaction relay later.3938if (!pfrom.IsBlockOnlyConn() &&3939!pfrom.IsFeelerConn() &&3940(fRelay || (peer.m_our_services & NODE_BLOOM))) {3941auto* const tx_relay = peer.SetTxRelay();3942{3943LOCK(tx_relay->m_bloom_filter_mutex);3944tx_relay->m_relay_txs = fRelay; // set to true after we get the first filter* message3945}3946if (fRelay) pfrom.m_relays_txs = true;3947}3949const auto mapped_as{m_connman.GetMappedAS(pfrom.addr)};3950LogDebug(BCLog::NET, "receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, %s%s",3951cleanSubVer.empty() ? "<no user agent>" : cleanSubVer, pfrom.nVersion,3952starting_height, addrMe.ToStringAddrPort(), fRelay, pfrom.LogPeer(),3953(mapped_as ? strprintf(", mapped_as=%d", mapped_as) : ""));3955if (pfrom.IsPrivateBroadcastConn()) {3956if (fRelay) {3957MakeAndPushMessage(pfrom, NetMsgType::VERACK);3958} else {3959LogDebug(BCLog::PRIVBROADCAST, "Disconnecting: does not support transaction relay (connected in vain), %s",3960pfrom.LogPeer());3961pfrom.fDisconnect = true;3962}3963return;3964}3966if (greatest_common_version >= WTXID_RELAY_VERSION) {3967MakeAndPushMessage(pfrom, NetMsgType::WTXIDRELAY);3968}3970// Signal ADDRv2 support (BIP155).3971if (greatest_common_version >= 70016) {3972// BIP155 defines addrv2 and sendaddrv2 for all protocol versions, but some3973// implementations reject messages they don't know. As a courtesy, don't send3974// it to nodes with a version before 70016, as no software is known to support3975// BIP155 that doesn't announce at least that protocol version number.3976MakeAndPushMessage(pfrom, NetMsgType::SENDADDRV2);3977}3979if (greatest_common_version >= WTXID_RELAY_VERSION && m_txreconciliation) {3980// Per BIP-330, we announce txreconciliation support if:3981// - protocol version per the peer's VERSION message supports WTXID_RELAY;3982// - transaction relay is supported per the peer's VERSION message3983// - this is not a block-relay-only connection and not a feeler3984// - this is not an addr fetch connection;3985// - we are not in -blocksonly mode.3986const auto* tx_relay = peer.GetTxRelay();3987if (tx_relay && WITH_LOCK(tx_relay->m_bloom_filter_mutex, return tx_relay->m_relay_txs) &&3988!pfrom.IsAddrFetchConn() && !m_opts.ignore_incoming_txs) {3989const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.GetId());3990MakeAndPushMessage(pfrom, NetMsgType::SENDTXRCNCL,3991TXRECONCILIATION_VERSION, recon_salt);3992}3993}3995if (greatest_common_version >= FEATURE_VERSION) {3996// announce supported features3997// MakeAndPushFeature(pfrom, NetMsgFeature::FOO, uint32_t{1});3998}4000// If we have too many tx-relaying inbound peers, attempt to evict an existing one.