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.
5251if (!filter.IsWithinSizeConstraints())5252{5253// There is no excuse for sending a too-large filter5254Misbehaving(peer, "too-large bloom filter");5255} else if (auto tx_relay = peer.GetTxRelay(); tx_relay != nullptr) {5256{5257LOCK(tx_relay->m_bloom_filter_mutex);5258tx_relay->m_bloom_filter.reset(new CBloomFilter(filter));5259tx_relay->m_relay_txs = true;5260}5261pfrom.m_bloom_filter_loaded = true;5262pfrom.m_relays_txs = true;5263MaybeDisconnectForTxRelayCapacity(pfrom, msg_type);5264}5265return;5266}5268if (msg_type == NetMsgType::FILTERADD) {5269if (!(peer.m_our_services & NODE_BLOOM)) {5270LogDebug(BCLog::NET, "filteradd received despite not offering bloom services, %s", pfrom.DisconnectMsg());5271pfrom.fDisconnect = true;5272return;5273}5274std::vector<unsigned char> vData;5275vRecv >> vData;5277// Nodes must NEVER send a data item > MAX_SCRIPT_ELEMENT_SIZE bytes (the max size for a script data object,5278// and thus, the maximum size any matched object can have) in a filteradd message5279bool bad = false;5280if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) {5281bad = true;5282} else if (auto tx_relay = peer.GetTxRelay(); tx_relay != nullptr) {5283LOCK(tx_relay->m_bloom_filter_mutex);5284if (tx_relay->m_bloom_filter) {5285tx_relay->m_bloom_filter->insert(vData);5286} else {5287bad = true;5288}5289}5290if (bad) {5291Misbehaving(peer, "bad filteradd message");5292}5293return;5294}5296if (msg_type == NetMsgType::FILTERCLEAR) {5297if (!(peer.m_our_services & NODE_BLOOM)) {5298LogDebug(BCLog::NET, "filterclear received despite not offering bloom services, %s", pfrom.DisconnectMsg());5299pfrom.fDisconnect = true;5300return;5301}5302auto tx_relay = peer.GetTxRelay();5303if (!tx_relay) return;5305{5306LOCK(tx_relay->m_bloom_filter_mutex);5307tx_relay->m_bloom_filter = nullptr;5308tx_relay->m_relay_txs = true;5309}5310pfrom.m_bloom_filter_loaded = false;5311pfrom.m_relays_txs = true;5312MaybeDisconnectForTxRelayCapacity(pfrom, msg_type);5313return;5314}5316if (msg_type == NetMsgType::FEEFILTER) {5317CAmount newFeeFilter = 0;5318vRecv >> newFeeFilter;5319if (MoneyRange(newFeeFilter)) {5320if (auto tx_relay = peer.GetTxRelay(); tx_relay != nullptr) {5321tx_relay->m_fee_filter_received = newFeeFilter;5322}5323LogDebug(BCLog::NET, "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom.GetId());5324}5325return;5326}5328if (msg_type == NetMsgType::GETCFILTERS) {5329ProcessGetCFilters(pfrom, peer, vRecv);5330return;5331}5333if (msg_type == NetMsgType::GETCFHEADERS) {5334ProcessGetCFHeaders(pfrom, peer, vRecv);5335return;5336}5338if (msg_type == NetMsgType::GETCFCHECKPT) {5339ProcessGetCFCheckPt(pfrom, peer, vRecv);5340return;5341}5343if (msg_type == NetMsgType::NOTFOUND) {5344std::vector<CInv> vInv;5345vRecv >> vInv;5346std::vector<GenTxid> tx_invs;5347if (vInv.size() <= node::MAX_PEER_TX_ANNOUNCEMENTS + MAX_BLOCKS_IN_TRANSIT_PER_PEER) {5348for (CInv &inv : vInv) {5349if (inv.IsGenTxMsg()) {5350tx_invs.emplace_back(ToGenTxid(inv));5351}5352}5353}5354LOCK(m_tx_download_mutex);5355m_txdownloadman.ReceivedNotFound(pfrom.GetId(), tx_invs);5356return;5357}5359// Ignore unknown message types for extensibility5360LogDebug(BCLog::NET, "Unknown message type \"%s\" from peer=%d", SanitizeString(msg_type), pfrom.GetId());5361return;5362}5364bool PeerManagerImpl::MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer)5365{5366{5367LOCK(peer.m_misbehavior_mutex);5369// There's nothing to do if the m_should_discourage flag isn't set5370if (!peer.m_should_discourage) return false;5372peer.m_should_discourage = false;5373} // peer.m_misbehavior_mutex5375if (pnode.HasPermission(NetPermissionFlags::NoBan)) {5376// We never disconnect or discourage peers for bad behavior if they have NetPermissionFlags::NoBan permission5377LogWarning("Not punishing noban peer %d!", peer.m_id);5378return false;5379}5381if (pnode.IsManualConn()) {5382// We never disconnect or discourage manual peers for bad behavior5383LogWarning("Not punishing manually connected peer %d!", peer.m_id);5384return false;5385}5387if (pnode.IsPrivateBroadcastConn()) {5388LogDebug(BCLog::PRIVBROADCAST, "Disconnecting misbehaving private broadcast peer=%d", peer.m_id);5389pnode.fDisconnect = true;5390return true;5391}5393if (pnode.addr.IsLocal()) {5394// We disconnect local peers for bad behavior but don't discourage (since that would discourage5395// all peers on the same local address)5396LogDebug(BCLog::NET, "Warning: disconnecting but not discouraging %s peer %d!\n",5397pnode.m_inbound_onion ? "inbound onion" : "local", peer.m_id);5398pnode.fDisconnect = true;5399return true;5400}5402// Normal case: Disconnect the peer and discourage all nodes sharing the address5403LogDebug(BCLog::NET, "Disconnecting and discouraging peer %d!\n", peer.m_id);5404if (m_banman) m_banman->Discourage(pnode.addr);5405m_connman.DisconnectNode(CSubNet{pnode.addr}, /*disconnect_private_broadcast=*/false);5406return true;5407}5409bool PeerManagerImpl::MaybeDisconnectForTxRelayCapacity(CNode& node, const std::string& msg_type, std::optional<NodeId> protect_peer)5410{5411if (!node.IsInboundConn() || !node.m_relays_txs) return false;5412if (m_connman.EvictTxPeerIfFull(protect_peer)) return false;5414LogDebug(BCLog::NET, "failed to find a tx-relaying eviction candidate - connection dropped after %s message, peer=%d\n", msg_type, node.GetId());5415node.fDisconnect = true;5416return true;5417}5419bool PeerManagerImpl::ProcessMessages(CNode& node, std::atomic<bool>& interruptMsgProc)5420{5421AssertLockNotHeld(m_tx_download_mutex);5422AssertLockHeld(g_msgproc_mutex);5424PeerRef maybe_peer{GetPeerRef(node.GetId())};5425if (maybe_peer == nullptr) return false;5426Peer& peer{*maybe_peer};5428// For outbound connections, ensure that the initial VERSION message5429// has been sent first before processing any incoming messages5430if (!node.IsInboundConn() && !peer.m_outbound_version_message_sent) return false;5432{5433LOCK(peer.m_getdata_requests_mutex);5434if (!peer.m_getdata_requests.empty()) {5435ProcessGetData(node, peer, interruptMsgProc);5436}5437}5439const bool processed_orphan = ProcessOrphanTx(peer);5441if (node.fDisconnect)5442return false;5444if (processed_orphan) return true;5446// this maintains the order of responses5447// and prevents m_getdata_requests to grow unbounded5448{5449LOCK(peer.m_getdata_requests_mutex);5450if (!peer.m_getdata_requests.empty()) return true;5451}5453// Don't bother if send buffer is too full to respond anyway5454if (node.fPauseSend) return false;5456auto poll_result{node.PollMessage()};5457if (!poll_result) {5458// No message to process5459return false;5460}5462CNetMessage& msg{poll_result->first};5463bool fMoreWork = poll_result->second;5465TRACEPOINT(net, inbound_message,5466node.GetId(),5467node.m_addr_name.c_str(),5468node.ConnectionTypeAsString().c_str(),5469msg.m_type.c_str(),5470msg.m_recv.size(),5471msg.m_recv.data()5472);5474if (m_opts.capture_messages) {5475CaptureMessage(node.addr, msg.m_type, MakeUCharSpan(msg.m_recv), /*is_incoming=*/true);5476}5478try {5479ProcessMessage(peer, node, msg.m_type, msg.m_recv, msg.m_time, interruptMsgProc);5480if (interruptMsgProc) return false;5481{5482LOCK(peer.m_getdata_requests_mutex);5483if (!peer.m_getdata_requests.empty()) fMoreWork = true;5484}5485// Does this peer have an orphan ready to reconsider?5486// (Note: we may have provided a parent for an orphan provided5487// by another peer that was already processed; in that case,5488// the extra work may not be noticed, possibly resulting in an5489// unnecessary 100ms delay)5490LOCK(m_tx_download_mutex);5491if (m_txdownloadman.HaveMoreWork(peer.m_id)) fMoreWork = true;5492} catch (const std::exception& e) {5493LogDebug(BCLog::NET, "%s(%s, %u bytes): Exception '%s' (%s) caught\n", __func__, SanitizeString(msg.m_type), msg.m_message_size, e.what(), typeid(e).name());5494} catch (...) {5495LogDebug(BCLog::NET, "%s(%s, %u bytes): Unknown exception caught\n", __func__, SanitizeString(msg.m_type), msg.m_message_size);5496}5498return fMoreWork;5499}