Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2020 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 <banman.h>
# 8 : : #include <clientversion.h>
# 9 : : #include <core_io.h>
# 10 : : #include <net.h>
# 11 : : #include <net_permissions.h>
# 12 : : #include <net_processing.h>
# 13 : : #include <net_types.h> // For banmap_t
# 14 : : #include <netbase.h>
# 15 : : #include <node/context.h>
# 16 : : #include <policy/settings.h>
# 17 : : #include <rpc/blockchain.h>
# 18 : : #include <rpc/protocol.h>
# 19 : : #include <rpc/util.h>
# 20 : : #include <sync.h>
# 21 : : #include <timedata.h>
# 22 : : #include <util/strencodings.h>
# 23 : : #include <util/string.h>
# 24 : : #include <util/system.h>
# 25 : : #include <util/translation.h>
# 26 : : #include <validation.h>
# 27 : : #include <version.h>
# 28 : : #include <warnings.h>
# 29 : :
# 30 : : #include <univalue.h>
# 31 : :
# 32 : : static UniValue getconnectioncount(const JSONRPCRequest& request)
# 33 : 8 : {
# 34 : 8 : RPCHelpMan{"getconnectioncount",
# 35 : 8 : "\nReturns the number of connections to other nodes.\n",
# 36 : 8 : {},
# 37 : 8 : RPCResult{
# 38 : 8 : RPCResult::Type::NUM, "", "The connection count"
# 39 : 8 : },
# 40 : 8 : RPCExamples{
# 41 : 8 : HelpExampleCli("getconnectioncount", "")
# 42 : 8 : + HelpExampleRpc("getconnectioncount", "")
# 43 : 8 : },
# 44 : 8 : }.Check(request);
# 45 : 8 :
# 46 : 8 : NodeContext& node = EnsureNodeContext(request.context);
# 47 : 8 : if(!node.connman)
# 48 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
# 49 : 8 :
# 50 : 8 : return (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
# 51 : 8 : }
# 52 : :
# 53 : : static UniValue ping(const JSONRPCRequest& request)
# 54 : 5 : {
# 55 : 5 : RPCHelpMan{"ping",
# 56 : 5 : "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
# 57 : 5 : "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
# 58 : 5 : "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n",
# 59 : 5 : {},
# 60 : 5 : RPCResult{RPCResult::Type::NONE, "", ""},
# 61 : 5 : RPCExamples{
# 62 : 5 : HelpExampleCli("ping", "")
# 63 : 5 : + HelpExampleRpc("ping", "")
# 64 : 5 : },
# 65 : 5 : }.Check(request);
# 66 : 5 :
# 67 : 5 : NodeContext& node = EnsureNodeContext(request.context);
# 68 : 5 : if(!node.connman)
# 69 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
# 70 : 5 :
# 71 : 5 : // Request that each node send a ping during next message processing pass
# 72 : 5 : node.connman->ForEachNode([](CNode* pnode) {
# 73 : 3 : pnode->fPingQueued = true;
# 74 : 3 : });
# 75 : 5 : return NullUniValue;
# 76 : 5 : }
# 77 : :
# 78 : : static UniValue getpeerinfo(const JSONRPCRequest& request)
# 79 : 3088 : {
# 80 : 3088 : RPCHelpMan{"getpeerinfo",
# 81 : 3088 : "\nReturns data about each connected network node as a json array of objects.\n",
# 82 : 3088 : {},
# 83 : 3088 : RPCResult{
# 84 : 3088 : RPCResult::Type::ARR, "", "",
# 85 : 3088 : {
# 86 : 3088 : {RPCResult::Type::OBJ, "", "",
# 87 : 3088 : {
# 88 : 3088 : {
# 89 : 3088 : {RPCResult::Type::NUM, "id", "Peer index"},
# 90 : 3088 : {RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"},
# 91 : 3088 : {RPCResult::Type::STR, "addrbind", "(ip:port) Bind address of the connection to the peer"},
# 92 : 3088 : {RPCResult::Type::STR, "addrlocal", "(ip:port) Local address as reported by the peer"},
# 93 : 3088 : {RPCResult::Type::NUM, "mapped_as", "The AS in the BGP route to the peer used for diversifying\n"
# 94 : 3088 : "peer selection (only available if the asmap config flag is set)"},
# 95 : 3088 : {RPCResult::Type::STR_HEX, "services", "The services offered"},
# 96 : 3088 : {RPCResult::Type::ARR, "servicesnames", "the services offered, in human-readable form",
# 97 : 3088 : {
# 98 : 3088 : {RPCResult::Type::STR, "SERVICE_NAME", "the service name if it is recognised"}
# 99 : 3088 : }},
# 100 : 3088 : {RPCResult::Type::BOOL, "relaytxes", "Whether peer has asked us to relay transactions to it"},
# 101 : 3088 : {RPCResult::Type::NUM_TIME, "lastsend", "The " + UNIX_EPOCH_TIME + " of the last send"},
# 102 : 3088 : {RPCResult::Type::NUM_TIME, "lastrecv", "The " + UNIX_EPOCH_TIME + " of the last receive"},
# 103 : 3088 : {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
# 104 : 3088 : {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
# 105 : 3088 : {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
# 106 : 3088 : {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
# 107 : 3088 : {RPCResult::Type::NUM, "pingtime", "ping time (if available)"},
# 108 : 3088 : {RPCResult::Type::NUM, "minping", "minimum observed ping time (if any at all)"},
# 109 : 3088 : {RPCResult::Type::NUM, "pingwait", "ping wait (if non-zero)"},
# 110 : 3088 : {RPCResult::Type::NUM, "version", "The peer version, such as 70001"},
# 111 : 3088 : {RPCResult::Type::STR, "subver", "The string version"},
# 112 : 3088 : {RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},
# 113 : 3088 : {RPCResult::Type::BOOL, "addnode", "Whether connection was due to addnode/-connect or if it was an automatic/inbound connection"},
# 114 : 3088 : {RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"},
# 115 : 3088 : {RPCResult::Type::NUM, "banscore", "The ban score (DEPRECATED, returned only if config option -deprecatedrpc=banscore is passed)"},
# 116 : 3088 : {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
# 117 : 3088 : {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},
# 118 : 3088 : {RPCResult::Type::ARR, "inflight", "",
# 119 : 3088 : {
# 120 : 3088 : {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
# 121 : 3088 : }},
# 122 : 3088 : {RPCResult::Type::BOOL, "whitelisted", "Whether the peer is whitelisted"},
# 123 : 3088 : {RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
# 124 : 3088 : {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
# 125 : 3088 : {
# 126 : 3088 : {RPCResult::Type::NUM, "msg", "The total bytes sent aggregated by message type\n"
# 127 : 3088 : "When a message type is not listed in this json object, the bytes sent are 0.\n"
# 128 : 3088 : "Only known message types can appear as keys in the object."}
# 129 : 3088 : }},
# 130 : 3088 : {RPCResult::Type::OBJ, "bytesrecv_per_msg", "",
# 131 : 3088 : {
# 132 : 3088 : {RPCResult::Type::NUM, "msg", "The total bytes received aggregated by message type\n"
# 133 : 3088 : "When a message type is not listed in this json object, the bytes received are 0.\n"
# 134 : 3088 : "Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'."}
# 135 : 3088 : }},
# 136 : 3088 : }},
# 137 : 3088 : }},
# 138 : 3088 : },
# 139 : 3088 : RPCExamples{
# 140 : 3088 : HelpExampleCli("getpeerinfo", "")
# 141 : 3088 : + HelpExampleRpc("getpeerinfo", "")
# 142 : 3088 : },
# 143 : 3088 : }.Check(request);
# 144 : 3088 :
# 145 : 3088 : NodeContext& node = EnsureNodeContext(request.context);
# 146 : 3088 : if(!node.connman)
# 147 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
# 148 : 3088 :
# 149 : 3088 : std::vector<CNodeStats> vstats;
# 150 : 3088 : node.connman->GetNodeStats(vstats);
# 151 : 3088 :
# 152 : 3088 : UniValue ret(UniValue::VARR);
# 153 : 3088 :
# 154 : 5306 : for (const CNodeStats& stats : vstats) {
# 155 : 5306 : UniValue obj(UniValue::VOBJ);
# 156 : 5306 : CNodeStateStats statestats;
# 157 : 5306 : bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
# 158 : 5306 : obj.pushKV("id", stats.nodeid);
# 159 : 5306 : obj.pushKV("addr", stats.addrName);
# 160 : 5306 : if (!(stats.addrLocal.empty()))
# 161 : 240 : obj.pushKV("addrlocal", stats.addrLocal);
# 162 : 5306 : if (stats.addrBind.IsValid())
# 163 : 5306 : obj.pushKV("addrbind", stats.addrBind.ToString());
# 164 : 5306 : if (stats.m_mapped_as != 0) {
# 165 : 0 : obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
# 166 : 0 : }
# 167 : 5306 : obj.pushKV("services", strprintf("%016x", stats.nServices));
# 168 : 5306 : obj.pushKV("servicesnames", GetServicesNames(stats.nServices));
# 169 : 5306 : obj.pushKV("relaytxes", stats.fRelayTxes);
# 170 : 5306 : obj.pushKV("lastsend", stats.nLastSend);
# 171 : 5306 : obj.pushKV("lastrecv", stats.nLastRecv);
# 172 : 5306 : obj.pushKV("bytessent", stats.nSendBytes);
# 173 : 5306 : obj.pushKV("bytesrecv", stats.nRecvBytes);
# 174 : 5306 : obj.pushKV("conntime", stats.nTimeConnected);
# 175 : 5306 : obj.pushKV("timeoffset", stats.nTimeOffset);
# 176 : 5306 : if (stats.m_ping_usec > 0) {
# 177 : 5035 : obj.pushKV("pingtime", ((double)stats.m_ping_usec) / 1e6);
# 178 : 5035 : }
# 179 : 5306 : if (stats.m_min_ping_usec < std::numeric_limits<int64_t>::max()) {
# 180 : 5035 : obj.pushKV("minping", ((double)stats.m_min_ping_usec) / 1e6);
# 181 : 5035 : }
# 182 : 5306 : if (stats.m_ping_wait_usec > 0) {
# 183 : 18 : obj.pushKV("pingwait", ((double)stats.m_ping_wait_usec) / 1e6);
# 184 : 18 : }
# 185 : 5306 : obj.pushKV("version", stats.nVersion);
# 186 : 5306 : // Use the sanitized form of subver here, to avoid tricksy remote peers from
# 187 : 5306 : // corrupting or modifying the JSON output by putting special characters in
# 188 : 5306 : // their ver message.
# 189 : 5306 : obj.pushKV("subver", stats.cleanSubVer);
# 190 : 5306 : obj.pushKV("inbound", stats.fInbound);
# 191 : 5306 : obj.pushKV("addnode", stats.m_manual_connection);
# 192 : 5306 : obj.pushKV("startingheight", stats.nStartingHeight);
# 193 : 5306 : if (fStateStats) {
# 194 : 5306 : if (IsDeprecatedRPCEnabled("banscore")) {
# 195 : 4 : // banscore is deprecated in v0.21 for removal in v0.22
# 196 : 4 : obj.pushKV("banscore", statestats.nMisbehavior);
# 197 : 4 : }
# 198 : 5306 : obj.pushKV("synced_headers", statestats.nSyncHeight);
# 199 : 5306 : obj.pushKV("synced_blocks", statestats.nCommonHeight);
# 200 : 5306 : UniValue heights(UniValue::VARR);
# 201 : 5306 : for (const int height : statestats.vHeightInFlight) {
# 202 : 934 : heights.push_back(height);
# 203 : 934 : }
# 204 : 5306 : obj.pushKV("inflight", heights);
# 205 : 5306 : }
# 206 : 5306 : obj.pushKV("whitelisted", stats.m_legacyWhitelisted);
# 207 : 5306 : UniValue permissions(UniValue::VARR);
# 208 : 5306 : for (const auto& permission : NetPermissions::ToStrings(stats.m_permissionFlags)) {
# 209 : 2468 : permissions.push_back(permission);
# 210 : 2468 : }
# 211 : 5306 : obj.pushKV("permissions", permissions);
# 212 : 5306 : obj.pushKV("minfeefilter", ValueFromAmount(stats.minFeeFilter));
# 213 : 5306 :
# 214 : 5306 : UniValue sendPerMsgCmd(UniValue::VOBJ);
# 215 : 67146 : for (const auto& i : stats.mapSendBytesPerMsgCmd) {
# 216 : 67146 : if (i.second > 0)
# 217 : 67146 : sendPerMsgCmd.pushKV(i.first, i.second);
# 218 : 67146 : }
# 219 : 5306 : obj.pushKV("bytessent_per_msg", sendPerMsgCmd);
# 220 : 5306 :
# 221 : 5306 : UniValue recvPerMsgCmd(UniValue::VOBJ);
# 222 : 175098 : for (const auto& i : stats.mapRecvBytesPerMsgCmd) {
# 223 : 175098 : if (i.second > 0)
# 224 : 65201 : recvPerMsgCmd.pushKV(i.first, i.second);
# 225 : 175098 : }
# 226 : 5306 : obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd);
# 227 : 5306 :
# 228 : 5306 : ret.push_back(obj);
# 229 : 5306 : }
# 230 : 3088 :
# 231 : 3088 : return ret;
# 232 : 3088 : }
# 233 : :
# 234 : : static UniValue addnode(const JSONRPCRequest& request)
# 235 : 251 : {
# 236 : 251 : std::string strCommand;
# 237 : 251 : if (!request.params[1].isNull())
# 238 : 248 : strCommand = request.params[1].get_str();
# 239 : 251 : if (request.fHelp || request.params.size() != 2 ||
# 240 : 251 : (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
# 241 : 3 : throw std::runtime_error(
# 242 : 3 : RPCHelpMan{"addnode",
# 243 : 3 : "\nAttempts to add or remove a node from the addnode list.\n"
# 244 : 3 : "Or try a connection to a node once.\n"
# 245 : 3 : "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n"
# 246 : 3 : "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n",
# 247 : 3 : {
# 248 : 3 : {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"},
# 249 : 3 : {"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"},
# 250 : 3 : },
# 251 : 3 : RPCResult{RPCResult::Type::NONE, "", ""},
# 252 : 3 : RPCExamples{
# 253 : 3 : HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
# 254 : 3 : + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
# 255 : 3 : },
# 256 : 3 : }.ToString());
# 257 : 248 :
# 258 : 248 : NodeContext& node = EnsureNodeContext(request.context);
# 259 : 248 : if(!node.connman)
# 260 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
# 261 : 248 :
# 262 : 248 : std::string strNode = request.params[0].get_str();
# 263 : 248 :
# 264 : 248 : if (strCommand == "onetry")
# 265 : 247 : {
# 266 : 247 : CAddress addr;
# 267 : 247 : node.connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), ConnectionType::MANUAL);
# 268 : 247 : return NullUniValue;
# 269 : 247 : }
# 270 : 1 :
# 271 : 1 : if (strCommand == "add")
# 272 : 1 : {
# 273 : 1 : if(!node.connman->AddNode(strNode))
# 274 : 0 : throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
# 275 : 0 : }
# 276 : 0 : else if(strCommand == "remove")
# 277 : 0 : {
# 278 : 0 : if(!node.connman->RemoveAddedNode(strNode))
# 279 : 0 : throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
# 280 : 1 : }
# 281 : 1 :
# 282 : 1 : return NullUniValue;
# 283 : 1 : }
# 284 : :
# 285 : : static UniValue disconnectnode(const JSONRPCRequest& request)
# 286 : 31 : {
# 287 : 31 : RPCHelpMan{"disconnectnode",
# 288 : 31 : "\nImmediately disconnects from the specified peer node.\n"
# 289 : 31 : "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
# 290 : 31 : "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
# 291 : 31 : {
# 292 : 31 : {"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"},
# 293 : 31 : {"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"},
# 294 : 31 : },
# 295 : 31 : RPCResult{RPCResult::Type::NONE, "", ""},
# 296 : 31 : RPCExamples{
# 297 : 31 : HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
# 298 : 31 : + HelpExampleCli("disconnectnode", "\"\" 1")
# 299 : 31 : + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
# 300 : 31 : + HelpExampleRpc("disconnectnode", "\"\", 1")
# 301 : 31 : },
# 302 : 31 : }.Check(request);
# 303 : 31 :
# 304 : 31 : NodeContext& node = EnsureNodeContext(request.context);
# 305 : 31 : if(!node.connman)
# 306 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
# 307 : 31 :
# 308 : 31 : bool success;
# 309 : 31 : const UniValue &address_arg = request.params[0];
# 310 : 31 : const UniValue &id_arg = request.params[1];
# 311 : 31 :
# 312 : 31 : if (!address_arg.isNull() && id_arg.isNull()) {
# 313 : 2 : /* handle disconnect-by-address */
# 314 : 2 : success = node.connman->DisconnectNode(address_arg.get_str());
# 315 : 29 : } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
# 316 : 25 : /* handle disconnect-by-id */
# 317 : 25 : NodeId nodeid = (NodeId) id_arg.get_int64();
# 318 : 25 : success = node.connman->DisconnectNode(nodeid);
# 319 : 25 : } else {
# 320 : 4 : throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
# 321 : 4 : }
# 322 : 27 :
# 323 : 27 : if (!success) {
# 324 : 1 : throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
# 325 : 1 : }
# 326 : 26 :
# 327 : 26 : return NullUniValue;
# 328 : 26 : }
# 329 : :
# 330 : : static UniValue getaddednodeinfo(const JSONRPCRequest& request)
# 331 : 6 : {
# 332 : 6 : RPCHelpMan{"getaddednodeinfo",
# 333 : 6 : "\nReturns information about the given added node, or all added nodes\n"
# 334 : 6 : "(note that onetry addnodes are not listed here)\n",
# 335 : 6 : {
# 336 : 6 : {"node", RPCArg::Type::STR, /* default */ "all nodes", "If provided, return information about this specific node, otherwise all nodes are returned."},
# 337 : 6 : },
# 338 : 6 : RPCResult{
# 339 : 6 : RPCResult::Type::ARR, "", "",
# 340 : 6 : {
# 341 : 6 : {RPCResult::Type::OBJ, "", "",
# 342 : 6 : {
# 343 : 6 : {RPCResult::Type::STR, "addednode", "The node IP address or name (as provided to addnode)"},
# 344 : 6 : {RPCResult::Type::BOOL, "connected", "If connected"},
# 345 : 6 : {RPCResult::Type::ARR, "addresses", "Only when connected = true",
# 346 : 6 : {
# 347 : 6 : {RPCResult::Type::OBJ, "", "",
# 348 : 6 : {
# 349 : 6 : {RPCResult::Type::STR, "address", "The bitcoin server IP and port we're connected to"},
# 350 : 6 : {RPCResult::Type::STR, "connected", "connection, inbound or outbound"},
# 351 : 6 : }},
# 352 : 6 : }},
# 353 : 6 : }},
# 354 : 6 : }
# 355 : 6 : },
# 356 : 6 : RPCExamples{
# 357 : 6 : HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
# 358 : 6 : + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")
# 359 : 6 : },
# 360 : 6 : }.Check(request);
# 361 : 6 :
# 362 : 6 : NodeContext& node = EnsureNodeContext(request.context);
# 363 : 6 : if(!node.connman)
# 364 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
# 365 : 6 :
# 366 : 6 : std::vector<AddedNodeInfo> vInfo = node.connman->GetAddedNodeInfo();
# 367 : 6 :
# 368 : 6 : if (!request.params[0].isNull()) {
# 369 : 2 : bool found = false;
# 370 : 2 : for (const AddedNodeInfo& info : vInfo) {
# 371 : 2 : if (info.strAddedNode == request.params[0].get_str()) {
# 372 : 1 : vInfo.assign(1, info);
# 373 : 1 : found = true;
# 374 : 1 : break;
# 375 : 1 : }
# 376 : 2 : }
# 377 : 2 : if (!found) {
# 378 : 1 : throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
# 379 : 1 : }
# 380 : 5 : }
# 381 : 5 :
# 382 : 5 : UniValue ret(UniValue::VARR);
# 383 : 5 :
# 384 : 5 : for (const AddedNodeInfo& info : vInfo) {
# 385 : 1 : UniValue obj(UniValue::VOBJ);
# 386 : 1 : obj.pushKV("addednode", info.strAddedNode);
# 387 : 1 : obj.pushKV("connected", info.fConnected);
# 388 : 1 : UniValue addresses(UniValue::VARR);
# 389 : 1 : if (info.fConnected) {
# 390 : 0 : UniValue address(UniValue::VOBJ);
# 391 : 0 : address.pushKV("address", info.resolvedAddress.ToString());
# 392 : 0 : address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
# 393 : 0 : addresses.push_back(address);
# 394 : 0 : }
# 395 : 1 : obj.pushKV("addresses", addresses);
# 396 : 1 : ret.push_back(obj);
# 397 : 1 : }
# 398 : 5 :
# 399 : 5 : return ret;
# 400 : 5 : }
# 401 : :
# 402 : : static UniValue getnettotals(const JSONRPCRequest& request)
# 403 : 11 : {
# 404 : 11 : RPCHelpMan{"getnettotals",
# 405 : 11 : "\nReturns information about network traffic, including bytes in, bytes out,\n"
# 406 : 11 : "and current time.\n",
# 407 : 11 : {},
# 408 : 11 : RPCResult{
# 409 : 11 : RPCResult::Type::OBJ, "", "",
# 410 : 11 : {
# 411 : 11 : {RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"},
# 412 : 11 : {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},
# 413 : 11 : {RPCResult::Type::NUM_TIME, "timemillis", "Current UNIX time in milliseconds"},
# 414 : 11 : {RPCResult::Type::OBJ, "uploadtarget", "",
# 415 : 11 : {
# 416 : 11 : {RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"},
# 417 : 11 : {RPCResult::Type::NUM, "target", "Target in bytes"},
# 418 : 11 : {RPCResult::Type::BOOL, "target_reached", "True if target is reached"},
# 419 : 11 : {RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"},
# 420 : 11 : {RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"},
# 421 : 11 : {RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"},
# 422 : 11 : }},
# 423 : 11 : }
# 424 : 11 : },
# 425 : 11 : RPCExamples{
# 426 : 11 : HelpExampleCli("getnettotals", "")
# 427 : 11 : + HelpExampleRpc("getnettotals", "")
# 428 : 11 : },
# 429 : 11 : }.Check(request);
# 430 : 11 : NodeContext& node = EnsureNodeContext(request.context);
# 431 : 11 : if(!node.connman)
# 432 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
# 433 : 11 :
# 434 : 11 : UniValue obj(UniValue::VOBJ);
# 435 : 11 : obj.pushKV("totalbytesrecv", node.connman->GetTotalBytesRecv());
# 436 : 11 : obj.pushKV("totalbytessent", node.connman->GetTotalBytesSent());
# 437 : 11 : obj.pushKV("timemillis", GetTimeMillis());
# 438 : 11 :
# 439 : 11 : UniValue outboundLimit(UniValue::VOBJ);
# 440 : 11 : outboundLimit.pushKV("timeframe", node.connman->GetMaxOutboundTimeframe());
# 441 : 11 : outboundLimit.pushKV("target", node.connman->GetMaxOutboundTarget());
# 442 : 11 : outboundLimit.pushKV("target_reached", node.connman->OutboundTargetReached(false));
# 443 : 11 : outboundLimit.pushKV("serve_historical_blocks", !node.connman->OutboundTargetReached(true));
# 444 : 11 : outboundLimit.pushKV("bytes_left_in_cycle", node.connman->GetOutboundTargetBytesLeft());
# 445 : 11 : outboundLimit.pushKV("time_left_in_cycle", node.connman->GetMaxOutboundTimeLeftInCycle());
# 446 : 11 : obj.pushKV("uploadtarget", outboundLimit);
# 447 : 11 : return obj;
# 448 : 11 : }
# 449 : :
# 450 : : static UniValue GetNetworksInfo()
# 451 : 47 : {
# 452 : 47 : UniValue networks(UniValue::VARR);
# 453 : 282 : for(int n=0; n<NET_MAX; ++n)
# 454 : 235 : {
# 455 : 235 : enum Network network = static_cast<enum Network>(n);
# 456 : 235 : if(network == NET_UNROUTABLE || network == NET_INTERNAL)
# 457 : 94 : continue;
# 458 : 141 : proxyType proxy;
# 459 : 141 : UniValue obj(UniValue::VOBJ);
# 460 : 141 : GetProxy(network, proxy);
# 461 : 141 : obj.pushKV("name", GetNetworkName(network));
# 462 : 141 : obj.pushKV("limited", !IsReachable(network));
# 463 : 141 : obj.pushKV("reachable", IsReachable(network));
# 464 : 141 : obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
# 465 : 141 : obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
# 466 : 141 : networks.push_back(obj);
# 467 : 141 : }
# 468 : 47 : return networks;
# 469 : 47 : }
# 470 : :
# 471 : : static UniValue getnetworkinfo(const JSONRPCRequest& request)
# 472 : 50 : {
# 473 : 50 : RPCHelpMan{"getnetworkinfo",
# 474 : 50 : "Returns an object containing various state info regarding P2P networking.\n",
# 475 : 50 : {},
# 476 : 50 : RPCResult{
# 477 : 50 : RPCResult::Type::OBJ, "", "",
# 478 : 50 : {
# 479 : 50 : {RPCResult::Type::NUM, "version", "the server version"},
# 480 : 50 : {RPCResult::Type::STR, "subversion", "the server subversion string"},
# 481 : 50 : {RPCResult::Type::NUM, "protocolversion", "the protocol version"},
# 482 : 50 : {RPCResult::Type::STR_HEX, "localservices", "the services we offer to the network"},
# 483 : 50 : {RPCResult::Type::ARR, "localservicesnames", "the services we offer to the network, in human-readable form",
# 484 : 50 : {
# 485 : 50 : {RPCResult::Type::STR, "SERVICE_NAME", "the service name"},
# 486 : 50 : }},
# 487 : 50 : {RPCResult::Type::BOOL, "localrelay", "true if transaction relay is requested from peers"},
# 488 : 50 : {RPCResult::Type::NUM, "timeoffset", "the time offset"},
# 489 : 50 : {RPCResult::Type::NUM, "connections", "the number of connections"},
# 490 : 50 : {RPCResult::Type::BOOL, "networkactive", "whether p2p networking is enabled"},
# 491 : 50 : {RPCResult::Type::ARR, "networks", "information per network",
# 492 : 50 : {
# 493 : 50 : {RPCResult::Type::OBJ, "", "",
# 494 : 50 : {
# 495 : 50 : {RPCResult::Type::STR, "name", "network (ipv4, ipv6 or onion)"},
# 496 : 50 : {RPCResult::Type::BOOL, "limited", "is the network limited using -onlynet?"},
# 497 : 50 : {RPCResult::Type::BOOL, "reachable", "is the network reachable?"},
# 498 : 50 : {RPCResult::Type::STR, "proxy", "(\"host:port\") the proxy that is used for this network, or empty if none"},
# 499 : 50 : {RPCResult::Type::BOOL, "proxy_randomize_credentials", "Whether randomized credentials are used"},
# 500 : 50 : }},
# 501 : 50 : }},
# 502 : 50 : {RPCResult::Type::NUM, "relayfee", "minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB"},
# 503 : 50 : {RPCResult::Type::NUM, "incrementalfee", "minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB"},
# 504 : 50 : {RPCResult::Type::ARR, "localaddresses", "list of local addresses",
# 505 : 50 : {
# 506 : 50 : {RPCResult::Type::OBJ, "", "",
# 507 : 50 : {
# 508 : 50 : {RPCResult::Type::STR, "address", "network address"},
# 509 : 50 : {RPCResult::Type::NUM, "port", "network port"},
# 510 : 50 : {RPCResult::Type::NUM, "score", "relative score"},
# 511 : 50 : }},
# 512 : 50 : }},
# 513 : 50 : {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"},
# 514 : 50 : }
# 515 : 50 : },
# 516 : 50 : RPCExamples{
# 517 : 50 : HelpExampleCli("getnetworkinfo", "")
# 518 : 50 : + HelpExampleRpc("getnetworkinfo", "")
# 519 : 50 : },
# 520 : 50 : }.Check(request);
# 521 : 50 :
# 522 : 50 : LOCK(cs_main);
# 523 : 50 : UniValue obj(UniValue::VOBJ);
# 524 : 50 : obj.pushKV("version", CLIENT_VERSION);
# 525 : 50 : obj.pushKV("subversion", strSubVersion);
# 526 : 50 : obj.pushKV("protocolversion",PROTOCOL_VERSION);
# 527 : 50 : NodeContext& node = EnsureNodeContext(request.context);
# 528 : 50 : if (node.connman) {
# 529 : 47 : ServiceFlags services = node.connman->GetLocalServices();
# 530 : 47 : obj.pushKV("localservices", strprintf("%016x", services));
# 531 : 47 : obj.pushKV("localservicesnames", GetServicesNames(services));
# 532 : 47 : }
# 533 : 50 : obj.pushKV("localrelay", g_relay_txes);
# 534 : 50 : obj.pushKV("timeoffset", GetTimeOffset());
# 535 : 50 : if (node.connman) {
# 536 : 47 : obj.pushKV("networkactive", node.connman->GetNetworkActive());
# 537 : 47 : obj.pushKV("connections", (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
# 538 : 47 : }
# 539 : 50 : obj.pushKV("networks", GetNetworksInfo());
# 540 : 50 : obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
# 541 : 50 : obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
# 542 : 50 : UniValue localAddresses(UniValue::VARR);
# 543 : 50 : {
# 544 : 50 : LOCK(cs_mapLocalHost);
# 545 : 50 : for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost)
# 546 : 6 : {
# 547 : 6 : UniValue rec(UniValue::VOBJ);
# 548 : 6 : rec.pushKV("address", item.first.ToString());
# 549 : 6 : rec.pushKV("port", item.second.nPort);
# 550 : 6 : rec.pushKV("score", item.second.nScore);
# 551 : 6 : localAddresses.push_back(rec);
# 552 : 6 : }
# 553 : 50 : }
# 554 : 50 : obj.pushKV("localaddresses", localAddresses);
# 555 : 50 : obj.pushKV("warnings", GetWarnings(false).original);
# 556 : 50 : return obj;
# 557 : 50 : }
# 558 : :
# 559 : : static UniValue setban(const JSONRPCRequest& request)
# 560 : 41 : {
# 561 : 41 : const RPCHelpMan help{"setban",
# 562 : 41 : "\nAttempts to add or remove an IP/Subnet from the banned list.\n",
# 563 : 41 : {
# 564 : 41 : {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
# 565 : 41 : {"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"},
# 566 : 41 : {"bantime", RPCArg::Type::NUM, /* 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)"},
# 567 : 41 : {"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp expressed in " + UNIX_EPOCH_TIME},
# 568 : 41 : },
# 569 : 41 : RPCResult{RPCResult::Type::NONE, "", ""},
# 570 : 41 : RPCExamples{
# 571 : 41 : HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
# 572 : 41 : + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
# 573 : 41 : + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
# 574 : 41 : },
# 575 : 41 : };
# 576 : 41 : std::string strCommand;
# 577 : 41 : if (!request.params[1].isNull())
# 578 : 36 : strCommand = request.params[1].get_str();
# 579 : 41 : if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) {
# 580 : 5 : throw std::runtime_error(help.ToString());
# 581 : 5 : }
# 582 : 36 : NodeContext& node = EnsureNodeContext(request.context);
# 583 : 36 : if (!node.banman) {
# 584 : 0 : throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
# 585 : 0 : }
# 586 : 36 :
# 587 : 36 : CSubNet subNet;
# 588 : 36 : CNetAddr netAddr;
# 589 : 36 : bool isSubnet = false;
# 590 : 36 :
# 591 : 36 : if (request.params[0].get_str().find('/') != std::string::npos)
# 592 : 18 : isSubnet = true;
# 593 : 36 :
# 594 : 36 : if (!isSubnet) {
# 595 : 18 : CNetAddr resolved;
# 596 : 18 : LookupHost(request.params[0].get_str(), resolved, false);
# 597 : 18 : netAddr = resolved;
# 598 : 18 : }
# 599 : 18 : else
# 600 : 18 : LookupSubNet(request.params[0].get_str(), subNet);
# 601 : 36 :
# 602 : 36 : if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
# 603 : 3 : throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");
# 604 : 33 :
# 605 : 33 : if (strCommand == "add")
# 606 : 26 : {
# 607 : 26 : if (isSubnet ? node.banman->IsBanned(subNet) : node.banman->IsBanned(netAddr)) {
# 608 : 5 : throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
# 609 : 5 : }
# 610 : 21 :
# 611 : 21 : int64_t banTime = 0; //use standard bantime if not specified
# 612 : 21 : if (!request.params[2].isNull())
# 613 : 6 : banTime = request.params[2].get_int64();
# 614 : 21 :
# 615 : 21 : bool absolute = false;
# 616 : 21 : if (request.params[3].isTrue())
# 617 : 2 : absolute = true;
# 618 : 21 :
# 619 : 21 : if (isSubnet) {
# 620 : 14 : node.banman->Ban(subNet, banTime, absolute);
# 621 : 14 : if (node.connman) {
# 622 : 14 : node.connman->DisconnectNode(subNet);
# 623 : 14 : }
# 624 : 14 : } else {
# 625 : 7 : node.banman->Ban(netAddr, banTime, absolute);
# 626 : 7 : if (node.connman) {
# 627 : 7 : node.connman->DisconnectNode(netAddr);
# 628 : 7 : }
# 629 : 7 : }
# 630 : 21 : }
# 631 : 7 : else if(strCommand == "remove")
# 632 : 7 : {
# 633 : 7 : if (!( isSubnet ? node.banman->Unban(subNet) : node.banman->Unban(netAddr) )) {
# 634 : 1 : throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously manually banned.");
# 635 : 1 : }
# 636 : 27 : }
# 637 : 27 : return NullUniValue;
# 638 : 27 : }
# 639 : :
# 640 : : static UniValue listbanned(const JSONRPCRequest& request)
# 641 : 31 : {
# 642 : 31 : RPCHelpMan{"listbanned",
# 643 : 31 : "\nList all manually banned IPs/Subnets.\n",
# 644 : 31 : {},
# 645 : 31 : RPCResult{RPCResult::Type::ARR, "", "",
# 646 : 31 : {
# 647 : 31 : {RPCResult::Type::OBJ, "", "",
# 648 : 31 : {
# 649 : 31 : {RPCResult::Type::STR, "address", ""},
# 650 : 31 : {RPCResult::Type::NUM_TIME, "banned_until", ""},
# 651 : 31 : {RPCResult::Type::NUM_TIME, "ban_created", ""},
# 652 : 31 : }},
# 653 : 31 : }},
# 654 : 31 : RPCExamples{
# 655 : 31 : HelpExampleCli("listbanned", "")
# 656 : 31 : + HelpExampleRpc("listbanned", "")
# 657 : 31 : },
# 658 : 31 : }.Check(request);
# 659 : 31 :
# 660 : 31 : NodeContext& node = EnsureNodeContext(request.context);
# 661 : 31 : if(!node.banman) {
# 662 : 0 : throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
# 663 : 0 : }
# 664 : 31 :
# 665 : 31 : banmap_t banMap;
# 666 : 31 : node.banman->GetBanned(banMap);
# 667 : 31 :
# 668 : 31 : UniValue bannedAddresses(UniValue::VARR);
# 669 : 31 : for (const auto& entry : banMap)
# 670 : 26 : {
# 671 : 26 : const CBanEntry& banEntry = entry.second;
# 672 : 26 : UniValue rec(UniValue::VOBJ);
# 673 : 26 : rec.pushKV("address", entry.first.ToString());
# 674 : 26 : rec.pushKV("banned_until", banEntry.nBanUntil);
# 675 : 26 : rec.pushKV("ban_created", banEntry.nCreateTime);
# 676 : 26 :
# 677 : 26 : bannedAddresses.push_back(rec);
# 678 : 26 : }
# 679 : 31 :
# 680 : 31 : return bannedAddresses;
# 681 : 31 : }
# 682 : :
# 683 : : static UniValue clearbanned(const JSONRPCRequest& request)
# 684 : 16 : {
# 685 : 16 : RPCHelpMan{"clearbanned",
# 686 : 16 : "\nClear all banned IPs.\n",
# 687 : 16 : {},
# 688 : 16 : RPCResult{RPCResult::Type::NONE, "", ""},
# 689 : 16 : RPCExamples{
# 690 : 16 : HelpExampleCli("clearbanned", "")
# 691 : 16 : + HelpExampleRpc("clearbanned", "")
# 692 : 16 : },
# 693 : 16 : }.Check(request);
# 694 : 16 : NodeContext& node = EnsureNodeContext(request.context);
# 695 : 16 : if (!node.banman) {
# 696 : 0 : throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
# 697 : 0 : }
# 698 : 16 :
# 699 : 16 : node.banman->ClearBanned();
# 700 : 16 :
# 701 : 16 : return NullUniValue;
# 702 : 16 : }
# 703 : :
# 704 : : static UniValue setnetworkactive(const JSONRPCRequest& request)
# 705 : 10 : {
# 706 : 10 : RPCHelpMan{"setnetworkactive",
# 707 : 10 : "\nDisable/enable all p2p network activity.\n",
# 708 : 10 : {
# 709 : 10 : {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},
# 710 : 10 : },
# 711 : 10 : RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"},
# 712 : 10 : RPCExamples{""},
# 713 : 10 : }.Check(request);
# 714 : 10 :
# 715 : 10 : NodeContext& node = EnsureNodeContext(request.context);
# 716 : 10 : if (!node.connman) {
# 717 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
# 718 : 0 : }
# 719 : 10 :
# 720 : 10 : node.connman->SetNetworkActive(request.params[0].get_bool());
# 721 : 10 :
# 722 : 10 : return node.connman->GetNetworkActive();
# 723 : 10 : }
# 724 : :
# 725 : : static UniValue getnodeaddresses(const JSONRPCRequest& request)
# 726 : 6 : {
# 727 : 6 : RPCHelpMan{"getnodeaddresses",
# 728 : 6 : "\nReturn known addresses which can potentially be used to find new nodes in the network\n",
# 729 : 6 : {
# 730 : 6 : {"count", RPCArg::Type::NUM, /* default */ "1", "How many addresses to return. Limited to the smaller of " + ToString(ADDRMAN_GETADDR_MAX) + " or " + ToString(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses."},
# 731 : 6 : },
# 732 : 6 : RPCResult{
# 733 : 6 : RPCResult::Type::ARR, "", "",
# 734 : 6 : {
# 735 : 6 : {RPCResult::Type::OBJ, "", "",
# 736 : 6 : {
# 737 : 6 : {RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " of when the node was last seen"},
# 738 : 6 : {RPCResult::Type::NUM, "services", "The services offered"},
# 739 : 6 : {RPCResult::Type::STR, "address", "The address of the node"},
# 740 : 6 : {RPCResult::Type::NUM, "port", "The port of the node"},
# 741 : 6 : }},
# 742 : 6 : }
# 743 : 6 : },
# 744 : 6 : RPCExamples{
# 745 : 6 : HelpExampleCli("getnodeaddresses", "8")
# 746 : 6 : + HelpExampleRpc("getnodeaddresses", "8")
# 747 : 6 : },
# 748 : 6 : }.Check(request);
# 749 : 6 : NodeContext& node = EnsureNodeContext(request.context);
# 750 : 6 : if (!node.connman) {
# 751 : 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
# 752 : 0 : }
# 753 : 6 :
# 754 : 6 : int count = 1;
# 755 : 6 : if (!request.params[0].isNull()) {
# 756 : 3 : count = request.params[0].get_int();
# 757 : 3 : if (count <= 0) {
# 758 : 1 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range");
# 759 : 1 : }
# 760 : 5 : }
# 761 : 5 : // returns a shuffled list of CAddress
# 762 : 5 : std::vector<CAddress> vAddr = node.connman->GetAddresses();
# 763 : 5 : UniValue ret(UniValue::VARR);
# 764 : 5 :
# 765 : 5 : int address_return_count = std::min<int>(count, vAddr.size());
# 766 : 29 : for (int i = 0; i < address_return_count; ++i) {
# 767 : 24 : UniValue obj(UniValue::VOBJ);
# 768 : 24 : const CAddress& addr = vAddr[i];
# 769 : 24 : obj.pushKV("time", (int)addr.nTime);
# 770 : 24 : obj.pushKV("services", (uint64_t)addr.nServices);
# 771 : 24 : obj.pushKV("address", addr.ToStringIP());
# 772 : 24 : obj.pushKV("port", addr.GetPort());
# 773 : 24 : ret.push_back(obj);
# 774 : 24 : }
# 775 : 5 : return ret;
# 776 : 5 : }
# 777 : :
# 778 : : void RegisterNetRPCCommands(CRPCTable &t)
# 779 : 677 : {
# 780 : 677 : // clang-format off
# 781 : 677 : static const CRPCCommand commands[] =
# 782 : 677 : { // category name actor (function) argNames
# 783 : 677 : // --------------------- ------------------------ ----------------------- ----------
# 784 : 677 : { "network", "getconnectioncount", &getconnectioncount, {} },
# 785 : 677 : { "network", "ping", &ping, {} },
# 786 : 677 : { "network", "getpeerinfo", &getpeerinfo, {} },
# 787 : 677 : { "network", "addnode", &addnode, {"node","command"} },
# 788 : 677 : { "network", "disconnectnode", &disconnectnode, {"address", "nodeid"} },
# 789 : 677 : { "network", "getaddednodeinfo", &getaddednodeinfo, {"node"} },
# 790 : 677 : { "network", "getnettotals", &getnettotals, {} },
# 791 : 677 : { "network", "getnetworkinfo", &getnetworkinfo, {} },
# 792 : 677 : { "network", "setban", &setban, {"subnet", "command", "bantime", "absolute"} },
# 793 : 677 : { "network", "listbanned", &listbanned, {} },
# 794 : 677 : { "network", "clearbanned", &clearbanned, {} },
# 795 : 677 : { "network", "setnetworkactive", &setnetworkactive, {"state"} },
# 796 : 677 : { "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
# 797 : 677 : };
# 798 : 677 : // clang-format on
# 799 : 677 :
# 800 : 9478 : for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
# 801 : 8801 : t.appendCommand(commands[vcidx].name, &commands[vcidx]);
# 802 : 677 : }
|