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.
751obj.pushKV("localservicesnames", GetServicesNames(services));752auto peerman_info{EnsurePeerman(node).GetInfo()};753obj.pushKV("localrelay", !peerman_info.ignores_incoming_txs);754obj.pushKV("timeoffset", Ticks<std::chrono::seconds>(peerman_info.median_outbound_time_offset));755obj.pushKV("tx_send_rate", peerman_info.tx_send_rate);756auto buckjson = [&](const auto& buckinfo) {757UniValue b{UniValue::VOBJ};758b.pushKV("backlog", buckinfo.backlog_count);759b.pushKV("count_tok", buckinfo.count_bucket);760b.pushKV("size_tok", buckinfo.size_bucket);761return b;762};763UniValue invbuckets{UniValue::VOBJ};764invbuckets.pushKV("inbound", buckjson(peerman_info.inbound_bucket));765invbuckets.pushKV("outbound", buckjson(peerman_info.outbound_bucket));766obj.pushKV("inv_buckets", invbuckets);767obj.pushKV("networkactive", connman.GetNetworkActive());768obj.pushKV("connections", connman.GetNodeCount(ConnectionDirection::Both));769obj.pushKV("connections_in", connman.GetNodeCount(ConnectionDirection::In));770obj.pushKV("connections_out", connman.GetNodeCount(ConnectionDirection::Out));771obj.pushKV("networks", GetNetworksInfo());772const NetGroupManager& netgroupman{*CHECK_NONFATAL(node.netgroupman)};773if (netgroupman.UsingASMap()) {774obj.pushKV("asmap_version", HexStr(netgroupman.GetAsmapVersion()));775}776const CTxMemPool& mempool = EnsureAnyMemPool(request.context);777// Those fields can be deprecated, to be replaced by the getmempoolinfo fields778obj.pushKV("relayfee", ValueFromAmount(mempool.m_opts.min_relay_feerate.GetFeePerK()));779obj.pushKV("incrementalfee", ValueFromAmount(mempool.m_opts.incremental_relay_feerate.GetFeePerK()));780UniValue localAddresses(UniValue::VARR);781{782LOCK(g_maplocalhost_mutex);783for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost)784{785UniValue rec(UniValue::VOBJ);786rec.pushKV("address", item.first.ToStringAddr());787rec.pushKV("port", item.second.nPort);788rec.pushKV("score", item.second.nScore);789localAddresses.push_back(std::move(rec));790}791}792obj.pushKV("localaddresses", std::move(localAddresses));793obj.pushKV("warnings", node::GetWarningsForRpc(*CHECK_NONFATAL(node.warnings), IsDeprecatedRPCEnabled("warnings")));794return obj;795},796};797}799static RPCMethod setban()800{801return RPCMethod{802"setban",803"Attempts to add or remove an IP/Subnet from the banned list.\n",804{805{"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},806{"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add an IP/Subnet to the list, 'remove' to remove an IP/Subnet from the list"},807{"bantime", RPCArg::Type::NUM, RPCArg::Default{0}, "time in seconds how long (or until when if [absolute] is set) the IP is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)"},808{"absolute", RPCArg::Type::BOOL, RPCArg::Default{false}, "If set, the bantime must be an absolute timestamp expressed in " + UNIX_EPOCH_TIME},809},810RPCResult{RPCResult::Type::NONE, "", ""},811RPCExamples{812HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")813+ HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")814+ HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")815},816[](const RPCMethod& help, const JSONRPCRequest& request) -> UniValue817{818auto command{help.Arg<std::string_view>("command")};819if (command != "add" && command != "remove") {820throw std::runtime_error(help.ToString());821}822NodeContext& node = EnsureAnyNodeContext(request.context);823BanMan& banman = EnsureBanman(node);825CSubNet subNet;826CNetAddr netAddr;827std::string subnet_arg{help.Arg<std::string_view>("subnet")};828const bool isSubnet{subnet_arg.find('/') != subnet_arg.npos};830if (!isSubnet) {831const std::optional<CNetAddr> addr{LookupHost(subnet_arg, false)};832if (addr.has_value()) {833netAddr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0}));834}835} else {836subNet = LookupSubNet(subnet_arg);837}839if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) {840throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");841}843if (command == "add") {844if (isSubnet ? banman.IsBanned(subNet) : banman.IsBanned(netAddr)) {845throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");846}848int64_t banTime = 0; //use standard bantime if not specified849if (!request.params[2].isNull())850banTime = request.params[2].getInt<int64_t>();852const bool absolute{request.params[3].isNull() ? false : request.params[3].get_bool()};854if (absolute && banTime < GetTime()) {855throw JSONRPCError(RPC_INVALID_PARAMETER, "Error: Absolute timestamp is in the past");856}858if (isSubnet) {859banman.Ban(subNet, banTime, absolute);860if (node.connman) {861node.connman->DisconnectNode(subNet);862}863} else {864banman.Ban(netAddr, banTime, absolute);865if (node.connman) {866node.connman->DisconnectNode(netAddr);867}868}869} else if(command == "remove") {870if (!( isSubnet ? banman.Unban(subNet) : banman.Unban(netAddr) )) {871throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously manually banned.");872}873}874return UniValue::VNULL;875},876};877}879static RPCMethod listbanned()880{881return RPCMethod{882"listbanned",883"List all manually banned IPs/Subnets.\n",884{},885RPCResult{RPCResult::Type::ARR, "", "",886{887{RPCResult::Type::OBJ, "", "",888{889{RPCResult::Type::STR, "address", "The IP/Subnet of the banned node"},890{RPCResult::Type::NUM_TIME, "ban_created", "The " + UNIX_EPOCH_TIME + " the ban was created"},891{RPCResult::Type::NUM_TIME, "banned_until", "The " + UNIX_EPOCH_TIME + " the ban expires"},892{RPCResult::Type::NUM_TIME, "ban_duration", "The ban duration, in seconds"},893{RPCResult::Type::NUM_TIME, "time_remaining", "The time remaining until the ban expires, in seconds"},894}},895}},896RPCExamples{897HelpExampleCli("listbanned", "")898+ HelpExampleRpc("listbanned", "")899},900[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue901{902BanMan& banman = EnsureAnyBanman(request.context);904banmap_t banMap;905banman.GetBanned(banMap);906const int64_t current_time{GetTime()};908UniValue bannedAddresses(UniValue::VARR);909for (const auto& entry : banMap)910{911const CBanEntry& banEntry = entry.second;912UniValue rec(UniValue::VOBJ);913rec.pushKV("address", entry.first.ToString());914rec.pushKV("ban_created", banEntry.nCreateTime);915rec.pushKV("banned_until", banEntry.nBanUntil);916rec.pushKV("ban_duration", (banEntry.nBanUntil - banEntry.nCreateTime));917rec.pushKV("time_remaining", (banEntry.nBanUntil - current_time));919bannedAddresses.push_back(std::move(rec));920}922return bannedAddresses;923},924};925}927static RPCMethod clearbanned()928{929return RPCMethod{930"clearbanned",931"Clear all banned IPs.\n",932{},933RPCResult{RPCResult::Type::NONE, "", ""},934RPCExamples{935HelpExampleCli("clearbanned", "")936+ HelpExampleRpc("clearbanned", "")937},938[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue939{940BanMan& banman = EnsureAnyBanman(request.context);942banman.ClearBanned();944return UniValue::VNULL;945},946};947}949static RPCMethod setnetworkactive()950{951return RPCMethod{952"setnetworkactive",953"Disable/enable all p2p network activity.\n",954{955{"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},956},957RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"},958RPCExamples{""},959[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue960{961NodeContext& node = EnsureAnyNodeContext(request.context);962CConnman& connman = EnsureConnman(node);964connman.SetNetworkActive(request.params[0].get_bool());966return connman.GetNetworkActive();967},968};969}971static RPCMethod getnodeaddresses()972{973return RPCMethod{"getnodeaddresses",974"Return known addresses, after filtering for quality and recency.\n"975"These can potentially be used to find new peers in the network.\n"976"The total number of addresses known to the node may be higher.",977{978{"count", RPCArg::Type::NUM, RPCArg::Default{1}, "The maximum number of addresses to return. Specify 0 to return all known addresses."},979{"network", RPCArg::Type::STR, RPCArg::DefaultHint{"all networks"}, "Return only addresses of the specified network. Can be one of: " + Join(GetNetworkNames(), ", ") + "."},980},981RPCResult{982RPCResult::Type::ARR, "", "",983{984{RPCResult::Type::OBJ, "", "",985{986{RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " when the node was last seen"},987{RPCResult::Type::NUM, "services", "The services offered by the node"},988{RPCResult::Type::STR, "address", "The address of the node"},989{RPCResult::Type::NUM, "port", "The port number of the node"},990{RPCResult::Type::STR, "network", "The network (" + Join(GetNetworkNames(), ", ") + ") the node connected through"},991}},992}993},994RPCExamples{995HelpExampleCli("getnodeaddresses", "8")996+ HelpExampleCli("getnodeaddresses", "4 \"i2p\"")997+ HelpExampleCli("-named getnodeaddresses", "network=onion count=12")998+ HelpExampleRpc("getnodeaddresses", "8")999+ HelpExampleRpc("getnodeaddresses", "4, \"i2p\"")1000},