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