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.
502bool success;503auto address{self.MaybeArg<std::string_view>("address")};504auto node_id{self.MaybeArg<int64_t>("nodeid")};506if (address && !node_id) {507/* handle disconnect-by-address */508success = connman.DisconnectNode(*address);509} else if (node_id && (!address || address->empty())) {510/* handle disconnect-by-id */511success = connman.DisconnectNode(*node_id);512} else {513throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");514}516if (!success) {517throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");518}520return UniValue::VNULL;521},522};523}525static RPCMethod getaddednodeinfo()526{527return RPCMethod{528"getaddednodeinfo",529"Returns information about the given added node, or all added nodes\n"530"(note that onetry addnodes are not listed here)\n",531{532{"node", RPCArg::Type::STR, RPCArg::DefaultHint{"all nodes"}, "If provided, return information about this specific node, otherwise all nodes are returned."},533},534RPCResult{535RPCResult::Type::ARR, "", "",536{537{RPCResult::Type::OBJ, "", "",538{539{RPCResult::Type::STR, "addednode", "The node IP address or name (as provided to addnode)"},540{RPCResult::Type::BOOL, "connected", "If connected"},541{RPCResult::Type::ARR, "addresses", "Only when connected = true",542{543{RPCResult::Type::OBJ, "", "",544{545{RPCResult::Type::STR, "address", "The bitcoin server IP and port we're connected to"},546{RPCResult::Type::STR, "connected", "connection, inbound or outbound"},547}},548}},549}},550}551},552RPCExamples{553HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")554+ HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")555},556[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue557{558NodeContext& node = EnsureAnyNodeContext(request.context);559const CConnman& connman = EnsureConnman(node);561std::vector<AddedNodeInfo> vInfo = connman.GetAddedNodeInfo(/*include_connected=*/true);563if (auto node{self.MaybeArg<std::string_view>("node")}) {564bool found = false;565for (const AddedNodeInfo& info : vInfo) {566if (info.m_params.m_added_node == *node) {567vInfo.assign(1, info);568found = true;569break;570}571}572if (!found) {573throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");574}575}577UniValue ret(UniValue::VARR);579for (const AddedNodeInfo& info : vInfo) {580UniValue obj(UniValue::VOBJ);581obj.pushKV("addednode", info.m_params.m_added_node);582obj.pushKV("connected", info.fConnected);583UniValue addresses(UniValue::VARR);584if (info.fConnected) {585UniValue address(UniValue::VOBJ);586address.pushKV("address", info.resolvedAddress.ToStringAddrPort());587address.pushKV("connected", info.fInbound ? "inbound" : "outbound");588addresses.push_back(std::move(address));589}590obj.pushKV("addresses", std::move(addresses));591ret.push_back(std::move(obj));592}594return ret;595},596};597}599static RPCMethod getnettotals()600{601return RPCMethod{"getnettotals",602"Returns information about network traffic, including bytes in, bytes out,\n"603"and current system time.",604{},605RPCResult{606RPCResult::Type::OBJ, "", "",607{608{RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"},609{RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},610{RPCResult::Type::NUM_TIME, "timemillis", "Current system " + UNIX_EPOCH_TIME + " in milliseconds"},611{RPCResult::Type::OBJ, "uploadtarget", "",612{613{RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"},614{RPCResult::Type::NUM, "target", "Target in bytes"},615{RPCResult::Type::BOOL, "target_reached", "True if target is reached"},616{RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"},617{RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"},618{RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"},619}},620}621},622RPCExamples{623HelpExampleCli("getnettotals", "")624+ HelpExampleRpc("getnettotals", "")625},626[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue627{628NodeContext& node = EnsureAnyNodeContext(request.context);629const CConnman& connman = EnsureConnman(node);631UniValue obj(UniValue::VOBJ);632obj.pushKV("totalbytesrecv", connman.GetTotalBytesRecv());633obj.pushKV("totalbytessent", connman.GetTotalBytesSent());634obj.pushKV("timemillis", TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()));636UniValue outboundLimit(UniValue::VOBJ);637outboundLimit.pushKV("timeframe", count_seconds(connman.GetMaxOutboundTimeframe()));638outboundLimit.pushKV("target", connman.GetMaxOutboundTarget());639outboundLimit.pushKV("target_reached", connman.OutboundTargetReached(false));640outboundLimit.pushKV("serve_historical_blocks", !connman.OutboundTargetReached(true));641outboundLimit.pushKV("bytes_left_in_cycle", connman.GetOutboundTargetBytesLeft());642outboundLimit.pushKV("time_left_in_cycle", count_seconds(connman.GetMaxOutboundTimeLeftInCycle()));643obj.pushKV("uploadtarget", std::move(outboundLimit));644return obj;645},646};647}649static UniValue GetNetworksInfo()650{651UniValue networks(UniValue::VARR);652for (int n = 0; n < NET_MAX; ++n) {653enum Network network = static_cast<enum Network>(n);654if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;655UniValue obj(UniValue::VOBJ);656obj.pushKV("name", GetNetworkName(network));657obj.pushKV("limited", !g_reachable_nets.Contains(network));658obj.pushKV("reachable", g_reachable_nets.Contains(network));659if (const auto proxy = GetProxy(network)) {660obj.pushKV("proxy", proxy->ToString());661obj.pushKV("proxy_randomize_credentials", proxy->m_tor_stream_isolation);662} else {663obj.pushKV("proxy", std::string());664obj.pushKV("proxy_randomize_credentials", false);665}666networks.push_back(std::move(obj));667}668return networks;669}671static RPCMethod getnetworkinfo()672{673return RPCMethod{"getnetworkinfo",674"Returns an object containing various state info regarding P2P networking.\n",675{},676RPCResult{677RPCResult::Type::OBJ, "", "",678{679{RPCResult::Type::NUM, "version", "the server version"},680{RPCResult::Type::STR, "subversion", "the server subversion string"},681{RPCResult::Type::NUM, "protocolversion", "the protocol version"},682{RPCResult::Type::STR_HEX, "localservices", "the services we offer to the network"},683{RPCResult::Type::ARR, "localservicesnames", "the services we offer to the network, in human-readable form",684{685{RPCResult::Type::STR, "SERVICE_NAME", "the service name"},686}},687{RPCResult::Type::BOOL, "localrelay", "true if transaction relay is requested from peers"},688{RPCResult::Type::NUM, "timeoffset", "the time offset"},689{RPCResult::Type::NUM, "tx_send_rate", "configured target for maximum number of transactions per second to send to inbound peers"},690{RPCResult::Type::OBJ_DYN, "inv_buckets", "", {691{RPCResult::Type::OBJ, "inbound/outbound", "connection direction",692{693{RPCResult::Type::NUM, "backlog", "number of queued txs to announce"},694{RPCResult::Type::NUM, "count_tok", "tokens available to be consumed per-transaction"},695{RPCResult::Type::NUM, "size_tok", "tokens available to be consumed per-byte"},696}697}698}},699{RPCResult::Type::NUM, "connections", "the total number of connections"},700{RPCResult::Type::NUM, "connections_in", "the number of inbound connections"},701{RPCResult::Type::NUM, "connections_out", "the number of outbound connections"},702{RPCResult::Type::BOOL, "networkactive", "whether p2p networking is enabled"},703{RPCResult::Type::ARR, "networks", "information per network",704{705{RPCResult::Type::OBJ, "", "",706{707{RPCResult::Type::STR, "name", "network (" + Join(GetNetworkNames(), ", ") + ")"},708{RPCResult::Type::BOOL, "limited", "is the network limited using -onlynet?"},709{RPCResult::Type::BOOL, "reachable", "is the network reachable?"},710{RPCResult::Type::STR, "proxy", "(\"host:port\") the proxy that is used for this network, or empty if none"},711{RPCResult::Type::BOOL, "proxy_randomize_credentials", "Whether randomized credentials are used"},712}},713}},714{RPCResult::Type::STR_HEX, "asmap_version", /*optional=*/true, "the SHA256 hash of the asmap data used for IP bucketing (only displayed if the -asmap config option is set)"},715{RPCResult::Type::STR_AMOUNT, "relayfee", "minimum relay fee rate for transactions in " + CURRENCY_UNIT + "/kvB"},716{RPCResult::Type::STR_AMOUNT, "incrementalfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"},717{RPCResult::Type::ARR, "localaddresses", "list of local addresses",718{719{RPCResult::Type::OBJ, "", "",720{721{RPCResult::Type::STR, "address", "network address"},722{RPCResult::Type::NUM, "port", "network port"},723{RPCResult::Type::NUM, "score", "relative score"},724}},725}},726(IsDeprecatedRPCEnabled("warnings") ?727RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} :728RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)",729{730{RPCResult::Type::STR, "", "warning"},731}732}733),734}735},736RPCExamples{737HelpExampleCli("getnetworkinfo", "")738+ HelpExampleRpc("getnetworkinfo", "")739},740[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue741{742LOCK(cs_main);743UniValue obj(UniValue::VOBJ);744obj.pushKV("version", CLIENT_VERSION);745obj.pushKV("subversion", strSubVersion);746obj.pushKV("protocolversion",PROTOCOL_VERSION);747NodeContext& node = EnsureAnyNodeContext(request.context);748CConnman& connman = EnsureConnman(node);749ServiceFlags services = connman.GetLocalServices();750obj.pushKV("localservices", strprintf("%016x", services));