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.
1// Copyright (c) 2009-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <rpc/register.h> // IWYU pragma: associated6#include <rpc/server.h>8#include <addrman.h>9#include <addrman_impl.h>10#include <banman.h>11#include <chainparams.h>12#include <clientversion.h>13#include <core_io.h>14#include <crypto/hex_base.h>15#include <net.h>16#include <net_permissions.h>17#include <net_processing.h>18#include <net_types.h>19#include <netaddress.h>20#include <netbase.h>21#include <netgroup.h>22#include <node/connection_types.h>23#include <node/context.h>24#include <node/protocol_version.h>25#include <node/warnings.h>26#include <policy/feerate.h>27#include <protocol.h>28#include <rpc/protocol.h>29#include <rpc/request.h>30#include <rpc/server_util.h>31#include <rpc/util.h>32#include <semaphore_grant.h>33#include <sync.h>34#include <tinyformat.h>35#include <txmempool.h>36#include <uint256.h>37#include <univalue.h>38#include <util/chaintype.h>39#include <util/check.h>40#include <util/strencodings.h>41#include <util/string.h>42#include <util/time.h>43#include <validation.h>44#ifdef ENABLE_EMBEDDED_ASMAP45#include <common/args.h>46#include <node/data/ip_asn.dat.h>47#include <streams.h>48#include <util/asmap.h>49#include <util/fs.h>50#endif52#include <atomic>53#include <compare>54#include <cstdint>55#include <map>56#include <memory>57#include <optional>58#include <span>59#include <sstream>60#include <stdexcept>61#include <string>62#include <string_view>63#include <type_traits>64#include <utility>65#include <vector>67using node::NodeContext;68using util::Join;69using util::TrimStringView;71const std::vector<std::string> CONNECTION_TYPE_DOC{72"outbound-full-relay (default automatic connections)",73"block-relay-only (does not relay transactions or addresses)",74"inbound (initiated by the peer)",75"manual (added via addnode RPC or -addnode/-connect configuration options)",76"addr-fetch (short-lived automatic connection for soliciting addresses)",77"feeler (short-lived automatic connection for testing addresses)",78"private-broadcast (short-lived automatic connection for broadcasting privacy-sensitive transactions)"79};81const std::vector<std::string> TRANSPORT_TYPE_DOC{82"detecting (peer could be v1 or v2)",83"v1 (plaintext transport protocol)",84"v2 (BIP324 encrypted transport protocol)"85};87static RPCMethod getconnectioncount()88{89return RPCMethod{90"getconnectioncount",91"Returns the number of connections to other nodes.\n",92{},93RPCResult{94RPCResult::Type::NUM, "", "The connection count"95},96RPCExamples{97HelpExampleCli("getconnectioncount", "")98+ HelpExampleRpc("getconnectioncount", "")99},100[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue101{102NodeContext& node = EnsureAnyNodeContext(request.context);103const CConnman& connman = EnsureConnman(node);105return connman.GetNodeCount(ConnectionDirection::Both);106},107};108}110static RPCMethod ping()111{112return RPCMethod{113"ping",114"Requests that a ping be sent to all other nodes, to measure ping time.\n"115"Results are provided in getpeerinfo.\n"116"Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n",117{},118RPCResult{RPCResult::Type::NONE, "", ""},119RPCExamples{120HelpExampleCli("ping", "")121+ HelpExampleRpc("ping", "")122},123[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue124{125NodeContext& node = EnsureAnyNodeContext(request.context);126PeerManager& peerman = EnsurePeerman(node);128// Request that each node send a ping during next message processing pass129peerman.SendPings();130return UniValue::VNULL;131},132};133}135/** Returns, given services flags, a list of humanly readable (known) network services */136static UniValue GetServicesNames(ServiceFlags services)137{138UniValue servicesNames(UniValue::VARR);140for (const auto& flag : serviceFlagsToStr(services)) {141servicesNames.push_back(flag);142}144return servicesNames;145}147static RPCMethod getpeerinfo()148{149return RPCMethod{150"getpeerinfo",151"Returns data about each connected network peer as a json array of objects.",152{},153RPCResult{154RPCResult::Type::ARR, "", "",155{156{RPCResult::Type::OBJ, "", "",157{158{159{RPCResult::Type::NUM, "id", "Peer index"},160{RPCResult::Type::STR, "addr", "(host:port) The IP address/hostname optionally followed by :port of the peer"},161{RPCResult::Type::STR, "addrbind", /*optional=*/true, "(ip:port) Bind address of the connection to the peer"},162{RPCResult::Type::STR, "addrlocal", /*optional=*/true, "(ip:port) Local address as reported by the peer"},163{RPCResult::Type::STR, "network", "Network (" + Join(GetNetworkNames(/*append_unroutable=*/true), ", ") + ")"},164{RPCResult::Type::NUM, "mapped_as", /*optional=*/true, "Mapped AS (Autonomous System) number at the end of the BGP route to the peer, used for diversifying\n"165"peer selection (only displayed if the -asmap config option is set)"},166{RPCResult::Type::STR_HEX, "services", "The services offered"},167{RPCResult::Type::ARR, "servicesnames", "the services offered, in human-readable form",168{169{RPCResult::Type::STR, "SERVICE_NAME", "the service name if it is recognised"}170}},171{RPCResult::Type::BOOL, "relaytxes", "Whether we relay transactions to this peer"},172{RPCResult::Type::NUM, "last_inv_sequence", "Mempool sequence number of this peer's last INV"},173{RPCResult::Type::NUM, "inv_to_send", "How many txs we have queued to announce to this peer"},174{RPCResult::Type::NUM_TIME, "lastsend", "The " + UNIX_EPOCH_TIME + " of the last send"},175{RPCResult::Type::NUM_TIME, "lastrecv", "The " + UNIX_EPOCH_TIME + " of the last receive"},176{RPCResult::Type::NUM_TIME, "last_transaction", "The " + UNIX_EPOCH_TIME + " of the last valid transaction received from this peer"},177{RPCResult::Type::NUM_TIME, "last_block", "The " + UNIX_EPOCH_TIME + " of the last block received from this peer"},178{RPCResult::Type::NUM, "bytessent", "The total bytes sent"},179{RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},180{RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},181{RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},182{RPCResult::Type::NUM, "pingtime", /*optional=*/true, "The last ping time in seconds, if any"},183{RPCResult::Type::NUM, "minping", /*optional=*/true, "The minimum observed ping time in seconds, if any"},184{RPCResult::Type::NUM, "pingwait", /*optional=*/true, "The duration in seconds of an outstanding ping (if non-zero)"},185{RPCResult::Type::NUM, "version", "The peer version, such as 70001"},186{RPCResult::Type::STR, "subver", "The string version"},187{RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},188{RPCResult::Type::BOOL, "bip152_hb_to", "Whether we selected peer as (compact blocks) high-bandwidth peer"},189{RPCResult::Type::BOOL, "bip152_hb_from", "Whether peer selected us as (compact blocks) high-bandwidth peer"},190{RPCResult::Type::NUM, "presynced_headers", "The current height of header pre-synchronization with this peer, or -1 if no low-work sync is in progress"},191{RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},192{RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},193{RPCResult::Type::ARR, "inflight", "",194{195{RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},196}},197{RPCResult::Type::BOOL, "addr_relay_enabled", "Whether we participate in address relay with this peer"},198{RPCResult::Type::NUM, "addr_processed", "The total number of addresses processed, excluding those dropped due to rate limiting"},199{RPCResult::Type::NUM, "addr_rate_limited", "The total number of addresses dropped due to rate limiting"},200{RPCResult::Type::ARR, "permissions", "Any special permissions that have been granted to this peer",201{202{RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},203}},204{RPCResult::Type::STR_AMOUNT, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},205{RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",206{207{RPCResult::Type::NUM, "msg", "The total bytes sent aggregated by message type\n"208"When a message type is not listed in this json object, the bytes sent are 0.\n"209"Only known message types can appear as keys in the object."}210}},211{RPCResult::Type::OBJ_DYN, "bytesrecv_per_msg", "",212{213{RPCResult::Type::NUM, "msg", "The total bytes received aggregated by message type\n"214"When a message type is not listed in this json object, the bytes received are 0.\n"215"Only known message types can appear as keys in the object and all bytes received\n"216"of unknown message types are listed under '"+NET_MESSAGE_TYPE_OTHER+"'."}217}},218{RPCResult::Type::STR, "connection_type", "Type of connection: \n" + Join(CONNECTION_TYPE_DOC, ",\n") + ".\n"219"Please note this output is unlikely to be stable in upcoming releases as we iterate to\n"220"best capture connection behaviors."},221{RPCResult::Type::STR, "transport_protocol_type", "Type of transport protocol: \n" + Join(TRANSPORT_TYPE_DOC, ",\n") + ".\n"},222{RPCResult::Type::STR, "session_id", "The session ID for this connection, or \"\" if there is none (\"v2\" transport protocol only).\n"},223}},224}},225},226RPCExamples{227HelpExampleCli("getpeerinfo", "")228+ HelpExampleRpc("getpeerinfo", "")229},230[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue231{232NodeContext& node = EnsureAnyNodeContext(request.context);233const CConnman& connman = EnsureConnman(node);234const PeerManager& peerman = EnsurePeerman(node);236std::vector<CNodeStats> vstats;237connman.GetNodeStats(vstats);239UniValue ret(UniValue::VARR);241for (const CNodeStats& stats : vstats) {242UniValue obj(UniValue::VOBJ);243CNodeStateStats statestats;244bool fStateStats = peerman.GetNodeStateStats(stats.nodeid, statestats);245// GetNodeStateStats() requires the existence of a CNodeState and a Peer object246// to succeed for this peer. These are created at connection initialisation and247// exist for the duration of the connection - except if there is a race where the248// peer got disconnected in between the GetNodeStats() and the GetNodeStateStats()249// calls. In this case, the peer doesn't need to be reported here.250if (!fStateStats) {