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