Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2021 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : #include <rpc/server.h>
# 6 : :
# 7 : : #include <addrman.h>
# 8 : : #include <banman.h>
# 9 : : #include <chainparams.h>
# 10 : : #include <clientversion.h>
# 11 : : #include <core_io.h>
# 12 : : #include <net_permissions.h>
# 13 : : #include <net_processing.h>
# 14 : : #include <net_types.h> // For banmap_t
# 15 : : #include <netbase.h>
# 16 : : #include <node/context.h>
# 17 : : #include <policy/settings.h>
# 18 : : #include <rpc/blockchain.h>
# 19 : : #include <rpc/protocol.h>
# 20 : : #include <rpc/server_util.h>
# 21 : : #include <rpc/util.h>
# 22 : : #include <sync.h>
# 23 : : #include <timedata.h>
# 24 : : #include <util/strencodings.h>
# 25 : : #include <util/string.h>
# 26 : : #include <util/time.h>
# 27 : : #include <util/translation.h>
# 28 : : #include <validation.h>
# 29 : : #include <version.h>
# 30 : : #include <warnings.h>
# 31 : :
# 32 : : #include <optional>
# 33 : :
# 34 : : #include <univalue.h>
# 35 : :
# 36 : : using node::NodeContext;
# 37 : :
# 38 : : const std::vector<std::string> CONNECTION_TYPE_DOC{
# 39 : : "outbound-full-relay (default automatic connections)",
# 40 : : "block-relay-only (does not relay transactions or addresses)",
# 41 : : "inbound (initiated by the peer)",
# 42 : : "manual (added via addnode RPC or -addnode/-connect configuration options)",
# 43 : : "addr-fetch (short-lived automatic connection for soliciting addresses)",
# 44 : : "feeler (short-lived automatic connection for testing addresses)"
# 45 : : };
# 46 : :
# 47 : : static RPCHelpMan getconnectioncount()
# 48 : 1641 : {
# 49 : 1641 : return RPCHelpMan{"getconnectioncount",
# 50 : 1641 : "\nReturns the number of connections to other nodes.\n",
# 51 : 1641 : {},
# 52 : 1641 : RPCResult{
# 53 : 1641 : RPCResult::Type::NUM, "", "The connection count"
# 54 : 1641 : },
# 55 : 1641 : RPCExamples{
# 56 : 1641 : HelpExampleCli("getconnectioncount", "")
# 57 : 1641 : + HelpExampleRpc("getconnectioncount", "")
# 58 : 1641 : },
# 59 : 1641 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 60 : 1641 : {
# 61 : 5 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 62 : 5 : const CConnman& connman = EnsureConnman(node);
# 63 : :
# 64 : 5 : return connman.GetNodeCount(ConnectionDirection::Both);
# 65 : 5 : },
# 66 : 1641 : };
# 67 : 1641 : }
# 68 : :
# 69 : : static RPCHelpMan ping()
# 70 : 1638 : {
# 71 : 1638 : return RPCHelpMan{"ping",
# 72 : 1638 : "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
# 73 : 1638 : "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
# 74 : 1638 : "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n",
# 75 : 1638 : {},
# 76 : 1638 : RPCResult{RPCResult::Type::NONE, "", ""},
# 77 : 1638 : RPCExamples{
# 78 : 1638 : HelpExampleCli("ping", "")
# 79 : 1638 : + HelpExampleRpc("ping", "")
# 80 : 1638 : },
# 81 : 1638 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 82 : 1638 : {
# 83 : 2 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 84 : 2 : PeerManager& peerman = EnsurePeerman(node);
# 85 : :
# 86 : : // Request that each node send a ping during next message processing pass
# 87 : 2 : peerman.SendPings();
# 88 : 2 : return UniValue::VNULL;
# 89 : 2 : },
# 90 : 1638 : };
# 91 : 1638 : }
# 92 : :
# 93 : : static RPCHelpMan getpeerinfo()
# 94 : 11308 : {
# 95 : 11308 : return RPCHelpMan{
# 96 : 11308 : "getpeerinfo",
# 97 : 11308 : "Returns data about each connected network peer as a json array of objects.",
# 98 : 11308 : {},
# 99 : 11308 : RPCResult{
# 100 : 11308 : RPCResult::Type::ARR, "", "",
# 101 : 11308 : {
# 102 : 11308 : {RPCResult::Type::OBJ, "", "",
# 103 : 11308 : {
# 104 : 11308 : {
# 105 : 11308 : {RPCResult::Type::NUM, "id", "Peer index"},
# 106 : 11308 : {RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"},
# 107 : 11308 : {RPCResult::Type::STR, "addrbind", /*optional=*/true, "(ip:port) Bind address of the connection to the peer"},
# 108 : 11308 : {RPCResult::Type::STR, "addrlocal", /*optional=*/true, "(ip:port) Local address as reported by the peer"},
# 109 : 11308 : {RPCResult::Type::STR, "network", "Network (" + Join(GetNetworkNames(/*append_unroutable=*/true), ", ") + ")"},
# 110 : 11308 : {RPCResult::Type::NUM, "mapped_as", /*optional=*/true, "The AS in the BGP route to the peer used for diversifying\n"
# 111 : 11308 : "peer selection (only available if the asmap config flag is set)"},
# 112 : 11308 : {RPCResult::Type::STR_HEX, "services", "The services offered"},
# 113 : 11308 : {RPCResult::Type::ARR, "servicesnames", "the services offered, in human-readable form",
# 114 : 11308 : {
# 115 : 11308 : {RPCResult::Type::STR, "SERVICE_NAME", "the service name if it is recognised"}
# 116 : 11308 : }},
# 117 : 11308 : {RPCResult::Type::BOOL, "relaytxes", /*optional=*/true, "Whether peer has asked us to relay transactions to it"},
# 118 : 11308 : {RPCResult::Type::NUM_TIME, "lastsend", "The " + UNIX_EPOCH_TIME + " of the last send"},
# 119 : 11308 : {RPCResult::Type::NUM_TIME, "lastrecv", "The " + UNIX_EPOCH_TIME + " of the last receive"},
# 120 : 11308 : {RPCResult::Type::NUM_TIME, "last_transaction", "The " + UNIX_EPOCH_TIME + " of the last valid transaction received from this peer"},
# 121 : 11308 : {RPCResult::Type::NUM_TIME, "last_block", "The " + UNIX_EPOCH_TIME + " of the last block received from this peer"},
# 122 : 11308 : {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
# 123 : 11308 : {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
# 124 : 11308 : {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
# 125 : 11308 : {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
# 126 : 11308 : {RPCResult::Type::NUM, "pingtime", /*optional=*/true, "ping time (if available)"},
# 127 : 11308 : {RPCResult::Type::NUM, "minping", /*optional=*/true, "minimum observed ping time (if any at all)"},
# 128 : 11308 : {RPCResult::Type::NUM, "pingwait", /*optional=*/true, "ping wait (if non-zero)"},
# 129 : 11308 : {RPCResult::Type::NUM, "version", "The peer version, such as 70001"},
# 130 : 11308 : {RPCResult::Type::STR, "subver", "The string version"},
# 131 : 11308 : {RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},
# 132 : 11308 : {RPCResult::Type::BOOL, "bip152_hb_to", "Whether we selected peer as (compact blocks) high-bandwidth peer"},
# 133 : 11308 : {RPCResult::Type::BOOL, "bip152_hb_from", "Whether peer selected us as (compact blocks) high-bandwidth peer"},
# 134 : 11308 : {RPCResult::Type::NUM, "startingheight", /*optional=*/true, "The starting height (block) of the peer"},
# 135 : 11308 : {RPCResult::Type::NUM, "presynced_headers", /*optional=*/true, "The current height of header pre-synchronization with this peer, or -1 if no low-work sync is in progress"},
# 136 : 11308 : {RPCResult::Type::NUM, "synced_headers", /*optional=*/true, "The last header we have in common with this peer"},
# 137 : 11308 : {RPCResult::Type::NUM, "synced_blocks", /*optional=*/true, "The last block we have in common with this peer"},
# 138 : 11308 : {RPCResult::Type::ARR, "inflight", /*optional=*/true, "",
# 139 : 11308 : {
# 140 : 11308 : {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
# 141 : 11308 : }},
# 142 : 11308 : {RPCResult::Type::BOOL, "addr_relay_enabled", /*optional=*/true, "Whether we participate in address relay with this peer"},
# 143 : 11308 : {RPCResult::Type::NUM, "addr_processed", /*optional=*/true, "The total number of addresses processed, excluding those dropped due to rate limiting"},
# 144 : 11308 : {RPCResult::Type::NUM, "addr_rate_limited", /*optional=*/true, "The total number of addresses dropped due to rate limiting"},
# 145 : 11308 : {RPCResult::Type::ARR, "permissions", "Any special permissions that have been granted to this peer",
# 146 : 11308 : {
# 147 : 11308 : {RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},
# 148 : 11308 : }},
# 149 : 11308 : {RPCResult::Type::NUM, "minfeefilter", /*optional=*/true, "The minimum fee rate for transactions this peer accepts"},
# 150 : 11308 : {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
# 151 : 11308 : {
# 152 : 11308 : {RPCResult::Type::NUM, "msg", "The total bytes sent aggregated by message type\n"
# 153 : 11308 : "When a message type is not listed in this json object, the bytes sent are 0.\n"
# 154 : 11308 : "Only known message types can appear as keys in the object."}
# 155 : 11308 : }},
# 156 : 11308 : {RPCResult::Type::OBJ_DYN, "bytesrecv_per_msg", "",
# 157 : 11308 : {
# 158 : 11308 : {RPCResult::Type::NUM, "msg", "The total bytes received aggregated by message type\n"
# 159 : 11308 : "When a message type is not listed in this json object, the bytes received are 0.\n"
# 160 : 11308 : "Only known message types can appear as keys in the object and all bytes received\n"
# 161 : 11308 : "of unknown message types are listed under '"+NET_MESSAGE_TYPE_OTHER+"'."}
# 162 : 11308 : }},
# 163 : 11308 : {RPCResult::Type::STR, "connection_type", "Type of connection: \n" + Join(CONNECTION_TYPE_DOC, ",\n") + ".\n"
# 164 : 11308 : "Please note this output is unlikely to be stable in upcoming releases as we iterate to\n"
# 165 : 11308 : "best capture connection behaviors."},
# 166 : 11308 : }},
# 167 : 11308 : }},
# 168 : 11308 : },
# 169 : 11308 : RPCExamples{
# 170 : 11308 : HelpExampleCli("getpeerinfo", "")
# 171 : 11308 : + HelpExampleRpc("getpeerinfo", "")
# 172 : 11308 : },
# 173 : 11308 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 174 : 11308 : {
# 175 : 9671 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 176 : 9671 : const CConnman& connman = EnsureConnman(node);
# 177 : 9671 : const PeerManager& peerman = EnsurePeerman(node);
# 178 : :
# 179 : 9671 : std::vector<CNodeStats> vstats;
# 180 : 9671 : connman.GetNodeStats(vstats);
# 181 : :
# 182 : 9671 : UniValue ret(UniValue::VARR);
# 183 : :
# 184 [ + + ]: 16359 : for (const CNodeStats& stats : vstats) {
# 185 : 16359 : UniValue obj(UniValue::VOBJ);
# 186 : 16359 : CNodeStateStats statestats;
# 187 : 16359 : bool fStateStats = peerman.GetNodeStateStats(stats.nodeid, statestats);
# 188 : 16359 : obj.pushKV("id", stats.nodeid);
# 189 : 16359 : obj.pushKV("addr", stats.m_addr_name);
# 190 [ + - ]: 16359 : if (stats.addrBind.IsValid()) {
# 191 : 16359 : obj.pushKV("addrbind", stats.addrBind.ToString());
# 192 : 16359 : }
# 193 [ + + ]: 16359 : if (!(stats.addrLocal.empty())) {
# 194 : 1982 : obj.pushKV("addrlocal", stats.addrLocal);
# 195 : 1982 : }
# 196 : 16359 : obj.pushKV("network", GetNetworkName(stats.m_network));
# 197 [ - + ]: 16359 : if (stats.m_mapped_as != 0) {
# 198 : 0 : obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
# 199 : 0 : }
# 200 [ + - ]: 16359 : ServiceFlags services{fStateStats ? statestats.their_services : ServiceFlags::NODE_NONE};
# 201 : 16359 : obj.pushKV("services", strprintf("%016x", services));
# 202 : 16359 : obj.pushKV("servicesnames", GetServicesNames(services));
# 203 : 16359 : obj.pushKV("lastsend", count_seconds(stats.m_last_send));
# 204 : 16359 : obj.pushKV("lastrecv", count_seconds(stats.m_last_recv));
# 205 : 16359 : obj.pushKV("last_transaction", count_seconds(stats.m_last_tx_time));
# 206 : 16359 : obj.pushKV("last_block", count_seconds(stats.m_last_block_time));
# 207 : 16359 : obj.pushKV("bytessent", stats.nSendBytes);
# 208 : 16359 : obj.pushKV("bytesrecv", stats.nRecvBytes);
# 209 : 16359 : obj.pushKV("conntime", count_seconds(stats.m_connected));
# 210 : 16359 : obj.pushKV("timeoffset", stats.nTimeOffset);
# 211 [ + + ]: 16359 : if (stats.m_last_ping_time > 0us) {
# 212 : 14005 : obj.pushKV("pingtime", Ticks<SecondsDouble>(stats.m_last_ping_time));
# 213 : 14005 : }
# 214 [ + + ]: 16359 : if (stats.m_min_ping_time < std::chrono::microseconds::max()) {
# 215 : 15894 : obj.pushKV("minping", Ticks<SecondsDouble>(stats.m_min_ping_time));
# 216 : 15894 : }
# 217 [ + - ][ + + ]: 16359 : if (fStateStats && statestats.m_ping_wait > 0s) {
# [ + + ]
# 218 : 39 : obj.pushKV("pingwait", Ticks<SecondsDouble>(statestats.m_ping_wait));
# 219 : 39 : }
# 220 : 16359 : obj.pushKV("version", stats.nVersion);
# 221 : : // Use the sanitized form of subver here, to avoid tricksy remote peers from
# 222 : : // corrupting or modifying the JSON output by putting special characters in
# 223 : : // their ver message.
# 224 : 16359 : obj.pushKV("subver", stats.cleanSubVer);
# 225 : 16359 : obj.pushKV("inbound", stats.fInbound);
# 226 : 16359 : obj.pushKV("bip152_hb_to", stats.m_bip152_highbandwidth_to);
# 227 : 16359 : obj.pushKV("bip152_hb_from", stats.m_bip152_highbandwidth_from);
# 228 [ + - ]: 16359 : if (fStateStats) {
# 229 : 16359 : obj.pushKV("startingheight", statestats.m_starting_height);
# 230 : 16359 : obj.pushKV("presynced_headers", statestats.presync_height);
# 231 : 16359 : obj.pushKV("synced_headers", statestats.nSyncHeight);
# 232 : 16359 : obj.pushKV("synced_blocks", statestats.nCommonHeight);
# 233 : 16359 : UniValue heights(UniValue::VARR);
# 234 [ + + ]: 16359 : for (const int height : statestats.vHeightInFlight) {
# 235 : 2015 : heights.push_back(height);
# 236 : 2015 : }
# 237 : 16359 : obj.pushKV("inflight", heights);
# 238 : 16359 : obj.pushKV("relaytxes", statestats.m_relay_txs);
# 239 : 16359 : obj.pushKV("minfeefilter", ValueFromAmount(statestats.m_fee_filter_received));
# 240 : 16359 : obj.pushKV("addr_relay_enabled", statestats.m_addr_relay_enabled);
# 241 : 16359 : obj.pushKV("addr_processed", statestats.m_addr_processed);
# 242 : 16359 : obj.pushKV("addr_rate_limited", statestats.m_addr_rate_limited);
# 243 : 16359 : }
# 244 : 16359 : UniValue permissions(UniValue::VARR);
# 245 [ + + ]: 16359 : for (const auto& permission : NetPermissions::ToStrings(stats.m_permissionFlags)) {
# 246 : 7938 : permissions.push_back(permission);
# 247 : 7938 : }
# 248 : 16359 : obj.pushKV("permissions", permissions);
# 249 : :
# 250 : 16359 : UniValue sendPerMsgType(UniValue::VOBJ);
# 251 [ + + ]: 213500 : for (const auto& i : stats.mapSendBytesPerMsgType) {
# 252 [ + - ]: 213500 : if (i.second > 0)
# 253 : 213500 : sendPerMsgType.pushKV(i.first, i.second);
# 254 : 213500 : }
# 255 : 16359 : obj.pushKV("bytessent_per_msg", sendPerMsgType);
# 256 : :
# 257 : 16359 : UniValue recvPerMsgType(UniValue::VOBJ);
# 258 [ + + ]: 572565 : for (const auto& i : stats.mapRecvBytesPerMsgType) {
# 259 [ + + ]: 572565 : if (i.second > 0)
# 260 : 204365 : recvPerMsgType.pushKV(i.first, i.second);
# 261 : 572565 : }
# 262 : 16359 : obj.pushKV("bytesrecv_per_msg", recvPerMsgType);
# 263 : 16359 : obj.pushKV("connection_type", ConnectionTypeAsString(stats.m_conn_type));
# 264 : :
# 265 : 16359 : ret.push_back(obj);
# 266 : 16359 : }
# 267 : :
# 268 : 9671 : return ret;
# 269 : 9671 : },
# 270 : 11308 : };
# 271 : 11308 : }
# 272 : :
# 273 : : static RPCHelpMan addnode()
# 274 : 2018 : {
# 275 : 2018 : return RPCHelpMan{"addnode",
# 276 : 2018 : "\nAttempts to add or remove a node from the addnode list.\n"
# 277 : 2018 : "Or try a connection to a node once.\n"
# 278 : 2018 : "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n"
# 279 : 2018 : "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n" +
# 280 : 2018 : strprintf("Addnode connections are limited to %u at a time", MAX_ADDNODE_CONNECTIONS) +
# 281 : 2018 : " and are counted separately from the -maxconnections limit.\n",
# 282 : 2018 : {
# 283 : 2018 : {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"},
# 284 : 2018 : {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once"},
# 285 : 2018 : },
# 286 : 2018 : RPCResult{RPCResult::Type::NONE, "", ""},
# 287 : 2018 : RPCExamples{
# 288 : 2018 : HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
# 289 : 2018 : + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
# 290 : 2018 : },
# 291 : 2018 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 292 : 2018 : {
# 293 : 382 : std::string strCommand;
# 294 [ + - ]: 382 : if (!request.params[1].isNull())
# 295 : 382 : strCommand = request.params[1].get_str();
# 296 [ + + ][ + + ]: 382 : if (strCommand != "onetry" && strCommand != "add" && strCommand != "remove") {
# [ - + ]
# 297 : 0 : throw std::runtime_error(
# 298 : 0 : self.ToString());
# 299 : 0 : }
# 300 : :
# 301 : 382 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 302 : 382 : CConnman& connman = EnsureConnman(node);
# 303 : :
# 304 : 382 : std::string strNode = request.params[0].get_str();
# 305 : :
# 306 [ + + ]: 382 : if (strCommand == "onetry")
# 307 : 378 : {
# 308 : 378 : CAddress addr;
# 309 : 378 : connman.OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), ConnectionType::MANUAL);
# 310 : 378 : return UniValue::VNULL;
# 311 : 378 : }
# 312 : :
# 313 [ + + ]: 4 : if (strCommand == "add")
# 314 : 2 : {
# 315 [ + + ]: 2 : if (!connman.AddNode(strNode)) {
# 316 : 1 : throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
# 317 : 1 : }
# 318 : 2 : }
# 319 [ + - ]: 2 : else if(strCommand == "remove")
# 320 : 2 : {
# 321 [ + + ]: 2 : if (!connman.RemoveAddedNode(strNode)) {
# 322 : 1 : throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node could not be removed. It has not been added previously.");
# 323 : 1 : }
# 324 : 2 : }
# 325 : :
# 326 : 2 : return UniValue::VNULL;
# 327 : 4 : },
# 328 : 2018 : };
# 329 : 2018 : }
# 330 : :
# 331 : : static RPCHelpMan addconnection()
# 332 : 1687 : {
# 333 : 1687 : return RPCHelpMan{"addconnection",
# 334 : 1687 : "\nOpen an outbound connection to a specified node. This RPC is for testing only.\n",
# 335 : 1687 : {
# 336 : 1687 : {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address and port to attempt connecting to."},
# 337 : 1687 : {"connection_type", RPCArg::Type::STR, RPCArg::Optional::NO, "Type of connection to open (\"outbound-full-relay\", \"block-relay-only\", \"addr-fetch\" or \"feeler\")."},
# 338 : 1687 : },
# 339 : 1687 : RPCResult{
# 340 : 1687 : RPCResult::Type::OBJ, "", "",
# 341 : 1687 : {
# 342 : 1687 : { RPCResult::Type::STR, "address", "Address of newly added connection." },
# 343 : 1687 : { RPCResult::Type::STR, "connection_type", "Type of connection opened." },
# 344 : 1687 : }},
# 345 : 1687 : RPCExamples{
# 346 : 1687 : HelpExampleCli("addconnection", "\"192.168.0.6:8333\" \"outbound-full-relay\"")
# 347 : 1687 : + HelpExampleRpc("addconnection", "\"192.168.0.6:8333\" \"outbound-full-relay\"")
# 348 : 1687 : },
# 349 : 1687 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 350 : 1687 : {
# 351 [ - + ]: 56 : if (Params().NetworkIDString() != CBaseChainParams::REGTEST) {
# 352 : 0 : throw std::runtime_error("addconnection is for regression testing (-regtest mode) only.");
# 353 : 0 : }
# 354 : :
# 355 : 56 : RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VSTR});
# 356 : 56 : const std::string address = request.params[0].get_str();
# 357 : 56 : const std::string conn_type_in{TrimString(request.params[1].get_str())};
# 358 : 56 : ConnectionType conn_type{};
# 359 [ + + ]: 56 : if (conn_type_in == "outbound-full-relay") {
# 360 : 34 : conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
# 361 [ + + ]: 34 : } else if (conn_type_in == "block-relay-only") {
# 362 : 19 : conn_type = ConnectionType::BLOCK_RELAY;
# 363 [ + + ]: 19 : } else if (conn_type_in == "addr-fetch") {
# 364 : 2 : conn_type = ConnectionType::ADDR_FETCH;
# 365 [ + - ]: 2 : } else if (conn_type_in == "feeler") {
# 366 : 1 : conn_type = ConnectionType::FEELER;
# 367 : 1 : } else {
# 368 : 0 : throw JSONRPCError(RPC_INVALID_PARAMETER, self.ToString());
# 369 : 0 : }
# 370 : :
# 371 : 56 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 372 : 56 : CConnman& connman = EnsureConnman(node);
# 373 : :
# 374 : 56 : const bool success = connman.AddConnection(address, conn_type);
# 375 [ - + ]: 56 : if (!success) {
# 376 : 0 : throw JSONRPCError(RPC_CLIENT_NODE_CAPACITY_REACHED, "Error: Already at capacity for specified connection type.");
# 377 : 0 : }
# 378 : :
# 379 : 56 : UniValue info(UniValue::VOBJ);
# 380 : 56 : info.pushKV("address", address);
# 381 : 56 : info.pushKV("connection_type", conn_type_in);
# 382 : :
# 383 : 56 : return info;
# 384 : 56 : },
# 385 : 1687 : };
# 386 : 1687 : }
# 387 : :
# 388 : : static RPCHelpMan disconnectnode()
# 389 : 1693 : {
# 390 : 1693 : return RPCHelpMan{"disconnectnode",
# 391 : 1693 : "\nImmediately disconnects from the specified peer node.\n"
# 392 : 1693 : "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
# 393 : 1693 : "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
# 394 : 1693 : {
# 395 : 1693 : {"address", RPCArg::Type::STR, RPCArg::DefaultHint{"fallback to nodeid"}, "The IP address/port of the node"},
# 396 : 1693 : {"nodeid", RPCArg::Type::NUM, RPCArg::DefaultHint{"fallback to address"}, "The node ID (see getpeerinfo for node IDs)"},
# 397 : 1693 : },
# 398 : 1693 : RPCResult{RPCResult::Type::NONE, "", ""},
# 399 : 1693 : RPCExamples{
# 400 : 1693 : HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
# 401 : 1693 : + HelpExampleCli("disconnectnode", "\"\" 1")
# 402 : 1693 : + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
# 403 : 1693 : + HelpExampleRpc("disconnectnode", "\"\", 1")
# 404 : 1693 : },
# 405 : 1693 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 406 : 1693 : {
# 407 : 57 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 408 : 57 : CConnman& connman = EnsureConnman(node);
# 409 : :
# 410 : 57 : bool success;
# 411 : 57 : const UniValue &address_arg = request.params[0];
# 412 : 57 : const UniValue &id_arg = request.params[1];
# 413 : :
# 414 [ + + ][ + + ]: 57 : if (!address_arg.isNull() && id_arg.isNull()) {
# 415 : : /* handle disconnect-by-address */
# 416 : 2 : success = connman.DisconnectNode(address_arg.get_str());
# 417 [ + - ][ + + ]: 55 : } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
# [ + - ][ - + ]
# 418 : : /* handle disconnect-by-id */
# 419 : 54 : NodeId nodeid = (NodeId) id_arg.getInt<int64_t>();
# 420 : 54 : success = connman.DisconnectNode(nodeid);
# 421 : 54 : } else {
# 422 : 1 : throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
# 423 : 1 : }
# 424 : :
# 425 [ + + ]: 56 : if (!success) {
# 426 : 1 : throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
# 427 : 1 : }
# 428 : :
# 429 : 55 : return UniValue::VNULL;
# 430 : 56 : },
# 431 : 1693 : };
# 432 : 1693 : }
# 433 : :
# 434 : : static RPCHelpMan getaddednodeinfo()
# 435 : 1640 : {
# 436 : 1640 : return RPCHelpMan{"getaddednodeinfo",
# 437 : 1640 : "\nReturns information about the given added node, or all added nodes\n"
# 438 : 1640 : "(note that onetry addnodes are not listed here)\n",
# 439 : 1640 : {
# 440 : 1640 : {"node", RPCArg::Type::STR, RPCArg::DefaultHint{"all nodes"}, "If provided, return information about this specific node, otherwise all nodes are returned."},
# 441 : 1640 : },
# 442 : 1640 : RPCResult{
# 443 : 1640 : RPCResult::Type::ARR, "", "",
# 444 : 1640 : {
# 445 : 1640 : {RPCResult::Type::OBJ, "", "",
# 446 : 1640 : {
# 447 : 1640 : {RPCResult::Type::STR, "addednode", "The node IP address or name (as provided to addnode)"},
# 448 : 1640 : {RPCResult::Type::BOOL, "connected", "If connected"},
# 449 : 1640 : {RPCResult::Type::ARR, "addresses", "Only when connected = true",
# 450 : 1640 : {
# 451 : 1640 : {RPCResult::Type::OBJ, "", "",
# 452 : 1640 : {
# 453 : 1640 : {RPCResult::Type::STR, "address", "The bitcoin server IP and port we're connected to"},
# 454 : 1640 : {RPCResult::Type::STR, "connected", "connection, inbound or outbound"},
# 455 : 1640 : }},
# 456 : 1640 : }},
# 457 : 1640 : }},
# 458 : 1640 : }
# 459 : 1640 : },
# 460 : 1640 : RPCExamples{
# 461 : 1640 : HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
# 462 : 1640 : + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")
# 463 : 1640 : },
# 464 : 1640 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 465 : 1640 : {
# 466 : 4 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 467 : 4 : const CConnman& connman = EnsureConnman(node);
# 468 : :
# 469 : 4 : std::vector<AddedNodeInfo> vInfo = connman.GetAddedNodeInfo();
# 470 : :
# 471 [ + + ]: 4 : if (!request.params[0].isNull()) {
# 472 : 2 : bool found = false;
# 473 [ + + ]: 2 : for (const AddedNodeInfo& info : vInfo) {
# 474 [ + - ]: 1 : if (info.strAddedNode == request.params[0].get_str()) {
# 475 : 1 : vInfo.assign(1, info);
# 476 : 1 : found = true;
# 477 : 1 : break;
# 478 : 1 : }
# 479 : 1 : }
# 480 [ + + ]: 2 : if (!found) {
# 481 : 1 : throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
# 482 : 1 : }
# 483 : 2 : }
# 484 : :
# 485 : 3 : UniValue ret(UniValue::VARR);
# 486 : :
# 487 [ + + ]: 3 : for (const AddedNodeInfo& info : vInfo) {
# 488 : 1 : UniValue obj(UniValue::VOBJ);
# 489 : 1 : obj.pushKV("addednode", info.strAddedNode);
# 490 : 1 : obj.pushKV("connected", info.fConnected);
# 491 : 1 : UniValue addresses(UniValue::VARR);
# 492 [ - + ]: 1 : if (info.fConnected) {
# 493 : 0 : UniValue address(UniValue::VOBJ);
# 494 : 0 : address.pushKV("address", info.resolvedAddress.ToString());
# 495 [ # # ]: 0 : address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
# 496 : 0 : addresses.push_back(address);
# 497 : 0 : }
# 498 : 1 : obj.pushKV("addresses", addresses);
# 499 : 1 : ret.push_back(obj);
# 500 : 1 : }
# 501 : :
# 502 : 3 : return ret;
# 503 : 4 : },
# 504 : 1640 : };
# 505 : 1640 : }
# 506 : :
# 507 : : static RPCHelpMan getnettotals()
# 508 : 1644 : {
# 509 : 1644 : return RPCHelpMan{"getnettotals",
# 510 : 1644 : "\nReturns information about network traffic, including bytes in, bytes out,\n"
# 511 : 1644 : "and current time.\n",
# 512 : 1644 : {},
# 513 : 1644 : RPCResult{
# 514 : 1644 : RPCResult::Type::OBJ, "", "",
# 515 : 1644 : {
# 516 : 1644 : {RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"},
# 517 : 1644 : {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},
# 518 : 1644 : {RPCResult::Type::NUM_TIME, "timemillis", "Current " + UNIX_EPOCH_TIME + " in milliseconds"},
# 519 : 1644 : {RPCResult::Type::OBJ, "uploadtarget", "",
# 520 : 1644 : {
# 521 : 1644 : {RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"},
# 522 : 1644 : {RPCResult::Type::NUM, "target", "Target in bytes"},
# 523 : 1644 : {RPCResult::Type::BOOL, "target_reached", "True if target is reached"},
# 524 : 1644 : {RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"},
# 525 : 1644 : {RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"},
# 526 : 1644 : {RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"},
# 527 : 1644 : }},
# 528 : 1644 : }
# 529 : 1644 : },
# 530 : 1644 : RPCExamples{
# 531 : 1644 : HelpExampleCli("getnettotals", "")
# 532 : 1644 : + HelpExampleRpc("getnettotals", "")
# 533 : 1644 : },
# 534 : 1644 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 535 : 1644 : {
# 536 : 8 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 537 : 8 : const CConnman& connman = EnsureConnman(node);
# 538 : :
# 539 : 8 : UniValue obj(UniValue::VOBJ);
# 540 : 8 : obj.pushKV("totalbytesrecv", connman.GetTotalBytesRecv());
# 541 : 8 : obj.pushKV("totalbytessent", connman.GetTotalBytesSent());
# 542 : 8 : obj.pushKV("timemillis", GetTimeMillis());
# 543 : :
# 544 : 8 : UniValue outboundLimit(UniValue::VOBJ);
# 545 : 8 : outboundLimit.pushKV("timeframe", count_seconds(connman.GetMaxOutboundTimeframe()));
# 546 : 8 : outboundLimit.pushKV("target", connman.GetMaxOutboundTarget());
# 547 : 8 : outboundLimit.pushKV("target_reached", connman.OutboundTargetReached(false));
# 548 : 8 : outboundLimit.pushKV("serve_historical_blocks", !connman.OutboundTargetReached(true));
# 549 : 8 : outboundLimit.pushKV("bytes_left_in_cycle", connman.GetOutboundTargetBytesLeft());
# 550 : 8 : outboundLimit.pushKV("time_left_in_cycle", count_seconds(connman.GetMaxOutboundTimeLeftInCycle()));
# 551 : 8 : obj.pushKV("uploadtarget", outboundLimit);
# 552 : 8 : return obj;
# 553 : 8 : },
# 554 : 1644 : };
# 555 : 1644 : }
# 556 : :
# 557 : : static UniValue GetNetworksInfo()
# 558 : 79 : {
# 559 : 79 : UniValue networks(UniValue::VARR);
# 560 [ + + ]: 632 : for (int n = 0; n < NET_MAX; ++n) {
# 561 : 553 : enum Network network = static_cast<enum Network>(n);
# 562 [ + + ][ + + ]: 553 : if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
# 563 : 395 : Proxy proxy;
# 564 : 395 : UniValue obj(UniValue::VOBJ);
# 565 : 395 : GetProxy(network, proxy);
# 566 : 395 : obj.pushKV("name", GetNetworkName(network));
# 567 : 395 : obj.pushKV("limited", !IsReachable(network));
# 568 : 395 : obj.pushKV("reachable", IsReachable(network));
# 569 [ + + ]: 395 : obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
# 570 : 395 : obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
# 571 : 395 : networks.push_back(obj);
# 572 : 395 : }
# 573 : 79 : return networks;
# 574 : 79 : }
# 575 : :
# 576 : : static RPCHelpMan getnetworkinfo()
# 577 : 1716 : {
# 578 : 1716 : return RPCHelpMan{"getnetworkinfo",
# 579 : 1716 : "Returns an object containing various state info regarding P2P networking.\n",
# 580 : 1716 : {},
# 581 : 1716 : RPCResult{
# 582 : 1716 : RPCResult::Type::OBJ, "", "",
# 583 : 1716 : {
# 584 : 1716 : {RPCResult::Type::NUM, "version", "the server version"},
# 585 : 1716 : {RPCResult::Type::STR, "subversion", "the server subversion string"},
# 586 : 1716 : {RPCResult::Type::NUM, "protocolversion", "the protocol version"},
# 587 : 1716 : {RPCResult::Type::STR_HEX, "localservices", "the services we offer to the network"},
# 588 : 1716 : {RPCResult::Type::ARR, "localservicesnames", "the services we offer to the network, in human-readable form",
# 589 : 1716 : {
# 590 : 1716 : {RPCResult::Type::STR, "SERVICE_NAME", "the service name"},
# 591 : 1716 : }},
# 592 : 1716 : {RPCResult::Type::BOOL, "localrelay", "true if transaction relay is requested from peers"},
# 593 : 1716 : {RPCResult::Type::NUM, "timeoffset", "the time offset"},
# 594 : 1716 : {RPCResult::Type::NUM, "connections", "the total number of connections"},
# 595 : 1716 : {RPCResult::Type::NUM, "connections_in", "the number of inbound connections"},
# 596 : 1716 : {RPCResult::Type::NUM, "connections_out", "the number of outbound connections"},
# 597 : 1716 : {RPCResult::Type::BOOL, "networkactive", "whether p2p networking is enabled"},
# 598 : 1716 : {RPCResult::Type::ARR, "networks", "information per network",
# 599 : 1716 : {
# 600 : 1716 : {RPCResult::Type::OBJ, "", "",
# 601 : 1716 : {
# 602 : 1716 : {RPCResult::Type::STR, "name", "network (" + Join(GetNetworkNames(), ", ") + ")"},
# 603 : 1716 : {RPCResult::Type::BOOL, "limited", "is the network limited using -onlynet?"},
# 604 : 1716 : {RPCResult::Type::BOOL, "reachable", "is the network reachable?"},
# 605 : 1716 : {RPCResult::Type::STR, "proxy", "(\"host:port\") the proxy that is used for this network, or empty if none"},
# 606 : 1716 : {RPCResult::Type::BOOL, "proxy_randomize_credentials", "Whether randomized credentials are used"},
# 607 : 1716 : }},
# 608 : 1716 : }},
# 609 : 1716 : {RPCResult::Type::NUM, "relayfee", "minimum relay fee rate for transactions in " + CURRENCY_UNIT + "/kvB"},
# 610 : 1716 : {RPCResult::Type::NUM, "incrementalfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"},
# 611 : 1716 : {RPCResult::Type::ARR, "localaddresses", "list of local addresses",
# 612 : 1716 : {
# 613 : 1716 : {RPCResult::Type::OBJ, "", "",
# 614 : 1716 : {
# 615 : 1716 : {RPCResult::Type::STR, "address", "network address"},
# 616 : 1716 : {RPCResult::Type::NUM, "port", "network port"},
# 617 : 1716 : {RPCResult::Type::NUM, "score", "relative score"},
# 618 : 1716 : }},
# 619 : 1716 : }},
# 620 : 1716 : {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"},
# 621 : 1716 : }
# 622 : 1716 : },
# 623 : 1716 : RPCExamples{
# 624 : 1716 : HelpExampleCli("getnetworkinfo", "")
# 625 : 1716 : + HelpExampleRpc("getnetworkinfo", "")
# 626 : 1716 : },
# 627 : 1716 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 628 : 1716 : {
# 629 : 79 : LOCK(cs_main);
# 630 : 79 : UniValue obj(UniValue::VOBJ);
# 631 : 79 : obj.pushKV("version", CLIENT_VERSION);
# 632 : 79 : obj.pushKV("subversion", strSubVersion);
# 633 : 79 : obj.pushKV("protocolversion",PROTOCOL_VERSION);
# 634 : 79 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 635 [ + - ]: 79 : if (node.connman) {
# 636 : 79 : ServiceFlags services = node.connman->GetLocalServices();
# 637 : 79 : obj.pushKV("localservices", strprintf("%016x", services));
# 638 : 79 : obj.pushKV("localservicesnames", GetServicesNames(services));
# 639 : 79 : }
# 640 [ + - ]: 79 : if (node.peerman) {
# 641 : 79 : obj.pushKV("localrelay", !node.peerman->IgnoresIncomingTxs());
# 642 : 79 : }
# 643 : 79 : obj.pushKV("timeoffset", GetTimeOffset());
# 644 [ + - ]: 79 : if (node.connman) {
# 645 : 79 : obj.pushKV("networkactive", node.connman->GetNetworkActive());
# 646 : 79 : obj.pushKV("connections", node.connman->GetNodeCount(ConnectionDirection::Both));
# 647 : 79 : obj.pushKV("connections_in", node.connman->GetNodeCount(ConnectionDirection::In));
# 648 : 79 : obj.pushKV("connections_out", node.connman->GetNodeCount(ConnectionDirection::Out));
# 649 : 79 : }
# 650 : 79 : obj.pushKV("networks", GetNetworksInfo());
# 651 [ + - ]: 79 : if (node.mempool) {
# 652 : : // Those fields can be deprecated, to be replaced by the getmempoolinfo fields
# 653 : 79 : obj.pushKV("relayfee", ValueFromAmount(node.mempool->m_min_relay_feerate.GetFeePerK()));
# 654 : 79 : obj.pushKV("incrementalfee", ValueFromAmount(node.mempool->m_incremental_relay_feerate.GetFeePerK()));
# 655 : 79 : }
# 656 : 79 : UniValue localAddresses(UniValue::VARR);
# 657 : 79 : {
# 658 : 79 : LOCK(g_maplocalhost_mutex);
# 659 [ - + ]: 79 : for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost)
# 660 : 0 : {
# 661 : 0 : UniValue rec(UniValue::VOBJ);
# 662 : 0 : rec.pushKV("address", item.first.ToString());
# 663 : 0 : rec.pushKV("port", item.second.nPort);
# 664 : 0 : rec.pushKV("score", item.second.nScore);
# 665 : 0 : localAddresses.push_back(rec);
# 666 : 0 : }
# 667 : 79 : }
# 668 : 79 : obj.pushKV("localaddresses", localAddresses);
# 669 : 79 : obj.pushKV("warnings", GetWarnings(false).original);
# 670 : 79 : return obj;
# 671 : 79 : },
# 672 : 1716 : };
# 673 : 1716 : }
# 674 : :
# 675 : : static RPCHelpMan setban()
# 676 : 1676 : {
# 677 : 1676 : return RPCHelpMan{"setban",
# 678 : 1676 : "\nAttempts to add or remove an IP/Subnet from the banned list.\n",
# 679 : 1676 : {
# 680 : 1676 : {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
# 681 : 1676 : {"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"},
# 682 : 1676 : {"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)"},
# 683 : 1676 : {"absolute", RPCArg::Type::BOOL, RPCArg::Default{false}, "If set, the bantime must be an absolute timestamp expressed in " + UNIX_EPOCH_TIME},
# 684 : 1676 : },
# 685 : 1676 : RPCResult{RPCResult::Type::NONE, "", ""},
# 686 : 1676 : RPCExamples{
# 687 : 1676 : HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
# 688 : 1676 : + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
# 689 : 1676 : + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
# 690 : 1676 : },
# 691 : 1676 : [&](const RPCHelpMan& help, const JSONRPCRequest& request) -> UniValue
# 692 : 1676 : {
# 693 : 38 : std::string strCommand;
# 694 [ + - ]: 38 : if (!request.params[1].isNull())
# 695 : 38 : strCommand = request.params[1].get_str();
# 696 [ + + ][ - + ]: 38 : if (strCommand != "add" && strCommand != "remove") {
# 697 : 0 : throw std::runtime_error(help.ToString());
# 698 : 0 : }
# 699 : 38 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 700 [ - + ]: 38 : if (!node.banman) {
# 701 : 0 : throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
# 702 : 0 : }
# 703 : :
# 704 : 38 : CSubNet subNet;
# 705 : 38 : CNetAddr netAddr;
# 706 : 38 : bool isSubnet = false;
# 707 : :
# 708 [ + + ]: 38 : if (request.params[0].get_str().find('/') != std::string::npos)
# 709 : 18 : isSubnet = true;
# 710 : :
# 711 [ + + ]: 38 : if (!isSubnet) {
# 712 : 20 : CNetAddr resolved;
# 713 : 20 : LookupHost(request.params[0].get_str(), resolved, false);
# 714 : 20 : netAddr = resolved;
# 715 : 20 : }
# 716 : 18 : else
# 717 : 18 : LookupSubNet(request.params[0].get_str(), subNet);
# 718 : :
# 719 [ + + ][ + + ]: 38 : if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
# 720 : 3 : throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");
# 721 : :
# 722 [ + + ]: 35 : if (strCommand == "add")
# 723 : 27 : {
# 724 [ + + ][ + + ]: 27 : if (isSubnet ? node.banman->IsBanned(subNet) : node.banman->IsBanned(netAddr)) {
# 725 : 5 : throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
# 726 : 5 : }
# 727 : :
# 728 : 22 : int64_t banTime = 0; //use standard bantime if not specified
# 729 [ + + ]: 22 : if (!request.params[2].isNull())
# 730 : 6 : banTime = request.params[2].getInt<int64_t>();
# 731 : :
# 732 : 22 : bool absolute = false;
# 733 [ + + ]: 22 : if (request.params[3].isTrue())
# 734 : 2 : absolute = true;
# 735 : :
# 736 [ + + ]: 22 : if (isSubnet) {
# 737 : 14 : node.banman->Ban(subNet, banTime, absolute);
# 738 [ + - ]: 14 : if (node.connman) {
# 739 : 14 : node.connman->DisconnectNode(subNet);
# 740 : 14 : }
# 741 : 14 : } else {
# 742 : 8 : node.banman->Ban(netAddr, banTime, absolute);
# 743 [ + - ]: 8 : if (node.connman) {
# 744 : 8 : node.connman->DisconnectNode(netAddr);
# 745 : 8 : }
# 746 : 8 : }
# 747 : 22 : }
# 748 [ + - ]: 8 : else if(strCommand == "remove")
# 749 : 8 : {
# 750 [ + + ][ + + ]: 8 : if (!( isSubnet ? node.banman->Unban(subNet) : node.banman->Unban(netAddr) )) {
# 751 : 1 : throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously manually banned.");
# 752 : 1 : }
# 753 : 8 : }
# 754 : 29 : return UniValue::VNULL;
# 755 : 35 : },
# 756 : 1676 : };
# 757 : 1676 : }
# 758 : :
# 759 : : static RPCHelpMan listbanned()
# 760 : 1675 : {
# 761 : 1675 : return RPCHelpMan{"listbanned",
# 762 : 1675 : "\nList all manually banned IPs/Subnets.\n",
# 763 : 1675 : {},
# 764 : 1675 : RPCResult{RPCResult::Type::ARR, "", "",
# 765 : 1675 : {
# 766 : 1675 : {RPCResult::Type::OBJ, "", "",
# 767 : 1675 : {
# 768 : 1675 : {RPCResult::Type::STR, "address", "The IP/Subnet of the banned node"},
# 769 : 1675 : {RPCResult::Type::NUM_TIME, "ban_created", "The " + UNIX_EPOCH_TIME + " the ban was created"},
# 770 : 1675 : {RPCResult::Type::NUM_TIME, "banned_until", "The " + UNIX_EPOCH_TIME + " the ban expires"},
# 771 : 1675 : {RPCResult::Type::NUM_TIME, "ban_duration", "The ban duration, in seconds"},
# 772 : 1675 : {RPCResult::Type::NUM_TIME, "time_remaining", "The time remaining until the ban expires, in seconds"},
# 773 : 1675 : }},
# 774 : 1675 : }},
# 775 : 1675 : RPCExamples{
# 776 : 1675 : HelpExampleCli("listbanned", "")
# 777 : 1675 : + HelpExampleRpc("listbanned", "")
# 778 : 1675 : },
# 779 : 1675 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 780 : 1675 : {
# 781 : 39 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 782 [ - + ]: 39 : if(!node.banman) {
# 783 : 0 : throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
# 784 : 0 : }
# 785 : :
# 786 : 39 : banmap_t banMap;
# 787 : 39 : node.banman->GetBanned(banMap);
# 788 : 39 : const int64_t current_time{GetTime()};
# 789 : :
# 790 : 39 : UniValue bannedAddresses(UniValue::VARR);
# 791 [ + + ]: 39 : for (const auto& entry : banMap)
# 792 : 33 : {
# 793 : 33 : const CBanEntry& banEntry = entry.second;
# 794 : 33 : UniValue rec(UniValue::VOBJ);
# 795 : 33 : rec.pushKV("address", entry.first.ToString());
# 796 : 33 : rec.pushKV("ban_created", banEntry.nCreateTime);
# 797 : 33 : rec.pushKV("banned_until", banEntry.nBanUntil);
# 798 : 33 : rec.pushKV("ban_duration", (banEntry.nBanUntil - banEntry.nCreateTime));
# 799 : 33 : rec.pushKV("time_remaining", (banEntry.nBanUntil - current_time));
# 800 : :
# 801 : 33 : bannedAddresses.push_back(rec);
# 802 : 33 : }
# 803 : :
# 804 : 39 : return bannedAddresses;
# 805 : 39 : },
# 806 : 1675 : };
# 807 : 1675 : }
# 808 : :
# 809 : : static RPCHelpMan clearbanned()
# 810 : 1649 : {
# 811 : 1649 : return RPCHelpMan{"clearbanned",
# 812 : 1649 : "\nClear all banned IPs.\n",
# 813 : 1649 : {},
# 814 : 1649 : RPCResult{RPCResult::Type::NONE, "", ""},
# 815 : 1649 : RPCExamples{
# 816 : 1649 : HelpExampleCli("clearbanned", "")
# 817 : 1649 : + HelpExampleRpc("clearbanned", "")
# 818 : 1649 : },
# 819 : 1649 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 820 : 1649 : {
# 821 : 13 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 822 [ - + ]: 13 : if (!node.banman) {
# 823 : 0 : throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
# 824 : 0 : }
# 825 : :
# 826 : 13 : node.banman->ClearBanned();
# 827 : :
# 828 : 13 : return UniValue::VNULL;
# 829 : 13 : },
# 830 : 1649 : };
# 831 : 1649 : }
# 832 : :
# 833 : : static RPCHelpMan setnetworkactive()
# 834 : 1643 : {
# 835 : 1643 : return RPCHelpMan{"setnetworkactive",
# 836 : 1643 : "\nDisable/enable all p2p network activity.\n",
# 837 : 1643 : {
# 838 : 1643 : {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},
# 839 : 1643 : },
# 840 : 1643 : RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"},
# 841 : 1643 : RPCExamples{""},
# 842 : 1643 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 843 : 1643 : {
# 844 : 7 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 845 : 7 : CConnman& connman = EnsureConnman(node);
# 846 : :
# 847 : 7 : connman.SetNetworkActive(request.params[0].get_bool());
# 848 : :
# 849 : 7 : return connman.GetNetworkActive();
# 850 : 7 : },
# 851 : 1643 : };
# 852 : 1643 : }
# 853 : :
# 854 : : static RPCHelpMan getnodeaddresses()
# 855 : 1657 : {
# 856 : 1657 : return RPCHelpMan{"getnodeaddresses",
# 857 : 1657 : "Return known addresses, after filtering for quality and recency.\n"
# 858 : 1657 : "These can potentially be used to find new peers in the network.\n"
# 859 : 1657 : "The total number of addresses known to the node may be higher.",
# 860 : 1657 : {
# 861 : 1657 : {"count", RPCArg::Type::NUM, RPCArg::Default{1}, "The maximum number of addresses to return. Specify 0 to return all known addresses."},
# 862 : 1657 : {"network", RPCArg::Type::STR, RPCArg::DefaultHint{"all networks"}, "Return only addresses of the specified network. Can be one of: " + Join(GetNetworkNames(), ", ") + "."},
# 863 : 1657 : },
# 864 : 1657 : RPCResult{
# 865 : 1657 : RPCResult::Type::ARR, "", "",
# 866 : 1657 : {
# 867 : 1657 : {RPCResult::Type::OBJ, "", "",
# 868 : 1657 : {
# 869 : 1657 : {RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " when the node was last seen"},
# 870 : 1657 : {RPCResult::Type::NUM, "services", "The services offered by the node"},
# 871 : 1657 : {RPCResult::Type::STR, "address", "The address of the node"},
# 872 : 1657 : {RPCResult::Type::NUM, "port", "The port number of the node"},
# 873 : 1657 : {RPCResult::Type::STR, "network", "The network (" + Join(GetNetworkNames(), ", ") + ") the node connected through"},
# 874 : 1657 : }},
# 875 : 1657 : }
# 876 : 1657 : },
# 877 : 1657 : RPCExamples{
# 878 : 1657 : HelpExampleCli("getnodeaddresses", "8")
# 879 : 1657 : + HelpExampleCli("getnodeaddresses", "4 \"i2p\"")
# 880 : 1657 : + HelpExampleCli("-named getnodeaddresses", "network=onion count=12")
# 881 : 1657 : + HelpExampleRpc("getnodeaddresses", "8")
# 882 : 1657 : + HelpExampleRpc("getnodeaddresses", "4, \"i2p\"")
# 883 : 1657 : },
# 884 : 1657 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 885 : 1657 : {
# 886 : 21 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 887 : 21 : const CConnman& connman = EnsureConnman(node);
# 888 : :
# 889 [ + + ]: 21 : const int count{request.params[0].isNull() ? 1 : request.params[0].getInt<int>()};
# 890 [ + + ]: 21 : if (count < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range");
# 891 : :
# 892 [ + + ]: 20 : const std::optional<Network> network{request.params[1].isNull() ? std::nullopt : std::optional<Network>{ParseNetwork(request.params[1].get_str())}};
# 893 [ + + ]: 20 : if (network == NET_UNROUTABLE) {
# 894 : 1 : throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Network not recognized: %s", request.params[1].get_str()));
# 895 : 1 : }
# 896 : :
# 897 : : // returns a shuffled list of CAddress
# 898 : 19 : const std::vector<CAddress> vAddr{connman.GetAddresses(count, /*max_pct=*/0, network)};
# 899 : 19 : UniValue ret(UniValue::VARR);
# 900 : :
# 901 [ + + ]: 18800 : for (const CAddress& addr : vAddr) {
# 902 : 18800 : UniValue obj(UniValue::VOBJ);
# 903 : 18800 : obj.pushKV("time", int64_t{TicksSinceEpoch<std::chrono::seconds>(addr.nTime)});
# 904 : 18800 : obj.pushKV("services", (uint64_t)addr.nServices);
# 905 : 18800 : obj.pushKV("address", addr.ToStringIP());
# 906 : 18800 : obj.pushKV("port", addr.GetPort());
# 907 : 18800 : obj.pushKV("network", GetNetworkName(addr.GetNetClass()));
# 908 : 18800 : ret.push_back(obj);
# 909 : 18800 : }
# 910 : 19 : return ret;
# 911 : 20 : },
# 912 : 1657 : };
# 913 : 1657 : }
# 914 : :
# 915 : : static RPCHelpMan addpeeraddress()
# 916 : 23749 : {
# 917 : 23749 : return RPCHelpMan{"addpeeraddress",
# 918 : 23749 : "\nAdd the address of a potential peer to the address manager. This RPC is for testing only.\n",
# 919 : 23749 : {
# 920 : 23749 : {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address of the peer"},
# 921 : 23749 : {"port", RPCArg::Type::NUM, RPCArg::Optional::NO, "The port of the peer"},
# 922 : 23749 : {"tried", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, attempt to add the peer to the tried addresses table"},
# 923 : 23749 : },
# 924 : 23749 : RPCResult{
# 925 : 23749 : RPCResult::Type::OBJ, "", "",
# 926 : 23749 : {
# 927 : 23749 : {RPCResult::Type::BOOL, "success", "whether the peer address was successfully added to the address manager"},
# 928 : 23749 : },
# 929 : 23749 : },
# 930 : 23749 : RPCExamples{
# 931 : 23749 : HelpExampleCli("addpeeraddress", "\"1.2.3.4\" 8333 true")
# 932 : 23749 : + HelpExampleRpc("addpeeraddress", "\"1.2.3.4\", 8333, true")
# 933 : 23749 : },
# 934 : 23749 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
# 935 : 23749 : {
# 936 : 22118 : NodeContext& node = EnsureAnyNodeContext(request.context);
# 937 [ - + ]: 22118 : if (!node.addrman) {
# 938 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
# 939 : 0 : }
# 940 : :
# 941 : 22118 : const std::string& addr_string{request.params[0].get_str()};
# 942 : 22118 : const auto port{request.params[1].getInt<uint16_t>()};
# 943 : 22118 : const bool tried{request.params[2].isTrue()};
# 944 : :
# 945 : 22118 : UniValue obj(UniValue::VOBJ);
# 946 : 22118 : CNetAddr net_addr;
# 947 : 22118 : bool success{false};
# 948 : :
# 949 [ + + ]: 22118 : if (LookupHost(addr_string, net_addr, false)) {
# 950 : 22115 : CAddress address{{net_addr, port}, ServiceFlags{NODE_NETWORK | NODE_WITNESS}};
# 951 : 22115 : address.nTime = Now<NodeSeconds>();
# 952 : : // The source address is set equal to the address. This is equivalent to the peer
# 953 : : // announcing itself.
# 954 [ + + ]: 22115 : if (node.addrman->Add({address}, address)) {
# 955 : 19529 : success = true;
# 956 [ + + ]: 19529 : if (tried) {
# 957 : : // Attempt to move the address to the tried addresses table.
# 958 : 2 : node.addrman->Good(address);
# 959 : 2 : }
# 960 : 19529 : }
# 961 : 22115 : }
# 962 : :
# 963 : 22118 : obj.pushKV("success", success);
# 964 : 22118 : return obj;
# 965 : 22118 : },
# 966 : 23749 : };
# 967 : 23749 : }
# 968 : :
# 969 : : void RegisterNetRPCCommands(CRPCTable& t)
# 970 : 1022 : {
# 971 : 1022 : static const CRPCCommand commands[]{
# 972 : 1022 : {"network", &getconnectioncount},
# 973 : 1022 : {"network", &ping},
# 974 : 1022 : {"network", &getpeerinfo},
# 975 : 1022 : {"network", &addnode},
# 976 : 1022 : {"network", &disconnectnode},
# 977 : 1022 : {"network", &getaddednodeinfo},
# 978 : 1022 : {"network", &getnettotals},
# 979 : 1022 : {"network", &getnetworkinfo},
# 980 : 1022 : {"network", &setban},
# 981 : 1022 : {"network", &listbanned},
# 982 : 1022 : {"network", &clearbanned},
# 983 : 1022 : {"network", &setnetworkactive},
# 984 : 1022 : {"network", &getnodeaddresses},
# 985 : 1022 : {"hidden", &addconnection},
# 986 : 1022 : {"hidden", &addpeeraddress},
# 987 : 1022 : };
# 988 [ + + ]: 15330 : for (const auto& c : commands) {
# 989 : 15330 : t.appendCommand(c.name, &c);
# 990 : 15330 : }
# 991 : 1022 : }
|